(12)模板变量 is_enum_v 与类 underlying_type_t,这两个模板变量与模板类,在本头文件 中也会用到。模板变量 is_enum_v 可以判断一个类是不是枚举类。 underlying_type_t 判断一个类的基础类型。
++ 源码如下:
// 确定 _Ty 是否为枚举类型 determine whether _Ty is an enumerated type
template <class _Ty>
struct is_enum : bool_constant< __is_enum(_Ty) > {};
template <class _Ty>
constexpr bool is_enum_v = __is_enum(_Ty);
//---------------------------------------
template <class _Ty, bool = is_enum_v<_Ty>>
struct _Underlying_type { using type = __underlying_type(_Ty) ; };
template <class _Ty>
struct _Underlying_type<_Ty, false> {};
template <class _Ty> // 确定枚举的基础类型 determine underlying根本的 type for enum
struct underlying_type : _Underlying_type<_Ty> {};
template <class _Ty>
using underlying_type_t = typename _Underlying_type<_Ty>::type;
++ 给出一些测试结果:
++ 关于枚举类型的赋值:
++ 以及:
++ 再举例,分析枚举类型的数值计算:
++ 以及:
(13) 支持枚举类型变量的运算的宏函数 _BITMASK_OPS ( launch ) 定义,如何处理枚举类型的数值运算,也很重要。 STL 库大师们为我们写好了支持枚举类型的数据的运算的函数。由此宏函数展开到源文件即可。本 头文件也用到了此方面的知识:
源文件中的定义概览:
++ 可见,内容很多,经展开如下:
++源码定义如下:
// 该宏函数定义来源于 <type_traits>
constexpr launch operator & (launch _Left, launch _Right) noexcept // return _Left & _Right
{ using _IntTy = _STD underlying_type_t<launch>; // 经测试 _IntTy 就是 int 类型,推导见上面的注释
return static_cast<launch>(static_cast<int>(_Left) & static_cast<int>(_Right));
} // 以下函数采用简化类型,突出重点。枚举类型只支持与运算,或运算,异或运算,取反运算
launch operator | (launch _Left, launch _Right) noexcept // return _Left | _Right
{ return static_cast<launch>(static_cast<int>(_Left) | static_cast<int>(_Right)); }
launch operator^(launch _Left, launch _Right) noexcept // return _Left ^ _Right
{ return static_cast<launch>(static_cast<int>(_Left) ^ static_cast<int>(_Right)); }
// return _Left &= _Right 注意:这仨复合运算符函数的形参 1 是左值引用,返回值也是左值引用
launch& operator &= (launch& _Left, launch _Right) { return _Left = _Left & _Right; }
// return _Left |= _Right 调用举例:需使用显式的复合运算符调用, A e &= A a;会报错(与 & 混淆了)
launch& operator |= (launch& _Left, launch _Right) { return _Left = _Left | _Right; }
// return _Left ^= _Right 调用举例:A f = operator^=(A::c, A::a);
launch& operator ^= (launch& _Left, launch _Right) { return _Left = _Left ^ _Right; }
// return ~_Left _BITMASK_OPS(launch)的展开结果
launch operator ~ (launch _Left) { return static_cast<launch>(~static_cast<int>(_Left)); }
// return (_Left & _Elements) != launch{} 按位与,测试形参 1 与 2 之间是否有数值重叠,即为包含
bool _Bitmask_includes(launch _Left, launch _Elements) { return (_Left & _Elements) != launch{}; }
// 注意:这俩函数的函数名是固定的,使用了小写字母,与宏函数的形参无关
// return (_Left & _Elements) == _Elements 按位与,测试形参1 是否全部包含了形参 2 的每一位
bool _Bitmask_includes_all(launch _Left, launch _Elements) { return (_Left & _Elements) == _Elements; }
++ 给个测试:
++ 这里的函数使用的左值引用形式的返回值,那么接受此函数返回的变量到底是不是引用呢?因为这个问题具有共性,在别的文章里另行总结,测试一下。
(14)
谢谢