我目前正在做一个项目,要求我将多个枚举汇总到一个巨大的枚举。我可以写它,但管理一个会很麻烦。我有一个想法,使用结构包围不同的枚举和模板,参数将是一个整数,例如:
template <int START>
struct first_enum
{
enum constant
{
a = START,
b, c, d
};
static constexpr int end() { return d; }
}
template <int START>
struct second_enum
{
enum constant
{
e = START,
f
};
static constexpr int end() { return f; }
}
template <int START>
struct third_enum
{
enum constant
{
g = START,
h
};
static constexpr int end() { return h; }
}
然后我有另一个继承自前面结构的结构:
struct enum_all : public first_enum<0>,
second_enum<first_enum<0>::end() + 1>,
third_enum<second_enum<first_enum<0>::end() + 1>::end() + 1> {};
这种方式enum_all
会有成员a
,b
,c
,...,h
,其值介于0 ... 7之间。
然而,写下来是非常麻烦且不可扩展(想象添加更多结构)。
我怀疑你可以使用可变参数模板来做到这一点,但我仍然是模板元编程的初学者。以下是我目前对基础案例的编制和编译。
template <int START, template<int> typename ENUM>
struct enum_all_t : public ENUM<START>
{
};
致电enum_all_t<0, first_enum>::a
会给我正确的结果。我尝试添加另一个模板专门化,但它告诉我&#34;错误:重新声明了3个模板参数&#34;。
template <int START, template <int> typename ENUM, template <int> typename... ENUMS>
struct enum_all_t : public ENUM<START>, enum_all_t<ENUM<START>::end() + 1, ENUMS> {};
答案 0 :(得分:1)
尝试在声明后添加递归结束显式声明。这应该有效:
template <int START, template <int> typename ENUM, template <int> typename... ENUMS>
struct enum_all_t : public ENUM<START>, enum_all_t<ENUM<START>::end() + 1, ENUMS...> {};
template <int START, template <int> typename ENUM>
struct enum_all_t<START, ENUM> : public ENUM<START> {};
这个想法是你必须在每个模板专业化中接受相同数量的参数。在你的例子中,你用2个args定义模板,然后用3重新定义它。在我的例子中,我用3个args定义它,然后用3个args重新定义它,但最后一个空。
答案 1 :(得分:1)
我准备了一个解决方案,但现在我发现它与Denis Sheremet的一个(+1)非常相似(地面案例和递归案例还原)。
无论如何......我建议enum_all_helper
将基本模板作为基础案例
template <int, template <int> class ...>
struct enum_all_helper
{ };
和递归专业化
template <int I, template <int> class E0, template <int> class ... Es>
struct enum_all_helper<I, E0, Es...>
: public E0<I>, public enum_all_helper<E0<I>::end()+1, Es...>
{ };
所以enum_all
可以简单地写成如下
template <template <int> class ... Es>
struct enum_all : public enum_all_helper<0, Es...>
{ };
以下是完整的编译示例
#include <type_traits>
template <int START>
struct first_enum
{
enum constant { a = START, b, c, d };
static constexpr int end() { return d; }
};
template <int START>
struct second_enum
{
enum constant { e = START, f };
static constexpr int end() { return f; }
};
template <int START>
struct third_enum
{
enum constant { g = START, h };
static constexpr int end() { return h; }
};
template <int, template <int> class ...>
struct enum_all_helper
{ };
template <int I, template <int> class E0, template <int> class ... Es>
struct enum_all_helper<I, E0, Es...>
: public E0<I>, public enum_all_helper<E0<I>::end()+1, Es...>
{ };
template <template <int> class ... Es>
struct enum_all : public enum_all_helper<0, Es...>
{ };
int main()
{
using EA = enum_all<first_enum, second_enum, third_enum>;
static_assert( std::is_base_of<first_enum<0>, EA>{}, "!" );
static_assert( std::is_base_of<second_enum<4>, EA>{}, "!" );
static_assert( std::is_base_of<third_enum<6>, EA>{}, "!" );
}