接近我可以告诉我正在寻找的理想事物是在C++ 11规范之外,如果我在其他方面有类似枚举类的东西,其核心看起来像这样:
enum class Color { RED, ORANGE, YELLOW, GREEN, CYAN, AZURE, BLUE, MAGENTA };
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想要(非虚拟)成员函数,以便我可以定义这样的东西:
Color Color::complement() const
{
switch(*this) {
case RED:return CYAN;
case ORANGE: return AZURE;
case YELLOW: return BLUE;
case GREEN: return MAGENTA;
case CYAN: return RED;
case AZURE: return ORANGE;
case BLUE: return YELLOW;
case MAGENTA: return GREEN;
}
}
Run Code Online (Sandbox Code Playgroud)
当然,C++ 11规范不允许您为枚举类定义成员函数,因此这是不可能的.
现在严格来说,我并不是真的要求我的complement函数实际上是常规成员函数,具体而言,但如果它不可能,那么理想情况下我希望它仍以某种方式指定Color::用于范围解析.即使是静态成员函数也可以,将Color参数作为参数,但同样...... C++ 11不允许在枚举类中使用静态成员函数.
发生在我身上的一个选择是牺牲这个Color::在名称中明确指定的偏好,并在与Color枚举相同的级别定义一个函数,如下所示:
Color complement(Color orginal)
{
switch(orginal) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
我用这种方法遇到的最大问题是这个补充函数没有绑定到类名称空间Color,虽然参数检查确保它不会在另一个上下文中使用,但我觉得使用该函数的代码会更清晰代码的读者,如果函数是通过调用的Color::complement,在我看来,这个函数比简单地更具惯用性complement.此外,类型转换为如何调用此函数实际上是由编译器本身强制执行的(理想情况下,在我看来,因为它不需要函数名称只是一个谓词,对于一个人来说非常清楚正在阅读关于函数目的是什么以及如何使用它的代码),如果底层类型应该改变,名称不会被无意中弃用,这是我尝试使用以某种方式编码名称的命名方案的最大问题将数据类型转换为标识符本身的名称.
我曾简要地考虑过只使用命名空间,如下所示:
namespace Color
enum { RED, ORANGE, YELLOW, GREEN, CYAN, AZURE, BLUE, MAGENTA };
int complement(int orginal)
{
switch(original) {
....
}
}
}
Run Code Online (Sandbox Code Playgroud)
这将允许我将颜色指定为Color::RED,Color::BLUE等,以及能够指定类似于Color::complement(x)获得x中包含的颜色的补充的东西,但是这种方法没有枚举类所做的强类型检查.如果我在Color命名空间本身内部使用了一个枚举类,那么我将被强制指定颜色Color::additional_name::RED等等......而不仅仅是Color::RED,这就是我希望能够指定它们的方式.
C++不允许我同时调用枚举类Color和命名空间Color,因此无法在语法上实现我之后的那种方式.
那么......有没有办法实现我想要的范围界定,我想要强大的类型检查,或者我只是在冲洗,并期望比实际设计的语言更多的语言?
不,由于你给出的原因.
但是我不明白为什么你这么干嘛把它变成一个会员功能.枚举或没有枚举,我认为无论如何都没有使它成为会员的价值.它应该是同一个封闭命名空间中的自由函数.
让ADL为您处理名称查找.这有什么问题?
Color comp{complement(Color::RED)};
Run Code Online (Sandbox Code Playgroud)
它并不是您所要的,但是您可以使的运算符重载enum class,并使用它来进行补充。
enum class Color {
RED,
ORANGE,
YELLOW,
GREEN,
CYAN,
AZURE,
BLUE,
MAGENTA
};
Color operator~(Color c) {
switch(c) {
case Color::RED: return Color::CYAN;
case Color::ORANGE: return Color::AZURE;
case Color::YELLOW: return Color::BLUE;
case Color::GREEN: return Color::MAGENTA;
case Color::CYAN: return Color::RED;
case Color::AZURE: return Color::ORANGE;
case Color::BLUE: return Color::YELLOW;
case Color::MAGENTA: return Color::GREEN;
}
}
~Color::RED == Color::CYAN
etc...
Run Code Online (Sandbox Code Playgroud)