Clang和Gcc不同意实例化后的显式专业化

Clang and Gcc disagree on explicit specialization after instantiation

本文关键字:专业化 实例化 Gcc 不同意 Clang      更新时间:2023-10-16

在我正在审查的一些代码中,我遇到了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