【发布时间】:2013-09-25 04:45:15
【问题描述】:
我有一个相当简单的变体类,它支持一组预定义的类型,并提供一个枚举来指示哪些可用类型当前处于活动状态。像这样的:
class variant
{
enum class type { integer, real, string, etc };
type active_type() const;
/* ... */
};
我想将类制作成模板,其中支持的类型作为模板参数提供:
template <typename... T>
class variant
{
const std::type_info& active_type() const; // logical, but can't switch on it
/* ... */
};
我依赖于捕获错误的一个关键特性是我可以在活动类型上switch,如果任何可能的情况被遗漏,编译器会发出警告。使用上述设计(也不使用boost::variant)是不可能的。
我的问题是,有没有什么方法可以自动生成一个枚举数与参数包中的参数数相同的枚举?
枚举的实际名称/值无关紧要,因为它们可以隐藏在用于将类型映射到正确枚举的 constexpr 函数后面。我可以想象这样的最终用法:
template <typename... T>
class variant
{
enum class type { T... }; // magic here
// specializations provided to map T into type (for use in case labels)
template <typename T>
static constexpr type type_enum();
type active_type() const;
/* ... */
};
typedef variant<int, float, std::string> myvar;
myvar var;
switch (var.active_type())
{
case myvar::type_enum<int>(): // static constexpr function
...
break;
case myvar::type_enum<float>():
...
break;
} // warning: enumeration for string not handled in switch
【问题讨论】:
-
不得不
switch依赖于变量类型几乎是从来没有一个好的设计。继承和虚函数通常是合适的替代品。 -
这似乎是the XY problem 的一个示例,您有一个不起作用的解决方案,需要帮助。但是对于您尝试解决的实际问题,可能有不止一种解决方案。描述您想要完成的事情(连同您尝试过的事情)通常会产生更好的答案。
-
@JoachimPileborg 当然,几乎永远不会。但在必要的情况下,最好有一个通用的变体模板来减轻痛苦。我不是在尝试用变体解决问题,而是在尝试编写一个健壮的类,以最大程度地减少变体是正确解决方案时的痛苦。
-
@Troy 感谢特洛伊。不幸的是,
boost::any遇到了与我的第二个版本相同的问题。它只给你一个std::type_info,这意味着要进行级联的if/else比较而不是switch——所以编译器仍然无法诊断遗漏的案例。