c++ - 在另一个命名空间中定义一个符号

标签 c++ templates namespaces

这是我的问题:在标题中我定义了一个结构模板 type_to_string , 旨在定义与给定类型参数对应的字符串:

namespace foo {

    template <typename T>
    struct type_to_string
    {
        static const char * value;
    };
}

template <typename T>
const char * foo::type_to_string<T>::value = "???";

我还为字符串定义了一个默认值。

现在,我想使用宏来定义新类型:

#define CREATE_ID(name)                               \
struct name;                                          \
                                                      \
template<>                                            \
const char * foo::type_to_string<name>::value = #name;

问题是我希望宏可以在 namespace 中使用,如:

namespace bar
{
    CREATE_ID(baz)
}

这是不可能的,因为 type_to_string<T>::value必须在包含 foo 的命名空间中定义.

这是我得到的编译错误:

[COMEAU 4.3.10.1] error: member "foo::type_to_string<T>::value [with T=bar::baz]"
cannot be specialized in the current scope

[VISUAL C++ 2008] error C2888: 'const char *foo::type_to_string<T>::value' :
symbol cannot be defined within namespace 'bar'
     with
     [
         T=bar::baz
     ]

奇怪的是,GCC 4.3.5(MinGW 版本)没有产生任何错误。

有没有人知道解决这个问题的方法,也许是通过使用一些我不知道的查找规则(即在宏中声明 type_to_string 以便每个命名空间都有自己的版本,或类似的东西)?

最佳答案

根据 C++ 标准 14.7.3/2:

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. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member. Such a declaration may also be a definition. If the declaration is not a definition, the specialization may be defined later in the name- space in which the explicit specialization was declared, or in a namespace that encloses the one in which the explicit specialization was declared.

你可以这样写:

#define DECL_ID(name) \
struct name;                                          

#define CREATE_ID(name) \
template<>              \
const char * foo::type_to_string<name>::value = #name;

namespace bar { namespace bar2 {
    DECL_ID(baz)
} }
CREATE_ID(bar::bar2::baz)

或者

#define CREATE_ID(ns, name)     \
namespace ns { struct name; }   \
                                \
template<>                      \
const char * foo::type_to_string<ns::name>::value = #name;

CREATE_ID(bar, baz)

第三个选项是前两个的叠加。它允许在 value 中使用非限定名称(如果需要):

#define DECL_ID(name) \
struct name;                                          

#define CREATE_ID(ns, name) \
template<>              \
const char * foo::type_to_string<ns::name>::value = #name;

namespace bar { namespace bar2 {
    DECL_ID(baz)
} }
CREATE_ID(bar::bar2, baz)

关于c++ - 在另一个命名空间中定义一个符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1470654/

相关文章:

Javascript命名空间污染问题

c++ - 没有这样的运算符 "[]"匹配这些操作数

c++ - 绕行函数在 printf 上崩溃

c++ - 指向模板函数的函数指针

javascript - 将 html 元素的值作为 ember 中的参数传递

c++ - 模板特化是扩展还是覆盖通用模板?

xml - XQuery 属性中具有不同 namespace 的 XML 文件 (epub :type)

c++命名空间使用和命名规则

c++ - 是否可以定义一个队列列表,其中每个队列可以是不同类型的?

C++/Arduino 将函数作为参数传递