I'm trying to take the address of an object's attribute through a member pointer at compile-time. The following code compiles fine on MSVC but not on GCC:
#include <optional>
struct S {
int i = 42;
};
int main() {
constexpr S obj;
constexpr auto member = &S::i;
constexpr auto ptr = std::optional(member);
// OK
constexpr auto value = obj.*(*ptr);
static_assert(value == 42);
// Doesn't compile on gcc, can't take address through member pointer
constexpr auto & attr = obj.*(*ptr);
static_assert(attr == obj.i);
}
GCC gives the following error:
<source>:17:39: error: '(const int&)(& obj)' is not a constant expression
17 | constexpr auto & attr = obj.*(*ptr);
Here's the code on compiler explorer: https://godbolt.org/z/4WhW3qd7c
I haven't been able to find information about which compiler is wrong here. Can anyone shed some light on this?
CodePudding user response:
The result of a glvalue constant expression can only refer to an object with static storage duration.
obj
doesn't have static storage duration, because it is declared at block scope.
You can give obj
static storage duration by adding the static
keyword at block scope:
static constexpr S obj;
or by declaring it at namespace scope.