Krupip
Krupip

Reputation: 4902

How do I get MSVC to see static constexpr member variables and functions at compile time in c++20?

Background

I'm attempting to get access to a constexpr variable at compile time within a CRTP class. Below is a MVCE of this.

template <class T>
struct CRTP {
    static constexpr int get_value() { 
        return T::value ; 
    }

    static constexpr int crtp_value = get_value();
};

struct Derived: CRTP<Derived> {
     static constexpr int value = 2;
};

int main() {
    static_assert(Derived::crtp_value == 2, "Should result in 2");
    return 0; 
}

I can't however run this on MSVC. Am I doing something I shouldn't be doing here? This works in other compilers, see godbolt links:

MSVC claims:

example.cpp
<source>(3): error C2039: 'value': is not a member of 'Derived'
<source>(7): note: see declaration of 'Derived'
<source>(3): note: the template instantiation context (the oldest one first) is
<source>(7): note: see reference to class template instantiation 'CRTP<Derived>' being compiled
<source>(3): note: while compiling class template member function 'int CRTP<Derived>::get_value(void)'
<source>(3): error C2065: 'value': undeclared identifier
<source>(4): error C3615: constexpr function 'CRTP<Derived>::get_value' cannot result in a constant expression
<source>(3): note: failure was caused by control reaching the end of a constexpr function
<source>(12): error C2131: expression did not evaluate to a constant
<source>(12): note: failure was caused by a read of an uninitialized symbol
<source>(12): note: see usage of 'crtp_value'
Compiler returned: 2

which I cannot make heads or tails of.

Question

How do I get accessing static constexpr member variables or member functions from the derived class in CRTP to work in MSVC?

Upvotes: 3

Views: 132

Answers (1)

catnip
catnip

Reputation: 25408

This seems to work:

template <class T>
struct CRTP {
    static const int crtp_value;
};
 
template <class T> const int CRTP <T>::crtp_value = T::value;
 
struct Derived : CRTP <Derived> {
    static constexpr int value = 2;
};
 
int main() {
    static_assert(Derived::value == 2, "Should result in 2");
}

Shouldn't be necessary, but hey.

Godbolt

Upvotes: 1

Related Questions