1 概述
首先,为什么可以通过模板特化来获取variant类中备选类型的数目。依据匹配原则,对于指定类型参数,如果一个未特化的模板和一个特化的模板都可以被正确匹配到,那么优先调用特化版。
使用模板特化来获取variant类中备选类型的数目,有两种方式:
- 类模板特化
- 变量模板特化(后来看optional 和 variant 标准库发现的)
2 两种方式
1 类模板特化
类模板是在编译时处理的主体,变量模板只是简化类模板的书写方式。
- 如果类型是variant类型,则返回备选类型的个数。
- 如果类型不是variant类型,则发生编译时错误。(可选择不发生)
template <typename _Tp>
struct __variant_size_imp; //用于去除掉类型中的cv和ref,不然就要定义多个带修饰符的特化版本
template <typename _Tp>
constexpr size_t variant_size_v_ = __variant_size_imp<_Tp>::value;
template <typename _Tp>
struct __variant_size{};
template <typename... _Tps>
struct __variant_size<std::variant<_Tps...>> : std::integral_constant<size_t, sizeof...(_Tps)> {};
template <typename _Tp>
struct __variant_size_imp : __variant_size<typename std::remove_cvref<_Tp>::type> {};(_Tps)> {};
2 使用变量模板特化
这个书写更简单
namespace details {
template <typename _Tp>
constexpr size_t __variant_size_v = static_cast<size_t>(-1);
template <typename... _Tps>
constexpr size_t __variant_size_v<std::variant<_Tps...>> = sizeof...(_Tps);
}
template <typename _Tp>
constexpr size_t variant_size_v = details::__variant_size_v<typename std::remove_cvref<_Tp>::type>;