C++ 检查枚举值范围的快速方法
是否有一种synatx古怪的快速/单行方式允许您检查枚举是否具有指定的值 例如:C++ 检查枚举值范围的快速方法,c++,enums,C++,Enums,是否有一种synatx古怪的快速/单行方式允许您检查枚举是否具有指定的值 例如: enum fruit_and_vegetables { apples, pears, tomatoes, cucumbers } int main() { fruit_and_vegetables something = apples; if( something = {apples, pears} ) // <-- this here cou
enum fruit_and_vegetables
{
apples,
pears,
tomatoes,
cucumbers
}
int main()
{
fruit_and_vegetables something = apples;
if( something = {apples, pears} ) // <-- this here
cout << "something is fruit." << endl;
else
cout "something is a vegetable." << endl;
return 0;
}
列举水果和蔬菜
{
苹果,
梨,
西红柿,
黄瓜
}
int main()
{
水果和蔬菜某物=苹果;
if(something={apples,pears})/if(something
我不知道,但您可以做的是将值2^I
分配给枚举成员。例如:
enum fruit_and_vegetables
{
apples = (1<<0),
pears = (1<<1),
tomatoes = (1<<2),
cucumbers = (1<<3)
// ...
}
列举水果和蔬菜
{
苹果=(1还有另一种方法扩展了@bitmask的答案:
假设您可以检查固定数量的条件。因此,您可以使用额外的LUT,而不是对水果和蔬菜枚举的值使用位掩码(这将限制您的单词大小):
enum fruit_and_vegetables {
apples = 0,
pears,
tomatoes,
cucumbers
}
enum qualifs {
is_fruit = 1,
is_sweet = 1<<1,
is_round = 1<<2,
is_tasty = 1<<3
}
const qualifs qualifs_LUT[] = { // can be generated
is_fruit | is_sweet | is_round, // apple
...
};
<强>编辑< /强>:另一个有趣的方法。考虑(再次)@位掩码:方法。它依赖于2的幂。但是素数如何?它们生长得慢得多,因此,通过将素数分配给枚举值,可以假定更多的值,假设产品不会溢出:
enum fruit_and_vegetables {
apples = 2,
pears = 3,
tomatoes = 5,
cucumbers = 7
}
if ((apples * pears * tomatoes) % tomatoes == 0)
printf("it's tasty!");
此选项限制了控件集中的项目数。您可以编写帮助器模板,帮助您实现所需的语法:
enum fruit_and_vegetables
{
nothing,
apples,
pears,
tomatoes,
cucumbers
};
// helper template
typedef fruit_and_vegetables fav;
template<fav v1 = nothing, fav v2 = nothing, fav v3 = nothing, fav v4 = nothing,
fav v5 = nothing, fav v6 = nothing, fav v7 = nothing, fav v8 = nothing>
bool check_equal( fruit_and_vegetables value )
{
return ( value == v1 || value == v2 || value == v3 || value == v4 ||
value == v5 || value == v6 || value == v7 || value == v8 );
}
// usage
int main()
{
fruit_and_vegetables something = apples;
if( check_equal<apples, pears>(something) )
std::cout << "something is fruit." << std::endl;
else
std::cout << "something is a vegetable." << std::endl;
return 0;
}
列举水果和蔬菜
{
没有什么,
苹果,
梨,
西红柿,
黄瓜
};
//辅助模板
typedef水果和蔬菜fav;
模板
布尔检查(水果和蔬菜价值)
{
返回值(value==v1 | | value==v2 | | value==v3 | | value==v4||
值==v5 | |值==v6 | |值==v7 | |值==v8);
}
//用法
int main()
{
水果和蔬菜某物=苹果;
如果(检查是否等于(某物))
std::cout处理较大的未分类产品集:
enum fruit_and_vegetables
{
apples,
pears,
tomatoes,
cucumbers,
MAX_VALUE
};
vector<bool> arguablyVegetables(MAX_VALUE, false);
arguablyVegetables[tomatoes] = true;
arguablyVegetables[cucumbers] = true;
cout << arguablyVegetables[apples] << endl;
列举水果和蔬菜
{
苹果,
梨,
西红柿,
黄瓜,
最大值
};
向量arguablyVegetables(最大值,false);
arguablyVegetables[番茄]=真;
arguablyVegetables[黄瓜]=真;
啊,这很容易做到
template <typename T>
pair<T, fruit_and_vegetables> operator||(T t, fruit_and_vegetables v) {
return make_pair(t, v);
}
template <typename T>
bool operator==(fruit_and vegetables lhs, pair<T, fruit_and_vegetables> rhs) {
return lhs == rhs.second || lhs == rhs.first;
}
但是如果你使用(苹果(梨(橙))
,这将不起作用。这可以很容易地解决,但我想保持代码简单。我相信这是目前为止唯一可以扩展到大型枚举的答案…为什么不使用集合
来进行逻辑运算或对多个水果和_蔬菜
?
如果将constexpr
放在运算符|
和运算符=
重载之前,
在参数和结果类型之前,
然后编译器将在编译时评估代码(无运行时开销)
如有可能;)
可以很好地扩展到更大的a | | b | | c | | c
enum范围,您可以随意将值放在括号中
#include <set>
using std::set;
enum fruit_and_vegetables
{
apples,
pears,
tomatoes,
cucumbers
};
set< fruit_and_vegetables > operator||( fruit_and_vegetables left, fruit_and_vegetables right ) {
set< fruit_and_vegetables > set;
set.insert( left );
set.insert( right );
return set;
}
set< fruit_and_vegetables > operator||( set<fruit_and_vegetables> left, fruit_and_vegetables right ) {
left.insert( right );
return left;
}
set< fruit_and_vegetables > operator||( fruit_and_vegetables left, set<fruit_and_vegetables> right ) {
right.insert( left );
return right;
}
bool operator!=( fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs ) {
return ( rhs.find( lhs ) == rhs.end() );
}
bool operator==( fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs ) {
return !( lhs != rhs );
}
int main() {
fruit_and_vegetables fav = apples;
if ( fav == ( apples || (pears || tomatoes) ) ) cout << "match apples\n";
fav = cucumbers;
if ( fav == ( (apples || pears) || tomatoes ) ) cout << "Error! matched ghost cucumbers\n";
if ( fav != apples ) cout << "correct no match apples\n";
if ( fav == cucumbers ) cout << "default operator==(FaV, FaV) match\n";
if ( fav == ( pears || apples ) ) cout << "yummi\n";
return 0;
}
#包括
使用std::set;
列举水果和蔬菜
{
苹果,
梨,
西红柿,
黄瓜
};
设置<水果和蔬菜>操作员| |(水果和蔬菜左侧,水果和蔬菜右侧){
套装<水果和蔬菜>套装;
设置。插入(左);
设置。插入(右);
返回集;
}
设置<水果和蔬菜>操作员| |(设置左侧,水果和蔬菜右侧){
左。插入(右);
左转;
}
设置<水果和蔬菜>操作员| |(水果和蔬菜左,设置右){
右。插入(左);
返还权;
}
bool操作员!=(水果和蔬菜左侧,设置右侧){
return(rhs.find(lhs)=rhs.end());
}
布尔运算符==(水果和蔬菜左侧,设置右侧){
返回!(左侧!=右侧);
}
int main(){
水果和蔬菜fav=苹果;
如果(fav==(苹果(梨(西红柿)))不能啊是的,“为什么我没想到这个”(C)
…但是如果枚举有中间值,而我的示例变得更复杂/未排序怎么办?西红柿和黄瓜是水果;-pNot根据SCOTUS:@Noah:西红柿是*
而不是
西红柿是*
哇,我看到了一个非常糟糕的例子。冷静点,孩子们,每个人都有足够的;-P
。看起来像这样评估将是“主观的和有争议的”:)-1声称西红柿好吃!j/k尽管我会说,当你开始想要从你的枚举中获得这种行为时,枚举并不是你想要的行为的合适构造。你一定是在开玩笑!西红柿真是太棒了!@bitmask:如果枚举包含70个成员呢?这种左移方法不起作用!哥们儿,既然一个类型方案在那一点上能起到更好的作用,为什么还要这么做呢?foodplanthing
->水果:foodplanthing
,蔬菜:foodplanthing
,等等……那么访问和/或动态播放就能很容易地判断出食物是蔬菜还是水果。为什么从2开始呢?为什么不从1开始呢.(我喜欢它!(但你可能应该让lut常量
)@bitmask:嗯,这只是一个实现细节:)我知道,但我必须填写15个字符:)这和手工检查每个值是一样的。OP要求一个比显而易见的更快的方法。OP询问简单的语法:“oneline-way of synatx-weirdness”.有没有办法让大范围也能工作?这完全是出于兴趣,你的解决方案让我可以完美地完成我想要的!谢谢。
enum fruit_and_vegetables
{
apples,
pears,
tomatoes,
cucumbers,
MAX_VALUE
};
vector<bool> arguablyVegetables(MAX_VALUE, false);
arguablyVegetables[tomatoes] = true;
arguablyVegetables[cucumbers] = true;
cout << arguablyVegetables[apples] << endl;
template <typename T>
pair<T, fruit_and_vegetables> operator||(T t, fruit_and_vegetables v) {
return make_pair(t, v);
}
template <typename T>
bool operator==(fruit_and vegetables lhs, pair<T, fruit_and_vegetables> rhs) {
return lhs == rhs.second || lhs == rhs.first;
}
if (something == (apple || pear || orange)) eat_the_yummy_fruit(something);
else feed_to_rabbit(something)
#include <set>
using std::set;
enum fruit_and_vegetables
{
apples,
pears,
tomatoes,
cucumbers
};
set< fruit_and_vegetables > operator||( fruit_and_vegetables left, fruit_and_vegetables right ) {
set< fruit_and_vegetables > set;
set.insert( left );
set.insert( right );
return set;
}
set< fruit_and_vegetables > operator||( set<fruit_and_vegetables> left, fruit_and_vegetables right ) {
left.insert( right );
return left;
}
set< fruit_and_vegetables > operator||( fruit_and_vegetables left, set<fruit_and_vegetables> right ) {
right.insert( left );
return right;
}
bool operator!=( fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs ) {
return ( rhs.find( lhs ) == rhs.end() );
}
bool operator==( fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs ) {
return !( lhs != rhs );
}
int main() {
fruit_and_vegetables fav = apples;
if ( fav == ( apples || (pears || tomatoes) ) ) cout << "match apples\n";
fav = cucumbers;
if ( fav == ( (apples || pears) || tomatoes ) ) cout << "Error! matched ghost cucumbers\n";
if ( fav != apples ) cout << "correct no match apples\n";
if ( fav == cucumbers ) cout << "default operator==(FaV, FaV) match\n";
if ( fav == ( pears || apples ) ) cout << "yummi\n";
return 0;
}