gpt4 book ai didi

c++ - 在不破坏现有代码的情况下添加新的枚举

转载 作者:行者123 更新时间:2023-12-02 09:51:20 25 4
gpt4 key购买 nike

我有一个带有一个未定义和两个用户值的枚举:

class enum E
{
UNDEFINED,
VALUE1,
VALUE2
};
我想添加 VALUE3,但我担心有很多类似的代码:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
和:
something = (val == E::VALUE1) ? a : b; // last part assumes E::VALUE2
我喜欢编译器警告switch语句不能处理所有枚举,并想知道是否有类似的东西可以显示上述所有实例?
我担心我不会找到并更新上述所有实例。
编译器是C语

最佳答案

枚举不限于您给其命名的值。从cppreference(格式是我的):

An enumeration is a distinct type whose value is restricted to a range of values (see below for details),

which may include several explicitly named constants ("enumerators"). The values of the constants are values of an integral type known as the underlying type of the enumeration.


“下面的细节”解释了如何确定枚举基础类型。在此范围之外,我们(通常)仅将名称赋予某些值,例如:
enum foo {A,B,C};

int main() {
foo x = static_cast<foo>(42);
}
这段代码是完全可以的。 x的基础值为 42。该值没有名称,但这并不重要……除非您认为确实如此。
此代码做出了错误的假设:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
此代码需要固定(与是否向枚举添加新的命名常量无关)。

现在要进行更严肃的审判以回答问题...

if-else链未涵盖所有枚举值时,将无法获得警告。您可以做的是将枚举的所有 if-else使用都变成错误。考虑一下这里实际发生的情况:
if (x == E::VALUE1) do_something();

switch(x) {
case E::VALUE1 : return 1;
}
在if语句中,我们将其称为 operator==(foo,foo);,其返回值要么是 bool,要么隐式转换为1。使用开关,则不需要任何操作。我们可以利用它来将枚举的 if-else用法转换为错误。忍受我,我将分两个步骤进行说明。首先让我们为 if( x == E::VALUE1)创建一个编译器错误:
class helper { 
operator bool(){ return false;}
};

helper operator==(E,E){
return {};
}
现在 if (x == E::VALUE1)调用 helper operator==(E,E),这很好。然后将结果转换为 bool,但失败,因为转换为 private。在开关中使用枚举仍然可以,您可以依靠编译器错误/警告。基本思想是使某些东西只有在被调用时(在错误/正确的上下文中)才能编译失败。 ( Live Demo)。
缺点是 operator==的所有其他用法也被破坏了。我们可以通过修改帮助程序和 call 站点来修复它们:
#include <type_traits>

enum E {VALUE1};

struct helper {
bool value;
private:
operator bool(){ return false;}
};

helper operator==(E a,E b){
return {
static_cast<std::underlying_type_t<E>>(a) == static_cast<std::underlying_type_t<E>>(b)
};
}

int main() {
E x{VALUE1};
//if ( x== E::VALUE1); // ERROR
bool is_same = (x == E::VALUE1).value;

switch(x) {
case E::VALUE1 : return 1;
}
}
是的,必须编写 .value是一个很大的不便,但是通过这种方式,您可以将 if中对枚举的所有使用都变成错误,而其他所有内容仍将编译。还要注意,您必须确保覆盖所有要捕获的情况(例如 !=<等)。

关于c++ - 在不破坏现有代码的情况下添加新的枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64394449/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com