实例化后,Clang和Gcc在显式专业化上意见不一致

时间:2019-05-28 23:09:31

标签: c++ templates gcc clang iso

在某些代码中,我正在审查我遇到Clang和Gcc意见不同的情况。环顾了一会后,我似乎无法弄清楚谁是对的。

免责声明 :我知道有一个更好的Singleton模式,但这是代码中使用的模式。

注释:

  • 在Ubuntu上的gcc 7.4.0(无错误)

  • Ubuntu上的
  • clang 6.0.0(抛出错误)

  • 对于所有C ++ 11后的ISO版本似乎都存在差异,但是我没有更早尝试过。

foo.hh

#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(){};

sing.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

2 个答案:

答案 0 :(得分:2)

两个编译器在技术上都不是错误的。该代码无效,但是不需要C ++实现来提供有关此类错误的诊断消息。

标准[temp.expl.spec]/6说(强调我):

  

如果一个模板,一个成员模板或一个类模板的成员是显式专门化的,则应在首次使用该专门化之前声明该专门化,这将导致在每个此类翻译单元中进行隐式实例化发生使用; 不需要诊断

您可以通过在sing.hh中定义singleton之后立即声明显式专门化来解决此问题:

struct Foo;
template<> singleton<Foo>::GetInstance singleton<Foo>::instance;

或者,如果您希望所有专业化都初始化为空指针,则可以只在sing.hh中定义通用类模板的成员。则不需要显式的专业化,除非您希望某些特定类型使用不同的初始化器。

template<typename T>
typename singleton<T>::GetInstance singleton<T>::instance = nullptr;

答案 1 :(得分:0)

从此答案here和cpp引用here开始。

  

显式专业化可以在任何主要专业化范围内声明   可以定义模板。[...]

     

显式专业化必须出现在非专业化之后   模板声明。

     

必须在第一次使用之前声明专业化   隐式实例化,在每个这样使用的翻译单元中   发生

如果显式专业化位于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