C++ 声明是否可以转义其封闭的命名空间?
我正在尝试编写一个宏来帮助构建一个带有各种辅助函数的C++ 声明是否可以转义其封闭的命名空间?,c++,namespaces,C++,Namespaces,我正在尝试编写一个宏来帮助构建一个带有各种辅助函数的enum类,例如用于转换为字符串。在某种集合中提供对枚举的所有值的访问是很自然的: DEFINE_ENUM(Foo, Value1, Value2); for (Foo v : enum_traits<Foo>::all_values) { // ... } 但是,如果扩展定义_ENUM(Foo,Value1,Value2)发生在命名空间内部,则它似乎不可能从该命名空间外部专门化模板: template<typen
enum类
,例如用于转换为字符串。在某种集合中提供对枚举的所有值的访问是很自然的:
DEFINE_ENUM(Foo, Value1, Value2);
for (Foo v : enum_traits<Foo>::all_values) {
// ...
}
但是,如果扩展定义_ENUM(Foo,Value1,Value2)
发生在命名空间内部,则它似乎不可能从该命名空间外部专门化模板:
template<typename T> struct enum_traits {};
namespace foo {
// imagine DEFINE_ENUM is invoked here:
enum class Foo { Value1, Value2 };
// error: class template specialization of 'enum_traits'
// must occur at global scope
template<> struct ::enum_traits<Foo> { /* ... */ };
}
template struct enum_traits{};
名称空间foo{
//假设在此处调用DEFINE_ENUM:
枚举类Foo{Value1,Value2};
//错误:“enum\u traits”的类模板专门化
//必须在全局范围内发生
模板结构::枚举特征{/*…*/};
}
是否有任何方法可以实现这一点,即宏“转义”包含其调用的名称空间,并从不同的名称空间(甚至全局名称空间)专门化模板?嗯,我无法直接帮助解决此模板专门化问题,我怀疑这是不可能的 但是,你可以通过以下方式实现你的真正目标: 看看窍门:
// globally:
template<typename T>
using enum_traits = decltype(get_enum_traits(T{}));
有些人认为它真的有效
#include <array>
// globally:
template<typename T>
using enum_traits = decltype(get_enum_traits(T{}));
// inside the macro:
#define DEFINE_ENUM(Name, ...) \
/* define "enum class Name" ... */ \
enum class Name { __VA_ARGS__ }; \
struct Name##_type_traits { \
static constexpr std::array<Name,1> values{{ Name{} }}; \
}; \
Name##_type_traits get_enum_traits(Name); // does not need implementation
namespace foo {
DEFINE_ENUM(Foo, Value1, Value2);
}
int main( ) {
for (auto e: enum_traits<foo::Foo>::values)
{}
}
#包括
//全球:
模板
使用enum_traits=decltype(get_enum_traits(T{}));
//在宏内部:
#定义枚举(名称,…)\
/*定义“枚举类名”…*/\
枚举类名{{uuu VA_ARGS}\
结构名称###(u类型){\
静态constexpr std::数组值{{Name{}}\
}; \
名称###类型(特征获取)枚举(名称)//不需要执行
名称空间foo{
定义_ENUM(Foo,Value1,Value2);
}
int main(){
用于(自动e:enum_traits::value)
{}
}
您可以通过在名称空间中定义,比如说,struct Name###Traits
来避免本地类,并让get_enum_Traits(Name)
只需返回它即可。@aschepler这是真的。可能是更好的解决方案。当您在for循环@Drew中实际使用e
时,这似乎会导致链接器错误。这是因为您使用C++11,而constexpr变量在默认情况下不像在C++17中那样是内联的。但这个问题与OP问题无关。
// inside the macro:
#define DEFINE_ENUM(Name, ...) \
/* define "enum class Name" ... */ \
enum class Name { __VA_ARGS__ }; \
struct Name##_type_traits { \
/* define all_values member */ \
}; \
Name##_type_traits get_enum_traits(Name);
#include <array>
// globally:
template<typename T>
using enum_traits = decltype(get_enum_traits(T{}));
// inside the macro:
#define DEFINE_ENUM(Name, ...) \
/* define "enum class Name" ... */ \
enum class Name { __VA_ARGS__ }; \
struct Name##_type_traits { \
static constexpr std::array<Name,1> values{{ Name{} }}; \
}; \
Name##_type_traits get_enum_traits(Name); // does not need implementation
namespace foo {
DEFINE_ENUM(Foo, Value1, Value2);
}
int main( ) {
for (auto e: enum_traits<foo::Foo>::values)
{}
}