Clang和Gcc不同意实例化后的显式专业化
Clang and Gcc disagree on explicit specialization after instantiation
在我正在审查的一些代码中,我遇到了Clang和Gcc不同意的情况。环顾四周一会儿后,我似乎无法弄清楚谁是对的。
免责声明 :我知道有一个更好的单例模式,但这是代码中使用的模式。
笔记:
-
Ubuntu 上的 gcc 7.4.0(无错误)
-
Ubuntu 上的 clang 6.0.0 (抛出错误)
-
所有 C++11 后 ISO 版本似乎都存在差异,但我之前没有尝试。
噗
#include "sing.hh"
class Foo {
public:
Foo();
~Foo();
static Foo *getSingleton(){
return singleton<Foo>::instance();
}
};
foo.cc
include "foo.hh"
//removing this line results in the error for clang disappearing
template<> singleton<Foo>::GetInstance singleton<Foo>::instance = nullptr;
int main(){};
唱.hh
template<typename T>
class singleton{
typedef T *(*GetInstance)(void);
public:
static GetInstance instance;
};
结果:
$ clang++ foo.cc
foo.cc:3:56: error: explicit specialization of 'instance' after instantiation
template<> singleton<Foo>::GetInstance singleton<Foo>::instance = nullptr;
^
./foo.hh:10:32: note: implicit instantiation first required here
return singleton<Foo>::instance();
^
1 error generated.
$ g++ foo.cc <- No Errors
这两个编译器在技术上都没有错。代码无效,但C++实现不需要提供有关此类错误的诊断消息。
标准 [temp.expl.spec]/6 说(强调我的):
如果模板、成员模板或类模板的成员明确专用化,则应在首次使用该专用化之前声明该专用化,这将导致隐式实例化发生,在发生这种使用的每个翻译单元中;无需诊断。
您可以通过在 sing.hh 中定义singleton
后立即声明显式专用化来解决此问题:
struct Foo;
template<> singleton<Foo>::GetInstance singleton<Foo>::instance;
或者,如果您希望所有专用化初始化为 null 指针,则可以只定义通用类模板的成员,也可能在 sing.hh 中定义。 然后,就不需要显式专用化,除非您希望为某些特定类型使用不同的初始值设定项。
template<typename T>
typename singleton<T>::GetInstance singleton<T>::instance = nullptr;
从这个答案这里和 cpp 参考这里。
明确的专业化可以在其主要范围的任何范围内声明 可以定义模板 [...]。
明确的专业化必须出现在非专业化之后 模板声明。
必须在第一次使用之前声明专业化,这会导致 隐式实例化,在每个使用此类的翻译单元中 发生
如果显式专用化在sing.cpp
文件中,则两个编译器都不会抱怨。或者,您可以使用前向声明执行以下操作,clang 和 gcc 都会很高兴。
#include <iostream>
template<typename T>
struct singleton
{
typedef T *(*GetInstance)(void);
static GetInstance instance;
};
template<>
singleton<struct Foo>::GetInstance singleton<struct Foo>::instance = nullptr;
struct Foo
{
static Foo *getSingleton()
{
return singleton<Foo>::instance();
}
};
int main()
{
}
在线代码示例:https://rextester.com/SPZLS83155
- 从C++实例化QML
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 约束和显式模板实例化
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 在C 中,当我对其进行专业化时会实例化模板
- Clang和Gcc不同意实例化后的显式专业化
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 了解类模板专业化示例的隐式实例化
- 实例化和专业化的定义是相互依赖的
- 明确的专业化;'std::hash<_Kty>' 已被实例化
- 模板功能实例化和专业化
- 实例化错误后成员函数模板的专业化,以及成员函数的顺序
- 将专业化定义为另一个类的实例化
- 专业化的隐式实例化
- 实例化错误后如何避免专业化
- 为什么模板专业化中的显式实例化会给我带来错误