【问题标题】:Specialization of template in different namespace不同命名空间中模板的专业化
【发布时间】:2014-10-08 07:25:19
【问题描述】:

我正在使用 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++ 给了我一个“不同命名空间中模板的专业化”错误。在命名空间 MyLib 中包装 DECLARE_ENUM 块可以解决这个问题。我的问题是为什么我必须这样做,有没有另一种方法可以解决这个问题,不需要我在块周围添加命名空间 MyLib?

【问题讨论】:

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


【解决方案1】:

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

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

由于您的 declarator-id 实际上是用MyLib:: 限定的,并且全局命名空间是“包含专用模板的命名空间”,这看起来像一个 GCC 错误 (bug 56480)。您的代码使用clang in C++11 mode 编译得很好。

然而,在 C++98 中,特化必须放在模板所属的命名空间中(请参阅下面的 Mark B 评论),如果put in C++98 mode,clang 将产生警告。

【讨论】:

  • 自 C++98 以来,这似乎发生了变化,它显示为 An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.。因此,根据使用的标准将指示哪个编译器是错误的。 (OP 没有明确或通过标签指示 C++11)。
  • @MarkB 枚举器列表末尾的逗号是 C++11 的事情,不过 :) 无论如何都要澄清。
  • @MarkB 我使用的是 C++11,抱歉我之前没有指定。
猜你喜欢
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 2013-12-04
相关资源
最近更新 更多