2

Using N3651 as a basis,

A variable template at class scope is a static data member template.

The example given is:

struct matrix_constants {  
 template <typename T>   
  using pauli = hermitian_matrix<T, 2>;

Yet all of the following definitions give an error:

struct foo
{
    template <typename T>
    T pi = T{3.14};
};

template <typename T>
struct foo2
{
    template <typename U = T>
    U pi = U{3.14};
};

template <typename T>
struct foo3
{
    template <T>
    T pi = 42;
};

error: member 'pi' declared as a template

What gives?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • Is this necessary? As the popular disclaimer goes, ‘this is an early draft. It’s known to be incomplet and incorrekt, and it has lots of bad formatting.’ I’m not sure we want one question/answer for each mistake in the proposals and drafts. – Luc Danton Jan 31 '14 at 09:26

2 Answers2

4

EDIT: The committee has spoken, Clang is correct to require the static keyword for static data member templates. The examples given in 14/1 are not correct. Hopefully, the next revision of the working draft will remove the ambiguity from the text.


This seems to be a bug in Clang, but the wording in the draft standard is ambiguous. I believe the intention is that the keyword static is implicit. If that was not the intention, presumably the standard wording would be more along the lines of "A variable template at class scope must be a static data member template." instead of "A variable template at class scope is a static data member template." (N3797 §14/1) The (admittedly non-normative) example given in §14/1 declares three class member variable templates, none with the static keyword:
struct matrix_constants {
  template<class T>
   using pauli = hermitian_matrix<T, 2>;
  template<class T>
   constexpr pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };
  template<class T>
   constexpr pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } };
  template<class T>
   constexpr pauli<T> sigma3 = { { 1, 0 }, { -1, 0 } };
};

The example in 14.5.1.3 Static data members of class templates [temp.static]/1 notably does use static:

struct limits {
  template<class T>
    static const T min; // declaration
};

template<class T>
  const T limits::min = { }; // definition

so at the very least it's not forbidden to do so.

As @RichardSmith states in his comment, the actual normative text of the section contradicts the example. They write Clang to the text of the standard, so the example is diagnosed as ill-formed. The committee is aware that the wording for variable templates needs some help in various places, so I'm sure there will be some cleanup in the next draft / C++14.

Community
  • 1
  • 1
Casey
  • 41,449
  • 7
  • 95
  • 125
  • 2
    I don't think this is clear. 14/1 also says "A declaration introduced by a template declaration of a variable is a variable template." and `T pi = T{3.14};` is a declaration of a non-static data member, not of a variable. So either the normative text is wrong or the example is. – Richard Smith Feb 05 '14 at 20:59
  • @RichardSmith I agree that the wording is at best ambiguous and at worst contradictory in places. I was interpreting the examples as normative, since the wording is usually a bit suspect for features upon first integration. I had intended to follow up on this answer and file a bug report after reading through the variable template proposals for clarification, but I was distracted. I'll clarify the answer. – Casey Feb 05 '14 at 22:14
  • 3
    After discussion on the WG21 core reflector, we've decided that the `static` keyword should be required here, and it is the example that is incorrect. – Richard Smith Feb 06 '14 at 07:26
0

If you try the first example, clang coughs up the magic error right away:

template <typename T, size_t N>
struct hermitian_matrix { };

struct foo
{
    template <typename T>
    using pauli = hermitian_matrix<T, 2>;

    template <typename T>
    constexpr pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };
};

error: non-static data member cannot be constexpr; did you intend to make it static?

Apparently at class scope, variable templates need to be declared static. clang doesn't cough up the right error unless you declare it constexpr, which can be misleading. As well as that, their example of a static data member:

struct foo
{
    template <typename T>
    static T bar;
};

template <typename T>
T foo::bar = T{3.14};

may throw you off because one might think that the whole point of variable member templates is to replace static data members.