我正在尝试编写一个宏来帮助构建enum class具有各种帮助函数的宏,例如用于转换为字符串。在某种集合中提供对枚举的所有值的访问是很自然的:
DEFINE_ENUM(Foo, Value1, Value2);
for (Foo v : enum_traits<Foo>::all_values) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
这似乎可以通过使DEFINE_ENUM()宏专门化一个公共enum_traits类来实现:
// globally:
template<typename T> struct enum_traits {};
// inside the macro:
#define DEFINE_ENUM(Name, ...) \
/* define "enum class Name" ... */ \
template<> struct my_enum_traits<Name> { \
/* define all_values member */ \
};
Run Code Online (Sandbox Code Playgroud)
但是,如果扩展DEFINE_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> { /* ... */ };
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以实现这一点,即让宏“转义”包含其调用的命名空间,并从不同的命名空间(甚至全局命名空间)专门化一个模板?
好吧,我无法直接帮助解决这个特征模板专业化问题,我怀疑这是不可能的。
但通过ADL实现您的真正目标是可能的
看窍门:
// globally:
template<typename T>
using enum_traits = decltype(get_enum_traits(T{}));
Run Code Online (Sandbox Code Playgroud)
诀窍是get_enum_traits在 的命名空间中定义函数T。该函数应具有返回类型 - 该类型应该是您的特征。此函数不需要实现 - 它只是从新定义的枚举类型的命名空间中获取类型的 ADL 方法。
// 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);
Run Code Online (Sandbox Code Playgroud)
一些演示表明它确实有效。
#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)
{}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
280 次 |
| 最近记录: |