Search code examples
c++templatesc++14autovariable-templates

Variable template in template class - unexpected error (possible bug?)


Having:

struct Value
{
    template<class T>
    static constexpr T value{0};
};

(0) ideone

template<typename TValue>
struct Something
{
    void x()
    {
        static_assert(TValue::template value<int> == 0, "");
    }
};

int main() { Something<Value>{}.x(); return 0; } 
  • Does not compile with clang++ 3.6.

    error: cannot refer to variable template 'value' without a template argument list

  • Does not compile with g++ 5.2.

    error: ‘template constexpr const T Value::value’ is not a function template


(1) ideone

Compiles with both clang++ and g++.

struct Something
{
    void x()
    {
        static_assert(Value::template value<int> == 0, "");
    }
};

int main() { Something{}.x(); return 0; } 

Why does (0) fail to compile?

It seems that the issue occurs if the variable template is accessed through a template parameter (in this case, TValue). Defining a type alias for TValue or using the typename keyword does not fix the issue.

What's going on here?


Solution

  • This is definitely a gcc and clang bug in their treatment of variable templates as dependent names. I submitted gcc 67248 and clang 24473.

    As a workaround for now, both compilers support the old way of doing variable templates, namely if you added:

    struct Value
    {
        template<class T>
        static constexpr T value = 0;
    
        template <typename T>
        struct variable_template_ish {
            static constexpr T value = Value::value<T>;
        };
    };
    

    then the following compiles:

    template<typename TValue>
    struct Something
    {
        void foo() {
            static_assert(TValue::template variable_template_ish<int>::value == 0, "");
        }
    };
    
    int main() { 
        Something<Value>{}.foo();
    }