我正在使用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?
答案 0 :(得分:6)
由于CWG issue 374和N3064,这在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将发出警告。