模板非静态数据成员初始化程序何时实例化
When are template non-static data member initialisers instantiated?
这里有一个简短的自包含测试用例来解释我的问题。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和英特尔早就这么做了。
我很难理解标准在[ptemp.inst]p1:中说了什么
类模板专门化的隐式实例化导致类成员函数、成员类、作用域成员枚举、静态数据成员和成员模板的声明的实例化,而不是定义或默认参数的实例化;它导致了无范围成员枚举和成员匿名联合定义的隐式实例化。
因为我根本看不到非静态数据成员(带或不带初始化程序)的声明在哪里被实例化。
关于我在哪里遇到这种情况的更多细节:我试图创建一个模板助手类(在运行时永远不会创建),其中包含一个使用std::declval<T>()
初始化的成员(我应该补充一点,我现在意识到这无论如何都没有多大用处),而libstdc++对std::declval
的实现包含一个静态断言,就像我的示例中那样。通过避免std::declval
,我可以毫不费力地解决这个问题,但我想知道标准需要什么。
在试图弄清楚如何问这个问题时,我偶然发现了答案,但我认为无论如何发布都可能有用。
这是C++标准的公开问题之一,确切地说是1396号。其目的是初始化程序只在需要时被实例化:
非静态数据成员初始值设定项与成员函数和默认参数获得相同的后期解析,但它们是否也像它们一样根据需要实例化?什么时候检查它们的有效性?
2012年10月会议纪要:
CWG同意非静态数据成员初始值设定项应该像默认参数一样处理。
但这种方法仍有许多问题有待解决。在它们被解决之前,不同的编译器在不同的时间执行实例化是很自然的,需要特定行为的代码应该被重写以避免这样的要求。在我的情况下,这意味着不使用std::declval
。
- async_write完成处理程序最早何时完成?
- VCL 应用程序何时获取其应用程序>主窗体>句柄?
- 何时调用 Windows 控制台应用程序需要 CoInitialize
- 如何判断Microsoft打印到 PDF 打印机驱动程序何时完成
- c++ 终止程序的内存泄漏何时重要?
- 何时在<string>程序中包含标头?
- 应用程序的建模.何时使用哪个图表
- 模板非静态数据成员初始化程序何时实例化
- 如何检测程序运行时 Kinect 何时断开连接/拔出
- 我如何有效地清理此程序并仍然检测文件输入何时不是字母
- 何时调用 boost::asio::async_read_until 的处理程序
- 我如何接受"standard input commands",然后知道何时继续运行该程序?
- 有什么方法可以判断分叉/执行Qt应用程序的主窗口何时显示?
- 程序何时不调用 C++ 中的析构函数
- 何时对 std::shared_ptr 使用自定义删除程序
- 构造一个c++linux程序.何时分解单独的文件与单独的程序
- 生产者和消费者无限期地等待应用程序何时退出
- 检测应用程序何时在Windows中被卸载
- 智能指针如何知道何时释放程序崩溃时的资源
- 如何使用C++侦听/识别程序何时在 Windows 中运行