gpt4 book ai didi

c++ - 枚举类运算符的实现

转载 作者:IT老高 更新时间:2023-10-28 12:41:45 28 4
gpt4 key购买 nike

在讨论后 Incrementation and decrementation of “enum class” ,我想问一下 enum class 类型的算术运算符的可能实现。

原始问题的示例:

enum class Colors { Black, Blue, White, END_OF_LIST };

// Special behavior for ++Colors
Colors& operator++( Colors &c ) {
c = static_cast<Colors>( static_cast<int>(c) + 1 );
if ( c == Colors::END_OF_LIST )
c = Colors::Black;
return c;
}

有没有一种方法可以实现算术运算符,而无需转换为已定义运算符的类型?我想不出来,但选角让我很困扰。类型转换通常表明有问题,并且必须有一个很好的理由来使用它们。我希望该语言允许在不强制使用特定类型的情况下实现运算符的实现。

2018 年 12 月更新:一篇针对 C++17 的论文似乎通过允许枚举类变量和底层类型之间的转换至少部分解决了这个问题:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0138r2.pdf

最佳答案

no-cast 解决方案是使用 switch。但是,您可以使用模板生成伪开关。原理是使用模板列表(或参数包)递归处理枚举的所有值。所以,这是我找到的 3 种方法。

测试枚举:

enum class Fruit
{
apple,
banana,
orange,
pineapple,
lemon
};

原版开关(live here) :

Fruit& operator++(Fruit& f)
{
switch(f)
{
case Fruit::apple: return f = Fruit::banana;
case Fruit::banana: return f = Fruit::orange;
case Fruit::orange: return f = Fruit::pineapple;
case Fruit::pineapple: return f = Fruit::lemon;
case Fruit::lemon: return f = Fruit::apple;
}
}

C++03-ish 方法(live here) :

template<typename E, E v>
struct EnumValue
{
static const E value = v;
};

template<typename h, typename t>
struct StaticList
{
typedef h head;
typedef t tail;
};

template<typename list, typename first>
struct CyclicHead
{
typedef typename list::head item;
};

template<typename first>
struct CyclicHead<void,first>
{
typedef first item;
};

template<typename E, typename list, typename first = typename list::head>
struct Advance
{
typedef typename list::head lh;
typedef typename list::tail lt;
typedef typename CyclicHead<lt, first>::item next;

static void advance(E& value)
{
if(value == lh::value)
value = next::value;
else
Advance<E, typename list::tail, first>::advance(value);
}
};

template<typename E, typename f>
struct Advance<E,void,f>
{
static void advance(E& value)
{
}
};

/// Scalable way, C++03-ish
typedef StaticList<EnumValue<Fruit,Fruit::apple>,
StaticList<EnumValue<Fruit,Fruit::banana>,
StaticList<EnumValue<Fruit,Fruit::orange>,
StaticList<EnumValue<Fruit,Fruit::pineapple>,
StaticList<EnumValue<Fruit,Fruit::lemon>,
void
> > > > > Fruit_values;

Fruit& operator++(Fruit& f)
{
Advance<Fruit, Fruit_values>::advance(f);
return f;
}

C++11-ish 方法(live here) :

template<typename E, E first, E head>
void advanceEnum(E& v)
{
if(v == head)
v = first;
}

template<typename E, E first, E head, E next, E... tail>
void advanceEnum(E& v)
{
if(v == head)
v = next;
else
advanceEnum<E,first,next,tail...>(v);
}

template<typename E, E first, E... values>
struct EnumValues
{
static void advance(E& v)
{
advanceEnum<E, first, first, values...>(v);
}
};

/// Scalable way, C++11-ish
typedef EnumValues<Fruit,
Fruit::apple,
Fruit::banana,
Fruit::orange,
Fruit::pineapple,
Fruit::lemon
> Fruit_values11;

Fruit& operator++(Fruit& f)
{
Fruit_values11::advance(f);
return f;
}

(C++11-ish old version)

您可以通过添加一些预处理器来进行扩展,以消除重复值列表的需要。

关于c++ - 枚举类运算符的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15451382/

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