我工作的公司中的许多代码都经常将无符号字符类型用于较小的数字,以避免数据结构中出现不必要的填充。我很少遇到这个问题,但是在使用按位运算符设置错误标志时,我遇到了一个隐式转换的小问题。我只是通过明确地发现了一种解决方法,但是我想知道是否有更优雅的方法。顺便说一句,我们用c ++ 11编译
给出以下错误代码枚举:
enum ErrorType : unsigned char
{
OK. = 0x00,
ERROR01 = 0x01,
ERROR02 = 0x02
};
,并假设我有一些类具有errorType类型的私有成员 它将使用公共成员设置或取消设置标志,例如:
struct S
{
public:
void setError1();
void unsetError1();
private:
ErrorType errorType;
};
如果我尝试隐式设置以下值:
void S::setError1()
{
this->errorType |= ERROR01;
}
我遇到类型转换错误
但是,如果我明确地将按位转换转换为有效
this->errorType = ErrorType(this->errorType | ERROR01);
问题似乎在于按位转换的输出始终是整数,并不一定反映输入类型。这是真的?如果可以的话,有没有一种方法可以为其指定类型,所以我不必每次都显式地进行转换?
答案 0 :(得分:4)
当不存在枚举的重载运算符时,按位运算将使用内置运算符版本,将枚举提升为底层类型后,可以将其显式转换为:
this->errorType = static_cast<ErrorType>(errorType | ERROR01);
或重载|=
运算符以允许:
ErrorType& operator|=(ErrorType& lhs, ErrorType rhs) {
lhs = static_cast<ErrorType>(lhs | rhs);
return lhs;
}
void S::setError1()
{
this->errorType |= ERROR01;
}
答案 1 :(得分:1)
是的,按位运算的结果是提升后的整数类型。当两个整数操作数参与算术运算时,它们首先被提升为至少int
类型,其中对int
进行运算,结果是int
。从int
到枚举没有隐式转换,因此您必须放弃自己。
以下是有关完整促销规则的更多信息:https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion
答案 2 :(得分:1)
问题似乎在于按位转换的输出始终是整数,并不一定反映输入类型。这是真的吗?
自C语言问世以来,对类型小于int
的数学运算会将类型提升为int
。
推理-当int
是“大整数类型”时-推广到int
会很便宜,并且可以防止某些溢出情况。
如果可以的话,可以为它指定一种类型,这样我就不必每次都显式转换吗?
是的!定义操作,而不是接受默认生成的实现。
ErrorType& operator |= ( ErrorType &left, ErrorType right )
{
return left = ErrorType(left | right);
}