C++ 是否可以手动定义枚举类的转换?
通常,您可以使用以下语法为类定义强制转换:C++ 是否可以手动定义枚举类的转换?,c++,enums,c++11,enum-class,C++,Enums,C++11,Enum Class,通常,您可以使用以下语法为类定义强制转换: class Test { public: explicit operator bool() { return false; } }; 有没有办法做这个或者类似于枚举类< /C> >?/p> < p>不能在C++中定义非成员的CAST运算符。当然,您不能为枚举定义成员函数。 因此,我建议您使用自由函数将枚举转换为其他类型,与实现强制转换运算符的方法相同 e、 g 有一种很好的方法可以将这些枚举与bool关联,您必须将其拆分为两个文件.h和.cpp
class Test {
public:
explicit operator bool() { return false; }
};
有没有办法做这个或者类似于<代码>枚举类< /C> >?/p> < p>不能在C++中定义非成员的CAST运算符。当然,您不能为枚举定义成员函数。 因此,我建议您使用自由函数将枚举转换为其他类型,与实现强制转换运算符的方法相同
e、 g有一种很好的方法可以将这些枚举与bool关联,您必须将其拆分为两个文件.h和.cpp。 如果有帮助的话,这里就是: 枚举h
///////////////////////////////
// enum.h
#ifdef CPP_FILE
#define ENUMBOOL_ENTRY(A, B) { (enum_e) A, (bool) B },
struct EnumBool
{
enum_e enumVal;
bool boolVal;
};
#else
#define ENUMBOOL_ENTRY(A, B) A,
#endif
#ifdef CPP_FILE
static EnumBool enumBoolTable[] = {
#else
enum enum_e
{
#endif
ENUMBOOL_ENTRY(ItemA, true),
ENUMBOOL_ENTRY(ItemB, false),
...
};
bool EnumToBool(enum_e val);
enum.cpp
///////////////////////////////
// enum.cpp
#define CPP_FILE
#include "enum.h"
bool EnumToBool(enum_e val)
//implement
我没有编译它,所以如果它有任何错误,请放心:)。不,它不是
实际上,enum类
根本不是类。之所以使用class
关键字,是因为突然将非作用域enum
更改为作用域enum
将意味着重新处理所有enum代码。所以委员会决定,要区分新旧样式,新的标签会被标记为<代码>类< /代码>,因为它是一个关键字,所以没有代码< EnUM>代码>可以在C++中被命名为代码>类< /代码>。他们本可以选择另一个,但无论如何也没有多大意义
但是,尽管使用了
class
关键字,它们仍然是常规枚举,因为括号中只允许使用枚举数(以及可能分配给它们的值)。否,但可以使用constexpr
成员和构造函数使普通类类型像枚举类一样工作。然后,您可以添加所有需要的附加成员函数
证明即使使用
开关也可以工作的证据:
#include <iostream>
struct FakeEnum
{
int x;
constexpr FakeEnum(int y = 0) : x(y) {}
constexpr operator int() const { return x; }
static const FakeEnum A, B, Z;
};
constexpr const FakeEnum FakeEnum::A{1}, FakeEnum::B{2}, FakeEnum::Z{26};
std::istream& operator>>(std::istream& st, FakeEnum& fe)
{
int val;
st >> val;
fe = FakeEnum{val};
return st;
}
int main()
{
std::cout << "Hello, world!\n";
FakeEnum fe;
std::cin >> fe;
switch (fe)
{
case FakeEnum::A:
std::cout << "A\n";
break;
case FakeEnum::B:
std::cout << "B\n";
break;
case FakeEnum::Z:
std::cout << "Z\n";
break;
}
}
如果您这样做了,那么使用enum类
有什么意义呢<代码>枚举
可以在给定基础类型的情况下进行前向声明,并且作用域为枚举名称。如果您可以自由地将它们从/转换为整数。。。为什么要使用enum类
?因为它是新的?因为我仍然不想让enum类
转换为整数,但我可以将它定义为能够转换为bool
,并使特定值计算为true,其他值计算为false。请注意,没有“隐式强制转换”这样的事情。强制转换是您在源代码中编写的内容。它告诉编译器进行转换。因此,强制转换是一种显式转换。编译器也可以在没有强制转换的情况下进行一些转换;这些被称为“隐式转换”。@NicolBolas我在这里搜索是因为我希望隐式转换为bool,其中一个枚举是SUCCESS,另一个是错误代码。显然,我们可以进行比较,但对于变量名来说,为了清晰起见,不需要这样做。。。一种情况是使用C样式的位字段@Nicolas为逐位操作设置一组标志。对于一个类,例如,MyCBitfield
,它允许程序员将转换定义为static\u cast(1)供参考:不能同时拥有这两个。只有一个或另一个。挑剔:TestToString
应该返回一个const char*
。挑剔:TestToString
应该返回std::string
enum类
最初是由C++/CLI以几乎相同的语义使用的。该标准采用了现有的语法并对其进行了标准化。太糟糕了,C++ + CLI没有使用<代码>枚举名称空间< />代码,Boost是一个很好的例子——查看非C++ 11的部分(<代码> BooStgNosiSnopeDeNeNeS/<代码>),并扩展“你可以使一个普通类类型像EnUM类”——不幸的是,你不能,在C++中,因为C++‘代码>开关是愚蠢的(在保存一些不变量,例如私有构造函数的情况下,也很难/不可能把它变成一个POD)。如果你定义一个转换函数为整数或枚举类型,你可以让你的类<代码>开关>代码>。你所说的“switch
是愚蠢的”是什么意思?(如果您还记得您试图指出的要点)@KonradRudolph:请注意,值A
,B
,Z
,实际上不必存在于秘密枚举类类型中。。。枚举类对象(与传统枚举不同)保证能够存储与其基础类型相同的一组值,无论它们是否是按位或下枚举数闭包的一部分。@BenVoigt我知道您将如何使用它。事实上,CRTP可以与此配合使用。
#include <iostream>
struct FakeEnum
{
int x;
constexpr FakeEnum(int y = 0) : x(y) {}
constexpr operator int() const { return x; }
static const FakeEnum A, B, Z;
};
constexpr const FakeEnum FakeEnum::A{1}, FakeEnum::B{2}, FakeEnum::Z{26};
std::istream& operator>>(std::istream& st, FakeEnum& fe)
{
int val;
st >> val;
fe = FakeEnum{val};
return st;
}
int main()
{
std::cout << "Hello, world!\n";
FakeEnum fe;
std::cin >> fe;
switch (fe)
{
case FakeEnum::A:
std::cout << "A\n";
break;
case FakeEnum::B:
std::cout << "B\n";
break;
case FakeEnum::Z:
std::cout << "Z\n";
break;
}
}
#include <iostream>
/* pseudo-enum compatible with switch and not implicitly convertible to integral type */
struct FakeEnum
{
enum class Values { A = 1, B = 2, Z = 26 };
Values x;
explicit constexpr FakeEnum(int y = 0) : FakeEnum{static_cast<Values>(y)} {}
constexpr FakeEnum(Values y) : x(y) {}
constexpr operator Values() const { return x; }
explicit constexpr operator bool() const { return x == Values::Z; }
static const FakeEnum A, B, Z;
};
constexpr const FakeEnum FakeEnum::A{Values::A}, FakeEnum::B{Values::B}, FakeEnum::Z{Values::Z};
std::istream& operator>>(std::istream& st, FakeEnum& fe)
{
int val;
st >> val;
fe = FakeEnum(val);
return st;
}
int main()
{
std::cout << "Hello, world!\n";
FakeEnum fe;
std::cin >> fe;
switch (fe)
{
case FakeEnum::A:
std::cout << "A\n";
break;
case FakeEnum::B:
std::cout << "B\n";
break;
case FakeEnum::Z:
std::cout << "Z\n";
break;
}
// THIS ERRORS: int z = fe;
}