• C++模板之std::enable_if,函数模板的多态


    中文标准库:enable_if

    一、模板原型

    template< bool B, class T = void >
    struct enable_if;
    

    当B为true时,则std::enable_if拥有等同于T的公开成员typedef type(即enable_if<B,T>::type);否则,无该成员typedef(VS会报错)

    二、示例

    void fun(){}
    
    int testFunc()
    {
        std::enable_if<std::is_function<decltype(fun)>::value, int>::type tt;  //这句相当于int tt;
        std::enable_if<std::is_function<int>::value, int>::type tt;  //报错,提示enable_if<false,int>没有成员type
    }
    

    三、用途

    转载:std::enable_if的几种用法

    1. 类型偏特化

    在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。例如:

    template <typename T, typename Enable=void>
    struct check;
     
    template <typename T>
    struct check<T, typename std::enable_if<T::value>::type> {
      static constexpr bool value = T::value;
    };
    

    上述的 check 只希望选择 value==true 的 T,否则就报编译时错误。如果想给用户更友好的提示,可以提供结构体的原型定义,并在其中进行static_assert静态检查,给出更明确的字符串说明。

    2. 控制函数返回类型

    对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看tuple的获取第k个元素的get函数:

    template <std::size_t k, class T, class... Ts>
    typename std::enable_if<k==0, typename element_type_holder<0, T, Ts...>::type&>::type
    get(tuple<T, Ts...> &t) 
    {
      return t.tail; 
    }
    template <std::size_t k, class T, class... Ts>
    typename std::enable_if<k!=0, typename element_type_holder<k, T, Ts...>::type&>::type
    get(tuple<T, Ts...> &t) 
    {
      tuple<Ts...> &base = t;
      return get<k-1>(base); 
    }
    

    由于函数模板不能偏特化,通过 enable_if 便可以根据 k 值的不同情况选择调用哪个 get,进而实现函数模板的多态

    3. 校验函数模板参数类型

    有时定义的模板函数,只希望特定的类型可以调用,参考cppreference官网示例,很好的说明了如何限制只有整型可以调用的函数定义:

    template <typename T>
    typename std::enable_if<std::is_const<T>::value&& std::is_integral<T>::value,const int>::type
    get(T t)
    {   //只有当T的类型为const int时,才可以调用get函数
    	return t;
    }
    
    template <typename T>
    typename std::enable_if<std::is_integral<T>::value, bool>::type
    is_odd(T t)
    {   //偶数返回false
        return bool(t % 2);
    }
    
    template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
    bool is_even(T t)
    {   //偶数返回true
        return !is_odd(t);
    }
    
    int main()
    {
        std::cout<<get<const int>(2); 
        //std::cout << get<const float>(2.0);  //报错
        std::cout << is_odd<int>(2);  //false
        std::cout << is_even<int>(2); //true
    }
    

    一个通过返回值,一个通过默认模板参数,都可以实现校验模板参数是整型的功能。

  • 相关阅读:
    selet 语句详解
    第三章 sql 的约束
    第二章 创建数据库并插入数据
    第一章
    微信小程序(九)
    微信小程序(七)
    微信小程序(八)
    微信小程序(六)
    bzoj4622 [NOI 2003] 智破连环阵
    bzoj3996 [TJOI2015]线性代数
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/15251584.html
Copyright © 2020-2023  润新知