std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系

Posted ithiker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系相关的知识,希望对你有一定的参考价值。

标准库与boost的这三个enable_if系列的函数可以帮助我们实现模板函数的重载。

一般函数的重载

先看一个一般函数重载的例子:

#include <iostream>

void print(int i)

  std::cout << "Integral: " << i << std::endl;


void print(double f)

  std::cout << "Floating point: " << f << std::endl;


int main()

  print(42);
  print(3.14);
 


上面的代码是一般函数的重载,程序会根据函数的参数类型进行匹配,执行相对应的函数。
但如果上面的print是类模板函数,是否可以实现类似的功能呢,比如:

template <typename T>
void print(T f)

  std::cout << "Floating point: " << f << std::endl;

当类型T为double类型时调用上面参数为3.14对应的函数,当类型T为int时调用上面参数为42对应的函数,显然,如果将上面的参数统一替换为T,:

template <typename T>
void print(T f)

  std::cout << "Floating point: " << f << std::endl;



template <typename T>
void print(T f)

    std::cout << "Integral: " << i << std::endl;

对同一个模板函数将会有两份定义,编译时将会报错:redefinition of 'template void print(T)
那么,我们是否有办法在模板参数是某个类型时才生成对应类型的代码。std::enable_if与boost就是来帮住实现类似功能的。

std::enable_if的作用

先看std::enable_if的定义

std::enable_if本身是一个模板类,有两个模板参数,第一个是一个bool型的非类型参数,第二个为类型参数T,当bool值为true时,std::enable_if会定义一个public类型的typedef type, 和T相同,一个可能的实现是:

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

它的作用是,如果条件为真,则声明类型T的类型为type, 后续对type的使用因而是有效的;如果条件为假,则不做任何事(使用默认的类模板示例化),后续对type的使用因而是无效的。
这样,如果我们有判断类型的方法,那么,我们就很容易实现我们想要的功能了。
C++11引入了大量的判断类型的type traits

利用上面的type traits, 代码改写为如下,将可以很容易的编译通过:

#include <type_traits>
#include <iostream>

template <typename T>
void print(typename std::enable_if<std::is_integral<T>::value, T>::type i)

  std::cout << "Integral: " << i << '\\n';


template <typename T>
void print(typename std::enable_if<std::is_floating_point<T>::value, T>::type f)

  std::cout << "Floating point: " << f << '\\n';




int main()

  print<short>(1);
  print<long>(2);
  print<double>(3.14);


std::enable_if与boost::enable_if的区别

查看boost::enable_if的声明

template <class Cond, class T = void> struct enable_if;

发现其第一个参数为类型, 再查看boost::enable_if_c的声明和定义:

template <bool B, class T = void>
struct enable_if_c 
    typedef T type;
;

template <class T>
struct enable_if_c<false, T> ;

template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> ;

boost::enable_if_c其实和std::enable_if是等价的
c++14中定义了std::enable_if_t如下

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;

std::enable_if_t是std::enable_if的一个type alias, std::enable_if_t和boost::enable_if是相似的,但不是等价的。
std::enable_if_t的最大优点是可以将其当作一个type,比如:

typename std::enable_if_t<std::is_floating_point<T>::value, T>

等价于

typename std::enable_if<std::is_floating_point<T>::value, T>::type

例子

将上面std::enable_if版本的代码改为boost::enable_if,boost::enable_if_c, std::enable_if_t版本的,分别为:

boost::enable_if例子

#include <boost/utility/enable_if.hpp>
#include <type_traits>
#include <iostream>

template <typename T>
void print(typename boost::enable_if<std::is_integral<T>, T>::type i)

  std::cout << "Integral: " << i << '\\n';


template <typename T>
void print(typename boost::enable_if<std::is_floating_point<T>, T>::type f)

  std::cout << "Floating point: " << f << '\\n';


int main()

  print<short>(1);
  print<long>(2);
  print<double>(3.14);

boost::enable_if_c例子

#include <boost/utility/enable_if.hpp>
#include <type_traits>
#include <iostream>

template <typename T>
void print(typename boost::enable_if_c<std::is_integral<T>::value, T>::type i)

  std::cout << "Integral: " << i << '\\n';


template <typename T>
void print(typename boost::enable_if_c<std::is_floating_point<T>::value, T>::type f)

  std::cout << "Floating point: " << f << '\\n';


int main()

  print<short>(1);
  print<long>(2);
  print<double>(3.14);

std::enable_if_t例子

#include <type_traits>
#include <iostream>

template <typename T>
void print(typename std::enable_if_t<std::is_integral<T>::value, T> i)

  std::cout << "Integral: " << i << '\\n';


template <typename T>
void print(typename std::enable_if_t<std::is_floating_point<T>::value, T> f)

  std::cout << "Floating point: " << f << '\\n';


int main()

  print<short>(1);
  print<long>(2);
  print<double>(3.14);

这里有对应的示例代码。

以上是关于std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系的主要内容,如果未能解决你的问题,请参考以下文章

std::enable_if与boost::enable_if,boost::enable_if_c的区别与联系

std::enable_if的错误使用方法

Visual Studio 2013 - std::enable_if 警告 4544

SWIG C++/Python 绑定和支持带有 std::enable_if 的条件成员

std::enable_if 在模板参数上确定 STL 容器

C++ std::enable_if解析