Rio*_*pho 16 c++ gcc templates clang
我像boost一样写了一个单例模板类:
template <typename _T>
class Singleton
{
public :
static _T* Instance()
{
static _T obj;
return &obj;
}
protected :
Singleton() {}
private :
struct ObjectCreator
{
ObjectCreator()
{
Singleton<_T>::instance();
}
};
static ObjectCreator object_creator;
};
template <typename _T>
typename Singleton<_T>::ObjectCreator Singleton<_T>::object_creator;
Run Code Online (Sandbox Code Playgroud)
我写了主要功能来测试它.
#include "Singleton.h"
class A : public Singleton <A>
{
public:
int a;
};
int main()
{
A::Instance()->a = 2;
}
Run Code Online (Sandbox Code Playgroud)
我知道我错误地输入了Instance in ObjectCreator的构造函数,奇怪的是我可以通过gcc-4.4.7正确编译它,然后我使用了clang-6.0,它打了我的错字.
我猜gcc可以做一些优化,因为我没有做任何事情ObjectCreator,所以它忽略了错误代码.
我有两个问题:
Ps:我知道boost会添加一个do_nothing函数ObjectCreate并调用它Singleton<_T>:: Instance()来避免这种优化.
- 我应该怎么做才能让gcc报告错误(不改变我的代码),比如添加一些编译器标志?
你可以添加一个显式实例化template class Singleton<float>;(我只是随机选择float类型,但你可以选择更合适的东西)来强制GCC检查语法.有关示例,请参阅https://gcc.godbolt.org/z/ii43qX.
如果您只是想要检查,您还可以通过向项目添加另一个cpp文件将此显式实例放到单独的编译单元中.
然而,进行明确的实例化比隐式实例更强,因为所有成员和方法都将被实例化.此行为可能是有害的(请参阅示例的标准库).
- 如果有人对此有更可靠的解释?一些官方文件会这样做.
静态成员不会被隐式初始化,直到它以需要定义的方式使用(这与显式实例非常不同).
@StoryTeller在标准中找到了正确的段落
14.7.1隐式实例化[temp.inst]
类模板特化的隐式实例化会导致类成员函数,成员类,静态数据成员和成员模板的声明的隐式实例化,而不是定义或默认参数的隐式实例化.它会导致成员匿名联合的定义的隐式实例化.除非已显式实例化或明确专门化类模板或成员模板的成员,否则在需要成员定义存在的上下文中引用特化时,将隐式实例化成员的特化; 特别是,除非静态数据成员本身以需要静态数据成员的定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用).
编辑 您应该接受@StoryTeller的答案,因为他首先正确解释了您问题的两个方面.