不同命名空间中模板的专业化

时间:2014-08-14 15:10:03

标签: c++ templates ubuntu c++11 g++

我正在使用C ++开发跨平台库。 MSVC编译得很好,但g ++给我带来了麻烦。假设我有以下Enum助手类:

// File: Enum.h
#ifndef ENUM_H
#define ENUM_H

#include <map>
#include <cstring>
namespace MyLib {

#define DECLARE_ENUM( type ) template<> std::map<const char*, type>  \
            MyLib::Enum<type>::mMap = std::map<const char*, type>(); \
            template<> MyLib::Enum<type>::Enum (void)

template <typename Type> class Enum
{
private:
    Enum (void);

public:
    static int Size (void) { /* ... */ return 0; }

private:
    static std::map<const char*, Type> mMap;
};

}
#endif

以下是预期用途:

// SomeFile.cpp
#include "Enum.h"

enum MyEnum
{
    value1, value2, value3,
};

DECLARE_ENUM (MyEnum)
{
    mMap["value1"] = value1;
    mMap["value2"] = value2;
    mMap["value3"] = value3;
}

void SomeFunc (void)
{
    cout << Enum<MyEnum>::Size();
}

g ++给了我一个&#34;模板在不同名称空间中的专业化&#34;错误。在命名空间MyLib中包装DECLARE_ENUM块可以解决此问题。我的问题是为什么我必须这样做,是否有另一种解决方法,并不要求我在块周围添加名称空间MyLib?

1 个答案:

答案 0 :(得分:6)

由于CWG issue 374N3064,这在C ++ 11中发生了变化。目前的措辞(§14.7.3[temp.expl.spec] / p2)是:

  

应在包含的名称空间中声明显式特化   专业模板。一个明确的专业化    declarator-id 不合格,应在最近的声明   封闭模板的命名空间,或者,如果命名空间是内联的   (7.3.1),来自其封闭命名空间集的任何命名空间。

由于你的 declarator-id 实际上是用MyLib::限定的,并且全局命名空间是一个“包含专用模板的命名空间”,这看起来像一个GCC错误({{3 }})。您的代码可以使用bug 56480编译好。

但是,在C ++ 98中,必须将特化放在模板所属的命名空间内(参见下面的Mark B的注释),如果clang in C++11 mode,则clang将发出警告。