C++ 如何检查枚举值是否有效?

C++ 如何检查枚举值是否有效?,c++,enums,C++,Enums,我正在从二进制文件中读取enum值,并想检查该值是否确实是enum值的一部分。我怎么做 #include <iostream> enum Abc { A = 4, B = 8, C = 12 }; int main() { int v1 = 4; Abc v2 = static_cast< Abc >( v1 ); switch ( v2 ) { case A: std:

我正在从二进制文件中读取
enum
值,并想检查该值是否确实是
enum
值的一部分。我怎么做

#include <iostream>

enum Abc
{
    A = 4,
    B = 8,
    C = 12
};

int main()
{
    int v1 = 4;
    Abc v2 = static_cast< Abc >( v1 );

    switch ( v2 )
    {
        case A:
            std::cout<<"A"<<std::endl;
            break;
        case B:
            std::cout<<"B"<<std::endl;
            break;
        case C:
            std::cout<<"C"<<std::endl;
            break;
        default :
            std::cout<<"no match found"<<std::endl;
    }
}
#包括
枚举Abc
{
A=4,
B=8,
C=12
};
int main()
{
int v1=4;
Abc v2=静态施法(v1);
开关(v2)
{
案例A:

std::cout可能会像这样使用enum:

enum MyEnum
{
A,
B,
C
};
检查

if (v2 >= A && v2 <= C)

如果(v2>=A&&v2谈到一种语言,没有更好的方法,枚举值只存在于编译时,无法通过编程方式枚举它们。但是,使用经过深思熟虑的基础结构,您可能仍然能够避免多次列出所有值。请参阅

然后可以使用此处提供的“enumFactory.h”重写您的示例,如下所示:

#include "enumFactory.h"

#define ABC_ENUM(XX) \
    XX(A,=4) \
    XX(B,=8) \
    XX(C,=12) \

DECLARE_ENUM(Abc,ABC_ENUM)

int main()
{
    int v1 = 4;
    Abc v2 = static_cast< Abc >( v1 );

    #define CHECK_ENUM_CASE(name,assign) case name: std::cout<< #name <<std::endl; break;
    switch ( v2 )
    {
        ABC_ENUM(CHECK_ENUM_CASE)
        default :
            std::cout<<"no match found"<<std::endl;
    }
    #undef CHECK_ENUM_CASE
}
#包括“enumFactory.h”
#定义ABC_枚举(XX)\
XX(A,=4)\
XX(B,=8)\
XX(C,=12)\
声明枚举(Abc,Abc枚举)
int main()
{
int v1=4;
Abc v2=静态施法(v1);

定义了CuffyQueNoSQL case(name,Advices)case name:STD::CUT

<代码> EnUM < /C>值在C++中有效,如果它属于[A,B],它由下面的标准规则定义。因此,在<代码>枚举x{a=1,b=3 } < /> >中,<代码> 2 < /C> >被认为是有效的枚举值。

考虑标准的7.2/6:

对于emin是最小枚举数且emax是最大枚举数的枚举,枚举的值是范围bmin到bmax内基础类型的值,其中bmin和bmax分别是可存储emin和emax的最小位字段的最小值和最大值。可以定义具有未由其任何枚举数定义的值。 < C++ >没有回溯。一种方法是在数组中另外列出枚举值,并编写一个包装,它将进行转换,并可能在失败时抛出异常。
有关更多详细信息,请参阅如何将int强制转换为enum。

我找到的唯一“简单”的方法是创建(宏)一个已排序的enum数组并进行检查

开关
技巧会因
enum
s而失败,因为
enum
可能有多个具有给定值的枚举数


这是个讨厌的问题,真的。

< P>托管扩展C++支持以下语法:

enum Abc
{
    A = 4,
    B = 8,
    C = 12
};

Enum::IsDefined(Abc::typeid, 8);

参考文献:在C++ 11中,MSDN“

>P>”如果你准备将枚举值作为模板参数列出,那么你可以把它看作一个好东西,允许你接受不同上下文中有效枚举值的子集;在解析来自外部源代码时经常有用。 下面的示例中一个可能有用的补充是围绕EnumType的基础类型相对于IntType的一些静态断言,以避免截断问题

#include <stdio.h>

template<typename EnumType, EnumType... Values> class EnumCheck;

template<typename EnumType> class EnumCheck<EnumType>
{
public:
    template<typename IntType>
    static bool constexpr is_value(IntType) { return false; }
};

template<typename EnumType, EnumType V, EnumType... Next>
class EnumCheck<EnumType, V, Next...> : private EnumCheck<EnumType, Next...>
{
    using super = EnumCheck<EnumType, Next...>;

public:
    template<typename IntType>
    static bool constexpr is_value(IntType v)
    {
        return v == static_cast<IntType>(V) || super::is_value(v);
    }
};

enum class Test {
    A = 1,
    C = 3,
    E = 5
};

using TestCheck = EnumCheck<Test, Test::A, Test::C, Test::E>;

void check_value(int v)
{
    if (TestCheck::is_value(v))
        printf("%d is OK\n", v);
    else
        printf("%d is not OK\n", v);
}

int main()
{
    for (int i = 0; i < 10; ++i)
        check_value(i);
}
#包括
模板类枚举检查;
模板类枚举检查
{
公众:
样板
静态bool constexpr是_值(IntType){return false;}
};
样板
类EnumCheck:私有EnumCheck
{
使用super=EnumCheck;
公众:
样板
静态布尔constexpr为_值(INTV型)
{
返回v==static_cast(v)| super::is_值(v);
}
};
枚举类测试{
A=1,
C=3,
E=5
};
使用TestCheck=EnumCheck;
无效检查值(整数v)
{
if(TestCheck::is_值(v))
printf(“%d正常\n”,v);
其他的
printf(“%d不正常\n”,v);
}
int main()
{
对于(int i=0;i<10;++i)
检查_值(i);
}

有点necro,但是…将int的范围检查为第一个/最后一个枚举值(可以结合janm的想法进行精确检查),C++11:

标题:

namespace chkenum
{
    template <class T, T begin, T end>
    struct RangeCheck
    {
    private:
        typedef typename std::underlying_type<T>::type val_t;
    public:
        static
        typename std::enable_if<std::is_enum<T>::value, bool>::type
        inrange(val_t value)
        {
            return value >= static_cast<val_t>(begin) && value <= static_cast<val_t>(end);
        }
    };

    template<class T>
    struct EnumCheck;
}

#define DECLARE_ENUM_CHECK(T,B,E) namespace chkenum {template<> struct EnumCheck<T> : public RangeCheck<T, B, E> {};}

template<class T>
inline
typename std::enable_if<std::is_enum<T>::value, bool>::type
testEnumRange(int val)
{
    return chkenum::EnumCheck<T>::inrange(val);
}
用法:

bool r = testEnumRange<MinMaxType>(i);
bool r=testEnumRange(i);

上述的主要区别在于,测试函数仅依赖于枚举类型本身。

还有另一种方法:

#include <algorithm>
#include <iterator>
#include <iostream>

template<typename>
struct enum_traits { static constexpr void* values = nullptr; };

namespace detail
{

template<typename T>
constexpr bool is_value_of(int, void*) { return false; }

template<typename T, typename U>
constexpr bool is_value_of(int v, U)
{
    using std::begin; using std::end;

    return std::find_if(begin(enum_traits<T>::values), end(enum_traits<T>::values),
        [=](auto value){ return value == static_cast<T>(v); }
    ) != end(enum_traits<T>::values);
}

}

template<typename T>
constexpr bool is_value_of(int v)
{ return detail::is_value_of<T>(v, decltype(enum_traits<T>::values) { }); }

////////////////////
enum Abc { A = 4, B = 8, C = 12 };

template<>
struct enum_traits<Abc> { static constexpr auto values = { A, B, C }; };
decltype(enum_traits<Abc>::values) enum_traits<Abc>::values;

enum class Def { D = 1, E = 3, F = 5 };

int main()
{
    std::cout << "Abc:";
    for(int i = 0; i < 10; ++i)
        if(is_value_of<Abc>(i)) std::cout << " " << i;
    std::cout << std::endl;

    std::cout << "Def:";
    for(int i = 0; i < 10; ++i)
        if(is_value_of<Def>(i)) std::cout << " " << i;
    std::cout << std::endl;

    return 0;
}
#包括
#包括
#包括
样板
结构枚举特征{static constexpr void*values=nullptr;};
名称空间详细信息
{
样板
constexpr bool是(int,void*){return false;}的值
样板
constexpr bool是(int v,U)的值
{
使用std::begin;使用std::end;
返回std::find_if(begin(enum_traits::values),end(enum_traits::values),
[=](自动值){返回值==static_cast(v);}
)!=结束(枚举特性::值);
}
}
样板
constexpr bool是(int v)的值
{return detail::is_value_of(v,decltype(enum_traits::values){}
////////////////////
枚举Abc{A=4,B=8,C=12};
样板
结构枚举特征{static constexpr auto values={A,B,C};};
decltype(enum_traits::value)enum_traits::value;
枚举类Def{D=1,E=3,F=5};
int main()
{

std::cout Any enum只是一个数字,所以我认为没有更好的方法来检查它。您可能应该为您的数据类型定义一个更严格的结构。您误解了标准引号,它不仅仅是
[a,B]
在有效值中。事实上,例如,如果值为1和5,则后者至少需要3位,因此6和7也将是枚举数的有效值。这个答案仍然不正确。@visitor指出了一个您的示例失败的示例。他说“如果值是1和5,那么后者至少需要3位,因此6和7也是枚举器的有效值”。您的答案意味着只有{1, 2, 3,4, 5 }是有效值,在这种情况下,您的标准引用是正确的,但是您的示例是误导的。我不知道什么“托管C++”。"是的,但是你肯定它是C++,而不是C++吗?看起来像C.*@ @ By**:<代码>托管C++<代码>是一个微软变体,代码< C++<代码>,它可以使用<代码> .NETFramework < /C> >的库。在托管扩展C++项目中尝试代码吗?我们在C++项目之一中使用类似的代码。
bool r = testEnumRange<MinMaxType>(i);
#include <algorithm>
#include <iterator>
#include <iostream>

template<typename>
struct enum_traits { static constexpr void* values = nullptr; };

namespace detail
{

template<typename T>
constexpr bool is_value_of(int, void*) { return false; }

template<typename T, typename U>
constexpr bool is_value_of(int v, U)
{
    using std::begin; using std::end;

    return std::find_if(begin(enum_traits<T>::values), end(enum_traits<T>::values),
        [=](auto value){ return value == static_cast<T>(v); }
    ) != end(enum_traits<T>::values);
}

}

template<typename T>
constexpr bool is_value_of(int v)
{ return detail::is_value_of<T>(v, decltype(enum_traits<T>::values) { }); }

////////////////////
enum Abc { A = 4, B = 8, C = 12 };

template<>
struct enum_traits<Abc> { static constexpr auto values = { A, B, C }; };
decltype(enum_traits<Abc>::values) enum_traits<Abc>::values;

enum class Def { D = 1, E = 3, F = 5 };

int main()
{
    std::cout << "Abc:";
    for(int i = 0; i < 10; ++i)
        if(is_value_of<Abc>(i)) std::cout << " " << i;
    std::cout << std::endl;

    std::cout << "Def:";
    for(int i = 0; i < 10; ++i)
        if(is_value_of<Def>(i)) std::cout << " " << i;
    std::cout << std::endl;

    return 0;
}
decltype(enum_traits<Abc>::values) enum_traits<Abc>::values
#define REGISTER_ENUM_VALUES(name, ...) \
template<> struct enum_traits<name> { static constexpr auto values = { __VA_ARGS__ }; }; \
decltype(enum_traits<name>::values) enum_traits<name>::values;