diff --git a/enable_if.html b/enable_if.html index 349189e..eb485c5 100644 --- a/enable_if.html +++ b/enable_if.html @@ -4,7 +4,7 @@
-namespace boost { +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; @@ -68,9 +67,7 @@ template, the instantiation is removed from the overload resolution set instead of causing a compilation error. The following example, taken from [1], demonstrates why this is important: -- -int negate(int i) { return -i; } +int negate(int i) { return -i; } template <class F> typename F::result_type negate(const F& f) { return -f(); } @@ -81,9 +78,7 @@ 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&); +int::result_type negate(const int&);where the return type is invalid. If this was an error, adding an unrelated function template @@ -111,9 +106,7 @@ The latter version interoperates with Boost.MPL.
The definitions of enable_if_c and enable_if are as follows (we use enable_if templates unqualified but they are in the boost namespace). -- -template <bool B, class T = void> +template <bool B, class T = void> struct enable_if_c { typedef T type; }; @@ -136,9 +129,7 @@ The enable_if_c template can thus be used for controlling when function 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> +template <class T> typename enable_if_c<boost::is_arithmetic<T>::value, T>::type foo(T t) { return t; } @@ -146,9 +137,7 @@ 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> +template <class T> typename disable_if_c<boost::is_arithmetic<T>::value, T>::type bar(T t) { return t; } @@ -160,9 +149,7 @@ The MPL bool_, and_, or_, and not_ templates 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> +template <class T> typename enable_if<boost::is_arithmetic<T>, T>::type foo(T t) { return t; } @@ -178,9 +165,7 @@ The enable_if templates are defined in The enable_if template can be used either as the return type, or as an extra argument. For example, the foo function in the previous section could also be written as: -- -template <class 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 @@ -206,9 +191,7 @@ Class template specializations can be enabled or disabled with enable_ifvoid. For example: -- -template <class T, class Enable = void> +template <class T, class Enable = void> class A { ... }; template <class T> @@ -236,9 +219,7 @@ rules are used to select the best matching function. In particular, there is no ordering between enabling conditions. Function templates with enabling conditions that are not mutually exclusive can lead to ambiguities. For example: -- -template <class T> +template <class T> typename enable_if<boost::is_integral<T>, void>::type foo(T t) {} @@ -263,9 +244,7 @@ partial specializations as well.
In some cases it is necessary to avoid instantiating part of a function signature unless an enabling condition is true. For example: -- -template <class T, class U> class mult_traits; +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 @@ -284,9 +263,7 @@ The SFINAE principle is not applied because the invalid type occurs as an argument to another template. The lazy_enable_if and lazy_disable_if templates (and their _c versions) can be used in such situations: -- -template<class T, class U> +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) { ... } @@ -314,9 +291,7 @@ above example, is_multipliable<T, U>::value defines when Some compilers flag functions as ambiguous if the only distinguishing factor is a different condition in an enabler (even though the functions could never be ambiguous). For example, some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous: -- -template <class T> +template <class T> typename enable_if<boost::is_arithmetic<T>, T>::type foo(T t); @@ -328,9 +303,7 @@ foo(T t);
- -template <class T> struct dummy { dummy(int) {} }; +template <class T> struct dummy { dummy(int) {} }; template <class T> typename enable_if<boost::is_arithmetic<T>, T>::type @@ -343,9 +316,7 @@ foo(T t, dummy<1> = 0);
- -namespace A { +namespace A { template <class T> typename enable_if<boost::is_arithmetic<T>, T>::type foo(T t); @@ -414,4 +385,4 @@ Open Systems Lab HEVEA. -