【问题标题】:Variable template at class scope类范围内的变量模板
【发布时间】:2014-01-31 06:49:56
【问题描述】:

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

什么给了?

【问题讨论】:

  • 这有必要吗?正如流行的免责声明所说,“这是一个早期的草案。众所周知,它是不完整和不正确的,而且它有很多错误的格式。我不确定我们是否需要为提案和草稿中的每个错误提供一个问题/答案。

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


【解决方案1】:

编辑: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 中会有一些清理。

【讨论】:

  • 我认为这不是很清楚。 14/1 还说“由变量的模板声明引入的声明是变量模板。” T pi = T{3.14}; 是非静态数据成员的声明,而不是变量的声明。因此,要么规范文本是错误的,要么示例是错误的。
  • @RichardSmith 我同意措辞充其量是模棱两可的,最坏的情况是在某些地方自相矛盾。我将这些示例解释为规范性的,因为在第一次集成时,措辞通常有点怀疑功能。我本来打算跟进这个答案并在阅读变量模板提案以进行澄清后提交错误报告,但我分心了。我会澄清答案。
  • 经过对WG21核心反射器的讨论,我们决定这里应该需要static关键字,是示例不正确。
【解决方案2】:

如果您尝试第一个示例,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};

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

【讨论】:

    猜你喜欢
    • 2017-03-16
    • 1970-01-01
    • 2016-11-25
    • 1970-01-01
    • 2014-06-27
    • 2017-05-22
    • 1970-01-01
    • 2016-11-06
    相关资源
    最近更新 更多