std::conditional用法
std::conditional从C++11开始支持,其使用方法如下:
template< bool B, class T, class F > struct conditional;将根据B的值来判断来提供数据类型,若B为true,则提供数据类型为T,反之则提供数据类型为F,例:
#include <iostream> #include <type_traits> #include <typeinfo> int main() { typedef std::conditional<true, int, double>::type Type1; typedef std::conditional<false, int, double>::type Type2; typedef std::conditional<sizeof(int) >= sizeof(double), int, double>::type Type3; std::cout << typeid(Type1).name() << '\n'; std::cout << typeid(Type2).name() << '\n'; std::cout << typeid(Type3).name() << '\n'; }输出结果为:
int double double用法
1. 模板参数推导,选择成员 / 返回类型
template<typename T> auto get_value(T t) -> std::conditional_t<std::is_pointer_v<T>, T*, T> { if constexpr(std::is_pointer_v<T>) return &t; else return t; }2. 容器 / 底层存储类型选择
template<long MaxVal> using SelectIntType = std::conditional_t< MaxVal <= 32767, short, std::conditional_t<MaxVal <= 2147483647, int, long long> >; using T1 = SelectIntType<1000>; // short using T2 = SelectIntType<100000>; // int using T3 = SelectIntType<3e10>; // long long3. 条件添加 const /volatile/ 引用修饰
// 如果布尔为true就变成const T,否则T template<bool IsConst, typename T> using CondConst = std::conditional_t<IsConst, const T, T>; CondConst<true, int> // const int CondConst<false, int> // int4. 配合 std::enable_if,做重载的类型选择
template<typename T> struct Wrapper { // 整数用int存储,浮点用double存储 using storage_type = std::conditional_t<std::is_integral_v<T>, int, double>; storage_type data; };5. 对齐、内存布局,条件选择对齐类型
// 是否启用simd:true用__m128,否则用float[4] template<bool UseSimd> using Vec4 = std::conditional_t<UseSimd, __m128, float[4]>;6. 元编程分支,类型列表、递归元编程
在模板元编程循环中,做终止条件判断。
// 元编程:取第N个类型(极简示意) template<int N, typename...Args> struct NthType; template<int N, typename Head, typename...Tail> struct NthType<N,Head,Tail...> { using type = typename std::conditional_t< N == 0, std::type_identity<Head>, NthType<N-1, Tail...> >::type; };这里通过原编程,从参数包Args...取出第N个类型,作用:类型包装器,把 T 包一层壳,内部别名::type还原成 T。
type_identity<int>::type → int type_identity_t<double> → double这里说明,std::type_identity是在C++20 引入,头文件<type_traits>,
7. 两边类型都会实例化,不会短路
// 即使条件false,false分支的类型依然会实例化,直接编译报错 using Bad = std::conditional_t<false, typename T::no_such_type, int>;解决:用std::type_identity惰性包装,推迟实例化。
template<bool Cond,typename T,typename U> using lazy_cond_t = typename std::conditional_t<Cond,std::type_identity<T>,std::type_identity<U>>::type;