通过重载运算符输出强类型枚举的值
例子摘自《现代C++教程:高速上手 C++11141720》
对于下面的枚举类型:
enum class NEW_ENUM : unsigned int
{a,b,c,d = 100,e = 100
};
我们可以通过重载运算符输出枚举的值:
template <typename T>
std::ostream& operator << (typename std::enable_if<std::is_enum<T>::value, std::ostream >:: type& stream , const T& e)
{return stream << static_cast<typename std::underlying_type<T>::type>(e);
}
这样我们就可以通过下面的代码输出枚举的值:
std::cout << NEW_ENUM::a << std::endl;
解释重载过程:
template <typename T>
- 定义一个模板函数,模板参数为类型T。这是为了支持任意类型的枚举。
std::ostream& operator << (typename std::enable_if<std::is_enum<T>::value, std::ostream >:: type& stream , const T& e)
- SFINAE(Substitution Failure Is Not An Error)技术是C++模板元编程中的一个技术。这个技术的核心思想是:如果一个模板函数在实例化时,无法通过编译,那么编译器不会报错,会根据具体的情况选择另一个重载的函数。(个人的一个通俗的理解,如果通过SFINAE机制的函数不满足条件,那么就忽略这个函数。)
std::ostream&
:返回值为输出流对象的引用。这是为了支持连续输出。operator <<
:重载输出运算符。std::enable_if<std::is_enum<T>::value, std::ostream >:: type
:这是一个模板元函数,用于判断T是否为枚举类型。如果是枚举类型,返回std::ostream类型,否则返回void。这是为了限制只有枚举类型才能调用这个函数。std::enable_if
:模板元函数。这个函数是一个模板函数,有两个模板参数:一个是bool类型的值,另一个是返回值类型。如果第一个参数为true,则返回第二个参数类型,否则返回void。std::is_enum<T>::value
:判断T是否为枚举类型。如果是枚举类型,返回true,否则返回false。std::ostream
:返回值类型。:: type
:返回值类型。stream
:输出流对象。是这个函数的第一个参数。表示重载的输出运算符左边的对象。const T& e
:枚举对象。是这个函数的第二个参数。表示重载的输出运算符右边的对象。
return stream << static_cast<typename std::underlying_type<T>::type>(e);
- 返回输出流对象。
stream << static_cast<typename std::underlying_type<T>::type>(e)
:输出枚举的值。stream
:输出流对象。<<
:输出运算符。static_cast<typename std::underlying_type<T>::type>(e)
:将枚举对象转换为枚举的底层类型。static_cast
:类型转换运算符。静态类型转换,不会进行运行时检查。std::underlying_type<T>
:获取枚举类型T
的底层类型。注意这里的T
是枚举类型,不是枚举对象。typename std::underlying_type<T>::type
:这里tpyename
是一个关键字,表示std::underlying_type<T>::type
是一个类型。std::underlying_type<T>::type
是枚举类型T
的底层类型。- 整体的逻辑是:将枚举对象转换为枚举的底层类型,然后输出这个值。