1. 用using声明枚举值
假设有一个限定范围的枚举类型(用枚举类声明):
enum class Status{open, progress, done = 9};
与未限定作用域的枚举类型(不带类的枚举) 不同,此类型的值需要带有类型名的限定符:
auto x = Status::open; // OK
auto x = open; // ERROR
然而,在某些明显没有冲突的上下文中,一直限定每个值可能会变得有点乏味。为了更方便地
使用作用域枚举类型,现在可以使用using 枚举声明。
一个典型的例子是切换所有可能的枚举值,可以这样实现:
void print(Status s)
{switch (s) {using enum Status; // make enum values available in current scopecase open:std::cout << "open";break;case progress:std::cout << "in progress";break;case done:std::cout << "done";break;}
}
只要在print() 的作用域中没有声明其他名为open、progress 或done 的符号,这段代码就可以正
常工作。
void print(Status s)
{switch (s) {using Status::open, Status::progress, Status::done;case open:std::cout << "open";break;case progress:std::cout << "in progress";break;case done:std::cout << "done";break;}
}
这样,就确切地知道哪些名称在当前作用域中可用。
也可以对无作用域的枚举类型使用using 声明。这不是必需的,但就不必知道枚举类型是如何
定义的了:
enum Status{open, progress, done = 9}; // unscoped enum
auto s1 = open; // OK
auto s2 = Status::open; // OKusing enum Status; // OK, but no effect
auto s3 = open; // OK
auto s4 = Status::open; // OK
2. 枚举类型委托给不同的作用域
使用枚举声明还可以将枚举值委托给不同的作用域。例如:
namespace MyProject
{
class Task
{
public:enum class Status{open, progress, done = 9};Task();...
};using enum Task::Status; // expose the values of Status to MyProject
}auto x = MyProject::open; // OK: x has value MyProject::Task::open
auto y = MyProject::done; // OK: y has value MyProject::Task::done
注意这里using enum声明只公开值,并不公开枚举类型:
MyProject::Status s; // ERROR
要公开枚举类型和它的值,还需要一个普通的using声明(类型别名):
namespace MyProject
{
using Status = Task::Status; // expose the type Task::Status
using enum Task::Status; // expose the values of Task::Status
}
MyProject::Status s = MyProject::done; // OK
对于公开的枚举值,甚至依赖于参数的查找(ADL) 也可以正常工作。可以将上面的例子扩展为
如下例子:
namespace MyProject
{
void foo(MyProject::Task::Status)
{
}
}namespace MyScope
{
using enum MyProject::Task::Status; // OK
}foo(MyProject::done); // OK: calls MyProject::foo() with MyProject::Task::Status::done
foo(MyScope::done); // OK: calls MyProject::foo() with MyProject::Task::Status::done
Note that a type alias is not generally used by ADL:
namespace MyScope
{
void bar(MyProject::Task::Status)
{
}
using MyProject::Task::Status; // expose enum type to MyScope
using enum MyProject::Task::Status; // expose the enum values to MyScope
}MyScope::Status s = MyScope::open; // OK
bar(MyScope::done); // ERROR
MyScope::bar(MyScope::done); // OK