6

有没有办法在编译时验证给定值是否在给定枚举的值范围内,因此有效?

enum myenum { val1 = 10, val2 = 30, val3 = 45 }

template <myenum t>
class myClass
{ ... }

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; //compiles, NOT OK!

在那里使用第二个模板非类型布尔参数将很有用,并且该布尔值的值将由元函数给出,给定值将验证该值是否在 myenum 的值内。

我查看了各种与枚举相关的问题,例如如何迭代枚举,似乎无法完成。

4

5 回答 5

5
enum myenum { val1 = 10, val2 = 30, val3 = 45 };
template<myenum e> struct is_valid_myenum { static const bool value = (e==val1 || e==val2 || e==val3); };

template<myenum t>
class myClass
{
    static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK

如果您真的非常想避免重复(并且对使用某些外部工具生成源代码不感兴趣),您可以求助于宏骇客。

#define LIST \
    ITEM(val1,10)\
    ITEM(val2,30)\
    ITEM(val3,45)

#define ITEM(NAME,VALUE) NAME = VALUE,

enum myenum { LIST };

#undef ITEM

#define ITEM(NAME,VALUE) e==NAME ||

template<myenum e> struct is_valid_myenum { static const bool value = ( LIST false ); };

template<myenum t>
class myClass
{
    static_assert(is_valid_myenum<t>::value, "t must be a valid enum value");
};

myClass<10> a; // fails, OK
myClass<val1> b; // compiles OK
myClass<myenum(24)> c; // fails, OK
于 2012-06-22T19:08:33.627 回答
2

您永远无法阻止其他开发人员自作主张。你永远不可能赢。只要确保您的 API 不会让事情变得简单

如果他取了一个无效的值,强制转换,然后传递给你,那纯粹是他的问题。这与您为他提供一个以类型指针T*作为参数的函数相同的问题,但他获取一些随机数据(任意类型),将其强制转换T*并传入。

这就是强制转换的工作原理:进行强制转换的人有责任保证被强制转换的表达式可以安全地解释为他强制转换的类型的值。

于 2012-06-22T19:07:07.537 回答
0

如果枚举的名称对您来说并不重要,也许您可​​以将其传输到数组中,例如:

const int myenum[]={10,30,45}

然后使用索引从 myenum 中引用它们。

template<unsigned int t>
class myClass
{
    static_assert(t < sizeof(myenum)/sizeof(int), "t must be a valid enum index");
    int val=myenum[t];
    ...
};
于 2012-06-22T21:21:03.087 回答
0

如果没有以元编程形式重新声明您的所有信息,这是无法做到的。但是,您可以例如执行以下操作:

enum myenum { val1 = 10, val2 = 30, val3 = 45 };
typedef vector_c< myenum, val1, val2, val3 > typed_myenum;

typedef
    contains< typed_myenum, integral_c< myenum, val >::value
    val_found;

使用来自Boost.MPL的功能,尽管实际语法可能有点偏离。

于 2012-06-22T19:06:54.277 回答
0

没有办法在运行时检查值是否在枚举的有效范围内,在编译时则更少。

检查的唯一方法是对每个值进行暴力检查。像这样的东西:

enum lala
{
  A = 10,
  B = 20,
  C = 30
};

template< int value >
struct T
{
  static_assert( (value == A) || (value == B ) || (value == C), "wrong value" );
};

int main()
{
  T< 10 > t10;
  T< 20 > t20;
  T< 25 > t25;
  T< 30 > t30;

  (void)t10;(void)t20;(void)t25;(void)t30;
}
于 2012-06-22T19:09:35.233 回答