Sunday, June 5, 2022

[SOLVED] gcc can't take constexpr address of attribute through member pointer?

Issue

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?


Solution

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.



Answered By - user17732522
Answer Checked By - David Marino (WPSolving Volunteer)