Search code examples
c++templatesmetaprogramming

Partially specialized template static constexpr in template class


(A toy, minimal not-working example)

The next code won't compile with cpp20/17:

template<typename TSomeTemplate>
struct A
{
    static constexpr size_t B = 1;

    template<typename T, typename... Ts>
    static constexpr size_t C = 4;

    template<typename T>
    static constexpr size_t C<T> = B;
};

int main()
{
    A<int>::C<int>;

    return 0;
}

With the error of "Expression did not evaluate to constant" regarding the last line in the struct. However, it does compile with full specialization, or without referencing B:

template<typename TSomeTemplate>
struct Works
{
    static constexpr size_t B = 1;

    template<typename T, typename... Ts>
    static constexpr size_t C = 4;

    template<>
    static constexpr size_t C<int> = B;
};

template<typename TSomeTemplate>
struct AlsoWorks
{
    static constexpr size_t B = 1;

    template<typename T, typename... Ts>
    static constexpr size_t C = 4;

    template<typename T>
    static constexpr size_t C<T> = 2;
};

Why is it so? How can I make the first struct work?


Solution

  • GCC and MSVC are wrong in rejecting the code as the program is well-formed.

    B is a constant expression and can be used as an initializer when initializing C during its partial specialization. This is a msvc bug reported here as:

    MSVC rejects valid code when using constexpr static data member as initializer.


    Moreover, we are allowed to provide a partial specialization for C(as you did). This is a gcc bug reported as:

    GCC rejects valid code involving partial specialization of variable template.