Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何自动将强类型枚举转换为int? #包括 结构a{ 枚举局部_A{A1,A2}; }; 枚举类b{B1,B2}; intfoo(intinput){returninput;} 内部主(空){ 性病:不能。没有自然的方法_C++_C++11_Strongly Typed Enum - Fatal编程技术网

C++ 如何自动将强类型枚举转换为int? #包括 结构a{ 枚举局部_A{A1,A2}; }; 枚举类b{B1,B2}; intfoo(intinput){returninput;} 内部主(空){ 性病:不能。没有自然的方法

C++ 如何自动将强类型枚举转换为int? #包括 结构a{ 枚举局部_A{A1,A2}; }; 枚举类b{B1,B2}; intfoo(intinput){returninput;} 内部主(空){ 性病:不能。没有自然的方法,c++,c++11,strongly-typed-enum,C++,C++11,Strongly Typed Enum,事实上,在C++11中使用强类型enum类的动机之一是防止它们无声地转换为int强类型enum,以解决多个问题,而不仅仅是问题中提到的范围界定问题: 提供类型安全性,从而通过整数提升消除到整数的隐式转换 指定基础类型 提供强大的范围 因此,不可能隐式地将强类型枚举转换为整数,甚至是它的基础类型——这就是想法。因此,必须使用static\u cast使转换显式化 如果您唯一的问题是作用域,并且您确实希望对整数进行隐式升级,那么最好使用非强类型枚举,并在其声明的结构范围内使用它。正如其他人所说,您不

事实上,在C++11中使用强类型
enum类的动机之一是防止它们无声地转换为
int

强类型enum,以解决多个问题,而不仅仅是问题中提到的范围界定问题:

  • 提供类型安全性,从而通过整数提升消除到整数的隐式转换
  • 指定基础类型
  • 提供强大的范围
  • 因此,不可能隐式地将强类型枚举转换为整数,甚至是它的基础类型——这就是想法。因此,必须使用
    static\u cast
    使转换显式化


    如果您唯一的问题是作用域,并且您确实希望对整数进行隐式升级,那么最好使用非强类型枚举,并在其声明的结构范围内使用它。

    正如其他人所说,您不能进行隐式转换,这是出于设计

    如果需要,可以避免在强制转换中指定基础类型

    #include <iostream>
    
    struct a {
      enum LOCAL_A { A1, A2 };
    };
    enum class b { B1, B2 };
    
    int foo(int input) { return input; }
    
    int main(void) {
      std::cout << foo(a::A1) << std::endl;
      std::cout << foo(static_cast<int>(b::B2)) << std::endl;
    }
    
    模板
    constexpr typename std::底层类型::类型到底层(E)无例外{
    返回静态_-cast(e);
    }
    std::cout
    #包括
    #包括
    #包括
    #包括
    命名空间utils
    {
    命名空间详细信息
    {
    模板
    如果::类型;
    }//名称空间详细信息
    模板
    constexpr inline details::enable_enum_t底层_值(E E)noexcept
    {
    返回静态类型转换(e);
    }   
    模板
    constexpr内联typename std::enable_if::类型
    to_enum(T值)无异常
    {
    返回静态_cast(值);
    }
    }//命名空间utils
    int main()
    {
    枚举类E{a=1,b=3,c=5};
    constexpr auto a=utils::底层_值(E::a);
    constexpr E b=utils::to_enum(5);
    constexpr auto bv=utils::基础_值(b);
    printf(“a=%d,b=%d”,a,bv);
    返回0;
    }
    
    希望这对你或其他人有所帮助

    #include <cstdlib>
    #include <cstdio>
    #include <cstdint>
    
    #include <type_traits>
    
    namespace utils
    {
    
    namespace details
    {
    
    template< typename E >
    using enable_enum_t = typename std::enable_if< std::is_enum<E>::value, 
                                                   typename std::underlying_type<E>::type 
                                                 >::type;
    
    }   // namespace details
    
    
    template< typename E >
    constexpr inline details::enable_enum_t<E> underlying_value( E e )noexcept
    {
        return static_cast< typename std::underlying_type<E>::type >( e );
    }   
    
    
    template< typename E , typename T>
    constexpr inline typename std::enable_if< std::is_enum<E>::value &&
                                              std::is_integral<T>::value, E
                                             >::type 
     to_enum( T value ) noexcept 
     {
         return static_cast<E>( value );
     }
    
    } // namespace utils
    
    
    
    
    int main()
    {
        enum class E{ a = 1, b = 3, c = 5 };
    
        constexpr auto a = utils::underlying_value(E::a);
        constexpr E    b = utils::to_enum<E>(5);
        constexpr auto bv = utils::underlying_value(b);
    
        printf("a = %d, b = %d", a,bv);
        return 0;
    }
    
    enum类EnumClass:int//设置枚举的大小
    {
    零,一,二,三,四
    };
    union//这将允许我们转换
    {
    ec类;
    int i;
    };
    int main()
    {
    使用名称空间std;
    //从强类型枚举转换为int
    联合国2号;
    un2.ec=枚举类::三;
    
    cout正如许多人所说,如果不增加开销和太多的复杂性,就无法自动转换,但是如果在场景中大量使用某些cast,您可以通过使用lambdas来减少键入量并使其看起来更好。这将增加一点函数开销调用,但与长时间的静态调用相比,会使代码更可读ast字符串,如下所示。这在项目范围内可能没有用处,但仅在类范围内有用

    enum class EnumClass : int //set size for enum
    {
        Zero, One, Two, Three, Four
    };
    
    union Union //This will allow us to convert
    {
        EnumClass ec;
        int i;
    };
    
    int main()
    {
    using namespace std;
    
    //convert from strongly typed enum to int
    
    Union un2;
    un2.ec = EnumClass::Three;
    
    cout << "un2.i = " << un2.i << endl;
    
    //convert from int to strongly typed enum
    Union un;
    un.i = 0; 
    
    if(un.ec == EnumClass::Zero) cout << "True" << endl;
    
    return 0;
    }
    
    #包括
    #包括
    枚举类标志{……,总计};
    std::位集MaskVar;
    std::矢量新标志;
    -----------
    自动scui=[](标志a){返回静态_cast(a);};
    用于(自动常量和it:NewFlags)
    {
    开关(it)
    {
    案例标志::水平:
    MaskVar.set(scui(Flags::Horizontal));
    重置(scui(标志::垂直));中断;
    案例标志::垂直:
    set(scui(Flags::Vertical));
    重置(scui(标志:水平));中断;
    案例标志::长文本:
    set(scui(Flags::LongText));
    重置(scui(Flags::ShorTText));中断;
    大小写标志::短文本:
    set(scui(Flags::ShorTText));
    重置(scui(Flags::LongText));中断;
    案例标志::显示标题:
    MaskVar.set(scui(Flags::ShowHeading));
    MaskVar.reset(scui(Flags::NoShowHeading));中断;
    案例标志::无显示标题:
    MaskVar.set(scui(Flags::NoShowHeading));
    MaskVar.reset(scui(Flags::ShowHeading));中断;
    违约:
    打破
    }
    }
    
    提供的答案的C++14版本是:

    #include <bitset>
    #include <vector>
    
    enum class Flags { ......, Total };
    std::bitset<static_cast<unsigned int>(Total)> MaskVar;
    std::vector<Flags> NewFlags;
    
    -----------
    auto scui = [](Flags a){return static_cast<unsigned int>(a); };
    
    for (auto const& it : NewFlags)
    {
        switch (it)
        {
        case Flags::Horizontal:
            MaskVar.set(scui(Flags::Horizontal));
            MaskVar.reset(scui(Flags::Vertical)); break;
        case Flags::Vertical:
            MaskVar.set(scui(Flags::Vertical));
            MaskVar.reset(scui(Flags::Horizontal)); break;
    
       case Flags::LongText:
            MaskVar.set(scui(Flags::LongText));
            MaskVar.reset(scui(Flags::ShorTText)); break;
        case Flags::ShorTText:
            MaskVar.set(scui(Flags::ShorTText));
            MaskVar.reset(scui(Flags::LongText)); break;
    
        case Flags::ShowHeading:
            MaskVar.set(scui(Flags::ShowHeading));
            MaskVar.reset(scui(Flags::NoShowHeading)); break;
        case Flags::NoShowHeading:
            MaskVar.set(scui(Flags::NoShowHeading));
            MaskVar.reset(scui(Flags::ShowHeading)); break;
    
        default:
            break;
        }
    }
    
    #包括
    模板
    constexpr auto to_底层(E)无异常
    {
    返回静态_-cast(e);
    }
    
    与前面的答案一样,这将适用于任何类型的枚举和基础类型。我添加了
    noexcept
    关键字,因为它不会引发异常


    更新

    这也出现在< Scott Meyers > <强>中的<>强有效的现代C++中。参见项目10(在我的书中的项目的最后页中详细说明)。

    < P>没有回答隐含转换(由设计)的原因。 我个人使用一元
    运算符+
    将枚举类转换为其基础类型:

    #include <type_traits>
    
    template <typename E>
    constexpr auto to_underlying(E e) noexcept
    {
        return static_cast<std::underlying_type_t<E>>(e);
    }
    
    模板
    constexpr自动运算符+(te)无异常
    ->std::如果启用,则启用
    {
    返回静态_-cast(e);
    }
    
    这使得“打字开销”非常小:


    std::cout对于本机
    enum类
    ,这似乎是不可能的,但您可能可以使用
    模拟
    enum类

    在这种情况下,

    #define UNSIGNED_ENUM_CLASS(name, ...) enum class name : unsigned { __VA_ARGS__ };\
    inline constexpr unsigned operator+ (name const val) { return static_cast<unsigned>(val); }
    
    相当于:

    enum class b
    {
        B1,
        B2
    };
    
    这主要相当于原始的
    enum类
    。您可以在返回类型为
    b
    的函数中直接返回
    b::B1
    。您可以使用它执行
    切换case
    等操作


    根据本例的精神,您可以使用模板(可能与其他东西一起)来概括和模拟
    enum类
    语法定义的任何可能对象。

    简短的回答是,您不能像上面的帖子所指出的那样。但就我的情况而言,我只是不想混乱名称空间,但仍然有隐式的对流
    std::cout << foo(+b::B2) << std::endl;
    
    #define UNSIGNED_ENUM_CLASS(name, ...) enum class name : unsigned { __VA_ARGS__ };\
    inline constexpr unsigned operator+ (name const val) { return static_cast<unsigned>(val); }
    
    enum class b
    {
        B1,
        B2
    };
    
    class b {
     private:
      int underlying;
     public:
      static constexpr int B1 = 0;
      static constexpr int B2 = 1;
      b(int v) : underlying(v) {}
      operator int() {
          return underlying;
      }
    };
    
    #include <iostream>
    
    using namespace std;
    
    namespace Foo {
       enum Foo { bar, baz };
    }
    
    int main() {
       cout << Foo::bar << endl; // 0
       cout << Foo::baz << endl; // 1
       return 0;
    }
    
    struct TextureUploadFormat {
        enum Type : uint32 {
            r,
            rg,
            rgb,
            rgba,
            __count
        };
    };
    
    // must use ::Type, which is the extra typing with this method; beats all the static_cast<>()
    uint32 getFormatStride(TextureUploadFormat::Type format){
        const uint32 formatStride[TextureUploadFormat::__count] = {
            1,
            2,
            3,
            4
        };
        return formatStride[format]; // decays without complaint
    }
    
    // enum class (AKA: "strong" or "scoped" enum)
    enum class my_enum
    {
        A = 0,
        B,
        C,
    };
    
    my_enum e = my_enum::A; // scoped through `my_enum::`
    e = my_enum::B;
    
    // NOT ALLOWED!:
    //   error: cannot convert ‘my_enum’ to ‘int’ in initialization
    // int i = e; 
    
    // But this works fine:
    int i = static_cast<int>(e);
    
    // regular enum (AKA: "weak" or "C-style" enum)
    enum my_enum
    {
        MY_ENUM_A = 0,
        MY_ENUM_B,
        MY_ENUM_C,
    };
    
    my_enum e = MY_ENUM_A; // scoped through `MY_ENUM_`
    e = MY_ENUM_B;
    
    // This works fine!
    int i = e;
    
    #include <iostream>
    #include <stdio.h>
    
    // enum class (AKA: "strong" or "scoped" enum [available only in C++, not C])
    enum class my_enum
    {
        A = 0,
        B,
        C,
    };
    
    // regular enum (AKA: "weak" or "C-style" enum [available in BOTH C and C++])
    enum my_enum2
    {
        MY_ENUM_A = 0,
        MY_ENUM_B,
        MY_ENUM_C,
    };
    
    
    int main()
    {
        printf("Hello World\n");
    
        // 1) scoped enum
    
        my_enum e = my_enum::A; // scoped through `my_enum::`
        e = my_enum::B;
        
        // IMPLICIT CASTING TO INT IS NOT ALLOWED!
        // int i = e; // "error: cannot convert ‘my_enum’ to ‘int’ in initialization"
        // But this explicit C++-style cast works fine:
        int i1 = static_cast<int>(e); 
        // This explicit C-style cast works fine too, and is easier to read
        int i2 = (int)e;
        
        
        // 2) regular enum 
        
        my_enum2 e2 = MY_ENUM_A; // scoped through `MY_ENUM_`
        e2 = MY_ENUM_B;
        
        // This implicit cast works fine / IS allowed on C-style enums!
        int i3 = e2;
        // These explicit casts are also fine, but explicit casting is NOT 
        // required for regular enums.
        int i4 = static_cast<int>(e2); // explicit C++-style cast 
        int i5 = (int)e2;              // explicit C-style cast 
    
        return 0;
    }
    
    enum class EnumType : int { Green, Blue, Yellow };
    std::cout << static_cast<std::underlying_type_t<EnumType>>(EnumType::Green);
    
    enum class EnumType : int { Green, Blue, Yellow };
    std::cout << static_cast<std::common_type_t<int, std::underlying_type_t<EnumType>>>(EnumType::Green);
    
    template <class E>
    constexpr std::common_type_t<int, std::underlying_type_t<E>>
    enumToInteger(E e) {
        return static_cast<std::common_type_t<int, std::underlying_type_t<E>>>(e);
    }
    
    std::cout << enumToInteger(EnumType::Green);