diff --git a/enable_if.html b/enable_if.html new file mode 100644 index 0000000..349189e --- /dev/null +++ b/enable_if.html @@ -0,0 +1,417 @@ + + +
+namespace boost { + template <class Cond, class T = void> struct enable_if; + template <class Cond, class T = void> struct disable_if; + template <class Cond, class T> struct lazy_enable_if; + template <class Cond, class T> struct lazy_disable_if; + + template <bool B, class T = void> struct enable_if_c; + template <bool B, class T = void> struct disable_if_c; + template <bool B, class T> struct lazy_enable_if_c; + template <bool B, class T> struct lazy_disable_if_c; +} ++ + +
+ +int negate(int i) { return -i; } + +template <class F> +typename F::result_type negate(const F& f) { return -f(); } + ++Suppose the compiler encounters the call negate(1). The first +definition is obviously a better match, but the compiler must +nevertheless consider (and instantiate the prototypes) of both +definitions to find this out. Instantiating the latter definition with +F as int would result in: +
+ +int::result_type negate(const int&); + ++where the return type is invalid. If this was an error, adding an unrelated function template +(that was never called) could break otherwise valid code. +Due to the SFINAE principle the above example is not, however, erroneous. +The latter definition of negate is simply removed from the overload resolution set.
+ +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> {}; + ++An instantiation of the enable_if_c template with the parameter +B as true contains a member type type, defined +to be T. If B is +false, no such member is defined. Thus +enable_if_c<B, T>::type is either a valid or an invalid type +expression, depending on the value of B. +When valid, enable_if_c<B, T>::type equals T. +The enable_if_c template can thus be used for controlling when functions are considered for +overload resolution and when they are not. +For example, the following function is defined for all arithmetic types (according to the +classification of the Boost type_traits library): +
+ +template <class T> +typename enable_if_c<boost::is_arithmetic<T>::value, T>::type +foo(T t) { return t; } + ++The disable_if_c template is provided as well, and has the +same functionality as enable_if_c except for the negated condition. The following +function is enabled for all non-arithmetic types. +
+ +template <class T> +typename disable_if_c<boost::is_arithmetic<T>::value, T>::type +bar(T t) { return t; } + ++For easier syntax in some cases and interoperation with Boost.MPL we provide versions of +the enable_if templates taking any type with a bool member constant named +value as the condition argument. +The MPL bool_, and_, or_, and not_ templates are likely to be +useful for creating such types. Also, the traits classes in the Boost.Type_traits library +follow this convention. +For example, the above example function foo can be alternatively written as: +
+ +template <class T> +typename enable_if<boost::is_arithmetic<T>, T>::type +foo(T t) { return t; } + ++ + +
+ +template <class T> +T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0); + +Hence, an extra parameter of type void* is added, but it is given +a default value to keep the parameter hidden from client code. +Note that the second template argument was not given to enable_if, as the default +void gives the desired behavior.
+ +template <class T, class Enable = void> +class A { ... }; + +template <class T> +class A<T, typename enable_if<is_integral<T> >::type> { ... }; + +template <class T> +class A<T, typename enable_if<is_float<T> >::type> { ... }; + +Instantiating A with any integral type matches the first specialization, +whereas any floating point type matches the second one. All other types +match the primary template. +The condition can be any compile-time boolean expression that depends on the +template arguments of the class. +Note that again, the second argument to enable_if is not needed; the default (void) +is the correct value.
+ +template <class T> +typename enable_if<boost::is_integral<T>, void>::type +foo(T t) {} + +template <class T> +typename enable_if<boost::is_arithmetic<T>, void>::type +foo(T t) {} + ++All integral types are also arithmetic. Therefore, say, for the call foo(1), +both conditions are true and both functions are thus in the overload resolution set. +They are both equally good matches and thus ambiguous. +Of course, more than one enabling condition can be simultaneously true as long as +other arguments disambiguate the functions.
+ +template <class T, class U> class mult_traits; + +template <class T, class U> +typename enable_if<is_multipliable<T, U>, typename mult_traits<T, U>::type>::type +operator*(const T& t, const U& u) { ... } + +Assume the class template mult_traits is a traits class defining +the resulting type of a multiplication operator. The is_multipliable traits +class specifies for which types to enable the operator. Whenever +is_multipliable<A, B>::value is true for some types A and B, +then mult_traits<A, B>::type is defined.
+ +template<class T, class U> +typename lazy_enable_if<is_multipliable<T, U>, mult_traits<T, U> >::type +operator*(const T& t, const U& u) { ... } + +The second argument of lazy_enable_if must be a class type +that defines a nested type named type whenever the first +parameter (the condition) is true.
+ +template <class T> +typename enable_if<boost::is_arithmetic<T>, T>::type +foo(T t); + +template <class T> +typename disable_if<boost::is_arithmetic<T>, T>::type +foo(T t); + +Two workarounds can be applied: +
+ +template <class T> struct dummy { dummy(int) {} }; + +template <class T> +typename enable_if<boost::is_arithmetic<T>, T>::type +foo(T t, dummy<0> = 0); + +template <class T> +typename disable_if<boost::is_arithmetic<T>, T>::type +foo(T t, dummy<1> = 0); +
+ +namespace A { + template <class T> + typename enable_if<boost::is_arithmetic<T>, T>::type + foo(T t); +} + +namespace B { + template <class T> + typename disable_if<boost::is_arithmetic<T>, T>::type + foo(T t); +} + +using A::foo; +using B::foo; + ++Note that the second workaround above cannot be used for member +templates. On the other hand, operators do not accept extra arguments, +which makes the first workaround unusable. As the net effect, +neither of the workarounds are of assistance for templated operators that +need to be defined as member functions (assignment and +subscript operators). +
This document was translated from LATEX by +HEVEA. ++ + diff --git a/include/boost/utility/enable_if.hpp b/include/boost/utility/enable_if.hpp new file mode 100644 index 0000000..c1f217d --- /dev/null +++ b/include/boost/utility/enable_if.hpp @@ -0,0 +1,69 @@ +// Boost enable_if library + +// Copyright 2003 © The Trustees of Indiana University. + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) +// Jeremiah Willcock (jewillco at osl.iu.edu) +// Andrew Lumsdaine (lums at osl.iu.edu) + + +#ifndef BOOST_UTILITY_ENABLE_IF_HPP +#define BOOST_UTILITY_ENABLE_IF_HPP + +namespace boost +{ + + template