2

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

是什么赋予了?

4

2 回答 2

4

编辑:委员会已经说过static,Clang 要求静态数据成员模板的关键字是正确的。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 在他的评论中所说,该部分的实际规范文本与示例相矛盾。他们将 Clang 写入标准的文本,因此该示例被诊断为格式错误。委员会知道变量模板的措辞在各个地方都需要一些帮助,所以我确信在下一个草案/C++14 中会有一些清理。

于 2014-01-31T14:20:20.033 回答
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?

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

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

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

可能会让你失望,因为人们可能认为变量成员模板的全部意义在于替换静态数据成员。

于 2014-01-31T06:49:56.213 回答