1. 程式人生 > >Boost中Core模組的enable_if用法及說明

Boost中Core模組的enable_if用法及說明

標頭檔案

boost/utility/enable_if.hpp

作用

enable_if,lazy_enable_if,disable_if,lazy_disable_if 作用說明

enable_if 說明

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

當Cond::value為真,enable_if,才會有型別type,且type為 T型別。

lazy_enable_if 說明

template <class Cond, class T> 
  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};

當Cond::value為真,lazy_enable_if,才會有型別T::type,常常與boost其他模組搭配使用。

disable_if 說明

template <class Cond, class T = void> 
  struct disable_if : public disable_if_c<Cond::value, T> {};

當Cond::value為假,disable_if,才會有型別type,且type為 T型別。

lazy_disable_if  說明

template <class Cond, class T> 
  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};

當Cond::value為假,lazy_disable_if,才會有型別T::type,常常與boost其他模組搭配使用。

enable_if,lazy_enable_if,disable_if,lazy_disable_if ,從本質上說,都是為了將不符合要求的引數剔除,傳遞了不符合要求的引數,在編譯期間會報錯。常常用於 模板類或模板函式的型參 型別,或者是 返回值 型別。

舉例

enable_if,disable_if模板類 建構函式 型參

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/detail/lightweight_test.hpp>

using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;

struct container {
  bool my_value;

  template <class T>
  container(const T&, const typename enable_if<is_arithmetic<T>, T>::type * = 0):
  my_value(true) {}

  template <class T>
  container(const T&, const typename disable_if<is_arithmetic<T>, T>::type * = 0):
  my_value(false) {}
};

// example from Howard Hinnant (tests enable_if template members of a templated class)
template <class charT>
struct xstring
{
  template <class It>
  xstring(It begin, It end, typename 
          disable_if<is_arithmetic<It> >::type* = 0)
    : data(end-begin) {}
  
  int data;
};


int main()
{
 
  BOOST_TEST(container(1).my_value);
  BOOST_TEST(container(1.0).my_value);

  BOOST_TEST(!container("1").my_value);  
  BOOST_TEST(!container(static_cast<void*>(0)).my_value);  

  char sa[] = "123456";
  BOOST_TEST(xstring<char>(sa, sa+6).data == 6);


  return boost::report_errors();
}

enable_if,disable_if模板函式 返回值

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/detail/lightweight_test.hpp>

using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;

template <int N> struct dummy {
  dummy(int) {};
};

template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<0> = 0) { return true; }

template<class T>
typename disable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<1> = 0) { return false; }


int main()
{
 
  BOOST_TEST(arithmetic_object(1));
  BOOST_TEST(arithmetic_object(1.0));

  BOOST_TEST(!arithmetic_object("1"));  
  BOOST_TEST(!arithmetic_object(static_cast<void*>(0)));  

  return boost::report_errors();
}

lazy_enable_if

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/lightweight_test.hpp>

using boost::lazy_enable_if;
using boost::lazy_disable_if;

using boost::lazy_enable_if_c;
using boost::lazy_disable_if_c;


template <class T>
struct is_int_or_double {
  BOOST_STATIC_CONSTANT(bool, 
    value = (boost::is_same<T, int>::value || 
             boost::is_same<T, double>::value));
};

template <class T>
struct some_traits {
  typedef typename T::does_not_exist type;
};

template <>
struct some_traits<int> {
  typedef bool type;
};

template <>
struct some_traits<double> {
  typedef bool type;
};

template <class T>
struct make_bool {
  typedef bool type;
};

template <>
struct make_bool<int> {};

template <>
struct make_bool<double> {};

namespace A {

  template<class T>
  typename lazy_enable_if<is_int_or_double<T>, some_traits<T> >::type
  foo(T t) { return true; }

  template<class T>
  typename lazy_enable_if_c<is_int_or_double<T>::value, some_traits<T> >::type
  foo2(T t) { return true; }
}

namespace B {
  template<class T>
  typename lazy_disable_if<is_int_or_double<T>, make_bool<T> >::type
  foo(T t) { return false; }

  template<class T>
  typename lazy_disable_if_c<is_int_or_double<T>::value, make_bool<T> >::type
  foo2(T t) { return false; }
}

int main()
{
  using namespace A;
  using namespace B;
  BOOST_TEST(foo(1));
  BOOST_TEST(foo(1.0));

  BOOST_TEST(!foo("1"));  
  BOOST_TEST(!foo(static_cast<void*>(0)));  

  BOOST_TEST(foo2(1));
  BOOST_TEST(foo2(1.0));

  BOOST_TEST(!foo2("1"));  
  BOOST_TEST(!foo2(static_cast<void*>(0)));  

  return boost::report_errors();
}

原始碼

namespace boost
{
  template<typename T, typename R=void>
  struct enable_if_has_type
  {
    typedef R type;
  };
 
  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> {};

  template <bool B, class T>
  struct lazy_enable_if_c {
    typedef typename T::type type;
  };

  template <class T>
  struct lazy_enable_if_c<false, T> {};

  template <class Cond, class T> 
  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};


  template <bool B, class T = void>
  struct disable_if_c {
    typedef T type;
  };

  template <class T>
  struct disable_if_c<true, T> {};

  template <class Cond, class T = void> 
  struct disable_if : public disable_if_c<Cond::value, T> {};

  template <bool B, class T>
  struct lazy_disable_if_c {
    typedef typename T::type type;
  };

  template <class T>
  struct lazy_disable_if_c<true, T> {};

  template <class Cond, class T> 
  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};

} // namespace boost