类范围的变量模板

时间:2014-01-31 06:49:56

标签: c++ c++14 variable-templates

N3651为基础,

  

类范围内的变量模板是静态数据成员   模板

给出的例子是:

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

然而,以下所有定义都会出错:

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

是什么给出了?

2 个答案:

答案 0 :(得分:4)

编辑:committee has spoken,Clang对于静态数据成员模板需要static关键字是正确的。 14/1中给出的示例正确。希望工作草案的下一次修订将消除文本中的含糊之处。

<小时/> 这个似乎是Clang中的一个错误,但标准草案中的措辞含糊不清。我认为意图是关键字static是隐含的。如果这不是意图,可能标准的措辞更像是“​​类范围的变量模板 必须 静态数据成员模板。”而不是“类范围的变量模板 静态数据成员模板。” (N3797§14/ 1)§14/ 1中给出的(公认的非规范性)示例声明了三个类成员变量模板,没有static关键字:

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

14.5.1.3类模板的静态数据成员[temp.static] / 1 ,特别是 使用static中的示例:

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

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

所以至少不要禁止这样做。

作为@RichardSmith states in his comment,该部分的实际规范文本与该示例相矛盾。他们把Clang写成标准的文本,所以这个例子被诊断为格式错误。 The committee is aware that the wording for variable templates needs some help in various places,所以我确信在下一个草案/ C ++ 14中会有一些清理。

答案 1 :(得分:0)

如果你尝试第一个例子,clang立即咳出神奇的错误:

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?

显然,在类范围内,变量模板需要声明为static。除非你宣布constexpr,否则clang不会咳出正确的错误,这可能会产生误导。除此之外,他们的静态数据成员示例:

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

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

可能会让你失望,因为人们可能会认为变量成员模板的重点是替换静态数据成员。