为枚举类重载强制转换运算符

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为枚举类重载强制转换运算符相关的知识,希望对你有一定的参考价值。

在我的项目中,我正在使用多个枚举类,我需要根据我需要使用它们来轻松地进行转换。它们基本上描述了相同的东西,但命名方式不同,以使代码更容易使用。以下是枚举类:

enum class tetroType {
    None, I, O, T, J, L, S, Z
};

enum class gridBlock {
    Empty, Blue, Green, Orange, Purple, Red, Teal, Yellow
};

tetroType中的每个值对应于gridBlock中的值(fe tetroType :: I = gridBlock :: Teal),但第一个值包含有关tetronimo形状的信息(tetronimo类中),第二个值包含有关块颜色的信息(in网格类)。我知道我可以使用一个枚举,但这样你就不会丢失任何信息。如果可能的话,我还需要把它转换成字符串。这就是我想用它的方式:

gridBlock grid = (gridBlock)tetroType::I;
string texture = (string)grid;

现在,我设置它的方式是这样的。每当我需要将一个枚举转换为另一个或转换为字符串时,我在其他方法的中间使用此开关:

switch (type) {
case tetroType::I:
    block = gridBlock::Teal;
    break;
case tetroType::O:
    block = gridBlock::Yellow;
    break;
case tetroType::T:
    block = gridBlock::Purple;
    break;
case tetroType::J:
    block = gridBlock::Blue;
    break;
case tetroType::L:
    block = gridBlock::Orange;
    break;
case tetroType::S:
    block = gridBlock::Green;
    break;
case tetroType::Z:
    block = gridBlock::Red;
    break;
case tetroType::None:
    block = gridBlock::Empty;
}
答案

你应该考虑将enum类重载为一个整数(这是一个C ++ 11特性)。

enum class tetroType : int {
    I = 1, O = 2, T = 3, J = 4, L = 5, S = 6, Z = 7, NONE
};

enum class gridBlock : int {
    Blue = 1, Green = 2, Orange = 3, Purple = 4, Red = 5, Teal = 6, Yellow = 9, EMPTY
};

从这里,您可以使用ether C Style类型转换或static_cast编写基本转换

gridBlock ConvertTetro(tetroType type){
    return static_cast<gridBlock>(static_cast<int>(type));
}

gridBlock ConvertTetro(tetroType type){
    return (gridBlock)((int)((type)));
}

这将匹配任何网格块到相同的tetrotypes,如果没有匹配的类型,将默认为gridBlock :: EMPTY。如果需要,这个功能应该很容易弄清楚如何走另一条路。从这里你需要匹配两者之间的int值。

您还可以使用char值作为char文字('A','b','!')

enum class enumName : char

这将与两种基础类型一样长

另一答案

简单回答:不要使用enum class,而是使用普通的enum,它们可以隐式地转换为它们的基础类型(默认为int)。

在C ++ 11中,enum class是一个强大的别名,需要从中进行投射。

另一答案

如果你接受这样一个事实,你必须保持两个枚举之一的定义与另一个相关,这样每个gridBlocktetroType获取一个值然后你可以覆盖operator==在比较中无缝地使用它们并覆盖不同的运算符(例如<<= )模仿不同类型之间的分配。

像这样的东西:

#include <iostream>
#include <type_traits>
#include <cassert>

using namespace std;

enum class tetroType {
    None, I, O, T, J, L, S, Z
};

enum class gridBlock {
    Empty = static_cast<std::underlying_type<tetroType>::type>(tetroType::None), 
    Blue = static_cast<std::underlying_type<tetroType>::type>(tetroType::I), 
    Green = static_cast<std::underlying_type<tetroType>::type>(tetroType::O), 
    Orange = static_cast<std::underlying_type<tetroType>::type>(tetroType::T), 
    Purple = static_cast<std::underlying_type<tetroType>::type>(tetroType::J), 
    Red = static_cast<std::underlying_type<tetroType>::type>(tetroType::L), 
    Teal = static_cast<std::underlying_type<tetroType>::type>(tetroType::S), 
    Yellow = static_cast<std::underlying_type<tetroType>::type>(tetroType::Z)
};

bool operator==(const tetroType& t, const gridBlock& g) { return static_cast<gridBlock>(t) == g; }
bool operator==(const gridBlock& g, const tetroType& t) { return static_cast<gridBlock>(t) == g; }

bool operator!=(const tetroType& t, const gridBlock& g) { return static_cast<gridBlock>(t) != g; }
bool operator!=(const gridBlock& g, const tetroType& t) { return static_cast<gridBlock>(t) != g; }

gridBlock& operator<<=(gridBlock& g, tetroType t) { g = static_cast<gridBlock>(t); return g; }
tetroType& operator<<=(tetroType& t, gridBlock g) { t = static_cast<tetroType>(g); return t; }

int main() {
  tetroType t1 = tetroType::I, t2 = tetroType::O;
  gridBlock g1 = gridBlock::Blue, g2 = gridBlock::Green;

  gridBlock g3;
  g3 <<= t1;
  tetroType t3;
  t3 <<= g2;


  assert(t1 == g1);
  assert(t1 != g2);
  assert(g3 == t1);
  assert(t3 == g2);

    return 0;
}

虽然这个解决方案很简洁,但它非常神秘而且模糊不清,所以你最好清楚地记录这个行为。但总的来说,enum class可以很好地覆盖像operator<<=这样的运算符,因为它们在任何情况下都没有定义。

请注意,您可以在值之间使用自定义映射,但如果您不需要它们,因为您可以使用另一个初始化一个值,则无需手动映射它们。

以上是关于为枚举类重载强制转换运算符的主要内容,如果未能解决你的问题,请参考以下文章

重载()运算符和重载强制类型转换

c++ 转换运算符重载、枚举、整数和字符

在 C# 中是不是可以通过以下方式重载泛型强制转换运算符?

C++ 强制转换运算符重载和多态性

枚举类中的 c++ 运算符重载

c ++:强制转换运算符与分配运算符与转换构造函数优先级