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

6 c++ language-lawyer c++11

这是一个简短的独立测试用例来解释我的问题.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>);
Run Code Online (Sandbox Code Playgroud)

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

struct S;
template <typename T> struct X { int x = T(); };
int s = sizeof(X<S>);
Run Code Online (Sandbox Code Playgroud)

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

我无法理解[temp.inst] p1中标准的含义:

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

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

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

小智 6

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

这是C++标准的公开问题之一,准确地说是问题1396.目的是初始化程序只根据需要实例化:

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

2012年10月会议记录:

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

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