C++ 如何自动将强类型枚举转换为int? #包括 结构a{ 枚举局部_A{A1,A2}; }; 枚举类b{B1,B2}; intfoo(intinput){returninput;} 内部主(空){ 性病:不能。没有自然的方法
事实上,在C++11中使用强类型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使转换显式化 如果您唯一的问题是作用域,并且您确实希望对整数进行隐式升级,那么最好使用非强类型枚举,并在其声明的结构范围内使用它。正如其他人所说,您不
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);