模板类中的变量模板-意外错误(可能的错误?)

问题描述:

具有:

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; } 

  • 不使用clang ++ 3.6进行编译.

    • Does not compile with clang++ 3.6.

      错误:如果没有模板参数列表,就无法引用变量模板'value'

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

    • 无法使用g ++ 5.2进行编译.

    • Does not compile with g++ 5.2.

      错误:"template constexpr const T Value :: value"不是函数模板

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

    • (1) ideone

      使用clang ++和g ++进行编译.

      Compiles with both clang++ and g++.

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


    为什么(0)无法编译?


    Why does (0) fail to compile?

    如果通过模板参数(在本例中为TValue)访问变量模板,似乎会出现此问题.为TValue定义类型别名或使用typename关键字不能解决该问题.

    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.

    这是怎么回事?

在将变量模板视为从属名称时,这肯定是gcc和clang错误.我提交了 gcc 67248

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>;
    };
};

然后执行以下编译:

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

int main() { 
    Something<Value>{}.foo();
}