19

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?

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 1
    What is `template static constexpr T value{0};` supposed to do? Is it something new? How is that called? – BЈовић Aug 17 '15 at 12:21
  • 4
    @BЈовић, It is called *variable template*, added in C++14. See [this](https://en.wikipedia.org/wiki/C%2B%2B14#Variable_templates) (wiki) and [this](http://en.cppreference.com/w/cpp/language/variable_template) (cppreference) – Nawaz Aug 17 '15 at 12:22
  • 2
    (0) fails for me on clang 3.6, with "cannot refer to variable template '`value`' without a template argument list" – Barry Aug 17 '15 at 12:28
  • I edited the original question: `auto` was not part of the issue - for some reason ClangComplete (Sublime Text plugin) did not display errors when `int` was used in place of `auto`. The issue regards the fact that `TValue` is a template parameter of `Something`. – Vittorio Romeo Aug 17 '15 at 12:43

2 Answers2

10

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();
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    I *knew* it was a bug. Strange that both gcc and clang got it wrong, though. The workaround I used was actually defining `static constexpr` functions that wrapped the variables. – Vittorio Romeo Aug 17 '15 at 12:59
0

I've had some headaches before when creating template class header files in c++.

Make sure you implementation of static constexpr T value{0}; is in the same header file as the declaration.

Max Bilbow
  • 110
  • 7