模板在不同命名空间中的专业化 [英] Specialization of template in different namespace

查看:104
本文介绍了模板在不同命名空间中的专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用C ++的跨平台库。 MSVC编译好,但g ++给我的问题。假设我有以下Enum helper类:

  //文件:Enum.h 
#ifndef ENUM_H
#define ENUM_H

#include< map>
#include< cstring>
命名空间MyLib {

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

模板< typename类型> class Enum
{
private:
Enum(void);

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

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

}
#endif

以下是预期用途:

  // SomeFile.cpp 
#includeEnum.h

enEn MyEnum
{
value1,value2,value3,
};

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

void SomeFunc(void)
{
cout<<枚举< MyEnum> ::尺寸();
}

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

解决方案

由于 CWG issue 374 and N3064 。当前的措词(§14.7.3[temp.expl.spec] / p2)是:

lockquote

明确的特殊化应在命名空间包含
专用模板。一个明确的特殊化,其
declarator-id 不合格应在模板的最近
封闭名称空间中声明,或者如果名称空间是内联
(7.3 。

由于您的 declarator-id 实际上是事实上的使用 MyLib :: 进行限定,全局名称空间是一个封装专用模板的名称空间,这看起来像是一个GCC错误( bug 56480 )。您的代码可以通过 C ++ 11模式中的clang 进行编译。



然而,在C ++ 98中,专业化必须放在模板是其成员的命名空间内(见下面的Mark B的注释),并且如果放入C ++ 98模式


I'm developing a cross-platform library using C++. MSVC compiles fine but g++ is giving me problems. Suppose I have the following Enum helper class:

// 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

Here is the intended use:

// 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++ gives me a "Specialization of template in different namespace" error. Wrapping the DECLARE_ENUM block in namespace MyLib solves this problem. My question is why do I have to do this and is there another way of fixing this that doesn't require me to add a namespace MyLib around the block?

解决方案

This changed in C++11 as a result of CWG issue 374 and N3064. The current wording (§14.7.3 [temp.expl.spec]/p2) is:

An explicit specialization shall be declared in a namespace enclosing the specialized template. An explicit specialization whose declarator-id is not qualified shall be declared in the nearest enclosing namespace of the template, or, if the namespace is inline (7.3.1), any namespace from its enclosing namespace set.

Since your declarator-id is in fact qualified with MyLib::, and the global namespace is a "namespace enclosing the specialized template", this looks like a GCC bug (bug 56480). Your code compiles fine with clang in C++11 mode.

In C++98, however, the specialization must be put inside namespace in which the template is a member (see Mark B's comment below), and clang will produce a warning if put in C++98 mode.

这篇关于模板在不同命名空间中的专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆