C++规范编码引涉语法点 之(1):std::enable_if

         std::enable_if 顾名思义,满足条件时类型有效。作为选择类型的小工具,其广泛的应用在 C++ 的模板元编程(meta programming)中。它的定义也异常的简单:

template <bool, typename T=void>
struct enable_if {
};
 
template <typename T>
struct enable_if<true, T> {
  using type = T;
};

        由上可知,只有当第一个模板参数为 true 时,type 才有定义,否则使用 type 会产生编译错误,并且默认模板参数可以让你不必指定类型。下面说说它的几种使用方法:

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

'''上述的 check 只希望选择 value==true 的 T,否则就报编译时错误。
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;
};

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

'''由于函数模板不能偏特化,通过 enable_if 便可以根据 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); //很奇怪为什么能编译通过,本地测试确实可以编译通过。难道是编译器对模板的语法检查不够严格吗
}

用法三:校验函数模板参数类型 (同用法一)
有时定义的模板函数,只希望特定的类型可以调用。示例代码很好的说明了如何限制只有整型可以调用的函数定义:

'''一个通过返回值,一个通过默认模板参数,都可以实现校验模板参数是整型的功能。
template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
is_odd(T t) {
  return bool(t%2);
}
 
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even(T t) {
  return !is_odd(t); 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`std::enable_if` 是 C++11 标准库中的一个模板元编程工具,用于在编译期根据某个条件来选择是否启用某个函数。它通常与函数模板一起使用,用于对函数模板进行条件限定。当条件满足时,函数模板才能被实例化。 `std::enable_if` 的基本语法如下: ```c++ template<bool B, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; ``` 其中第一个模板定义了一个空类型 `enable_if`,它有两个模板参数:一个布尔类型 `B` 和一个任意类型 `T`,默认为 `void`。第二个模板是一个特化模板,当 `B` 为 `true` 时,它定义了一个名为 `type` 的 `T` 类型别名。 下面是一个使用 `std::enable_if` 的示例: ```c++ #include <iostream> #include <type_traits> template <typename T> typename std::enable_if<std::is_integral<T>::value, T>::type add(T a, T b) { return a + b; } int main() { std::cout << add(1, 2) << std::endl; // 输出 3 // std::cout << add(1.0, 2.0) << std::endl; // 编译错误,因为 double 不是整数类型 return 0; } ``` 在这个示例中,`add` 函数使用了 `std::enable_if` 进行条件限定,只有当模板参数 `T` 是整数类型时,才能被实例化。当 `T` 是整数类型时,返回类型是 `T`,否则编译器会报错。 需要注意的是,`std::enable_if` 只是一个工具,它并不会在运行时对代码进行任何操作。它只是在编译期根据某个条件来决定是否启用某个函数模板。因此,它只能用于编译期的条件判断,不能用于运行时的条件判断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值