模板非静态数据成员初始化何时实例化?

时间:2014-02-15 21:40:01

标签: c++ c++11 language-lawyer

这是一个简短的独立测试用例来解释我的问题。 GCC接受此代码,但是clang和Intel拒绝它:

template <typename T>
struct false_t {
  static const bool value = false;
};
template <typename T>
int f() {
  static_assert(false_t<T>::value, "");
  return 0;
}
template <typename T>
struct S {
  int m = f<T>();
};
int s = sizeof(S<int>);

或者,根据pmr的评论,这里有一个更简单的例子,它也被gcc接受并被clang拒绝:

struct S;
template <typename T> struct X { int x = T(); };
int s = sizeof(X<S>);

sizeof(S<int>)(或sizeof(X<S>))应该实例化它所需的类的位,但编译器不同意这些位是什么。由于非静态数据成员初始值设定项仅由构造函数使用,因此GCC将实例化作为实例化类的构造函数的一部分。 clang和英特尔早些时候这样做了。

我无法理解标准在[temp.inst] p1中所说的内容:

  

类模板特化的隐式实例化会导致隐式   实例化类成员函数,成员类,作用域成员枚举,静态数据成员和成员模板的声明,但不是定义或默认参数的实例化;它会导致隐式实例化未作用域成员枚举和成员匿名联合的定义。

因为我甚至没有看到非静态数据成员(有或没有初始化)的声明在哪里被实例化。

关于我遇到这个问题的更多细节:我试图创建一个模板助手类(永远不会在运行时创建),其中包含使用std::declval<T>()初始化的成员(我应该添加,我现在无论如何,实现都没有多大用处),libstdc ++的std::declval实现包含一个静态断言,就像我的例子中的断言一样。我可以通过避免std::declval而不费力地解决问题,但我想知道标准需要什么。

1 个答案:

答案 0 :(得分:6)

在试图弄清楚如何提出这个问题时,我偶然发现了答案,但认为无论如何都要发帖。

这是C ++标准的一个公开问题,准确地说是issue 1396。目的是初始化者只能根据需要实例化:

  

非静态数据成员初始化程序获得与成员函数和默认参数相同的后期解析,但是它们是否也像它们一样需要实例化?什么时候检查他们的有效性?

     

2012年10月会议的说明:

     

CWG同意应该像默认参数一样处理非静态数据成员初始值设定项。

但是这种方法存在很多问题仍在解决中。在它们被解决之前,不同编译器在不同时间执行实例化是很自然的,并且应该重写需要特定行为的代码以避免这种要求。就我而言,这意味着不使用std::declval