头文件
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