diff --git a/doc/checked_delete.qbk b/doc/checked_delete.qbk index b168261..09a0c74 100644 --- a/doc/checked_delete.qbk +++ b/doc/checked_delete.qbk @@ -37,7 +37,7 @@ namespace boost [section checked_delete] -[section `template void checked_delete(T * p);`] +[section template void checked_delete(T * p);] * *Requires:* *T* must be a complete type. The expression `delete p` must be well-formed. @@ -49,7 +49,7 @@ namespace boost [section checked_array_delete] -[section `template void checked_array_delete(T * p);`] +[section template void checked_array_delete(T * p);] * *Requires:* *T* must be a complete type. The expression `delete [] p` must be well-formed. @@ -70,7 +70,7 @@ template struct checked_deleter }; `` -[section `void checked_deleter::operator()(T * p) const;`] +[section void checked_deleter::operator()(T * p) const;] * *Requires:* `T` must be a complete type. The expression `delete p` must be well-formed. @@ -91,10 +91,11 @@ template struct checked_array_deleter }; `` -[section `void checked_array_deleter::operator()(T * p) const;`] +[section void checked_array_deleter::operator()(T * p) const;] + * *Requires:* `T` must be a complete type. The expression `delete [] p` must be well-formed. -* `Effects:` `delete [] p;` +* *Effects:* `delete [] p;` [endsect] diff --git a/doc/core.qbk b/doc/core.qbk index d204081..64f2ffa 100644 --- a/doc/core.qbk +++ b/doc/core.qbk @@ -34,9 +34,15 @@ Currently, the Core library contains: [`boost::checked_delete`] ] [ - [[@../../enable_if.html enable_if]] + [[link core.enable_if enable_if]] [`boost::enable_if`] ] + [ + [[link core.explicit_operator_bool explicit_operator_bool]] + [`BOOST_EXPLICIT_OPERATOR_BOOL, + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT, + BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL`] + ] [ [[link core.ignore_unused ignore_unused]] [`boost::ignore_unused`] @@ -54,6 +60,10 @@ Currently, the Core library contains: [[link core.noncopyable noncopyable]] [`boost::noncopyable`] ] + [ + [[link core.null_deleter null_deleter]] + [`boost::null_deleter`] + ] [ [ref] [`boost::ref`] @@ -62,26 +72,17 @@ Currently, the Core library contains: [[link core.swap swap]] [`boost::swap`] ] - [ - [[link core.null_deleter null_deleter]] - [`boost::null_deleter`] - ] - [ - [[link core.explicit_operator_bool explicit_operator_bool]] - [`BOOST_EXPLICIT_OPERATOR_BOOL, - BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT, - BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL`] - ] ] [endsect] [include:core addressof.qbk] [include:core checked_delete.qbk] +[include:core enable_if.qbk] [include:core explicit_operator_bool.qbk] [include:core ignore_unused.qbk] [include:core lightweight_test.qbk] [include:core no_exceptions_support.qbk] [include:core noncopyable.qbk] -[include:core swap.qbk] [include:core null_deleter.qbk] +[include:core swap.qbk] diff --git a/doc/enable_if.qbk b/doc/enable_if.qbk new file mode 100644 index 0000000..3416513 --- /dev/null +++ b/doc/enable_if.qbk @@ -0,0 +1,461 @@ +[section:enable_if Header ] + +[section Introduction] + +The `enable_if` family of templates is a set of tools to allow +a function template or a class template specialization to +include or exclude itself from a set of matching functions or +specializations based on properties of its template arguments. +For example, one can define function templates that are only +enabled for, and thus only match, an arbitrary set of types +defined by a traits class. The `enable_if` templates can also +be applied to enable class template specializations. +Applications of `enable_if` are discussed in length in +[link REF1 \[1\]] and [link REF2 \[2\]]. + +[section Synopsis] + +`` +namespace boost { + template struct enable_if; + template struct disable_if; + template struct lazy_enable_if; + template struct lazy_disable_if; + + template struct enable_if_c; + template struct disable_if_c; + template struct lazy_enable_if_c; + template struct lazy_disable_if_c; +} +`` + +[endsect] + +[section Background] + +Sensible operation of template function overloading in C++ +relies on the /SFINAE/ (substitution-failure-is-not-an-error) +principle [link REF3 \[3\]]: if an invalid argument or return +type is formed during the instantiation of a function template, +the instantiation is removed from the overload resolution set +instead of causing a compilation error. The following example, +taken from [link REF1 \[1\]], demonstrates why this is +important: + +`` +int negate(int i) { return -i; } + +template +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 were 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. + +The `enable_if` templates are tools for controlled creation of +the SFINAE conditions. + +[endsect] + +[endsect] + +[section The enable_if templates] + +The names of the `enable_if` templates have three parts: an +optional `lazy_` tag, either `enable_if` or `disable_if`, and +an optional `_c` tag. All eight combinations of these parts +are supported. The meaning of the `lazy_` tag is described +in the section [link +core.enable_if.using_enable_if.enable_if_lazy below]. The +second part of the name indicates whether a true condition +argument should enable or disable the current overload. The +third part of the name indicates whether the condition +argument is a `bool` value (`_c` suffix), or a type containing +a static `bool` constant named `value` (no suffix). 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 +struct enable_if_c { + typedef T type; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c {}; +`` + +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::type` is either a valid or an invalid type +expression, depending on the value of `B`. When valid, +`enable_if_c::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 +typename enable_if_c::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 +typename disable_if_c::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 +typename enable_if, T>::type +foo(T t) { return t; } +`` + +[endsect] + +[section:using_enable_if Using enable_if] + +The `enable_if` templates are defined in +`boost/utility/enable_if.hpp`, which is included by +`boost/utility.hpp`. + +With respect to function templates, `enable_if` can be used in +multiple different ways: + +* As the return type of an instantiatied function +* As an extra parameter of an instantiated function +* As an extra template parameter (useful only in a compiler + that supports C++0x default arguments for function template + parameters, see [link + core.enable_if.using_enable_if.enable_if_0x Enabling function + templates in C++0x] for details. + +In the previous section, the return type form of `enable_if` +was shown. As an example of using the form of `enable_if` that +works via an extra function parameter, the `foo` function in +the previous section could also be written as: + +`` +template +T foo(T t, + typename enable_if >::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. + +Which way to write the enabler is largely a matter of taste, +but for certain functions, only a subset of the options is +possible: + +* Many operators have a fixed number of arguments, thus + `enable_if` must be used either in the return type or in an + extra template parameter. +* Functions that have a variadic parameter list must use either + the return type form or an extra template parameter. +* Constructors do not have a return type so you must use either + an extra function parameter or an extra template parameter. +* Constructors that have a variadic parameter list must an + extra template parameter. +* Conversion operators can only be written with an extra + template parameter. + +[section:enable_if_0x Enabling function templates in C++0x] + +In a compiler which supports C++0x default arguments for +function template parameters, you can enable and disable +function templates by adding an additional template parameter. +This approach works in all situations where you would use +either the return type form of `enable_if` or the function +parameter form, including operators, constructors, variadic +function templates, and even overloaded conversion operations. + +As an example: + +`` +#include +#include +#include + +class test +{ +public: + // A constructor that works for any argument list of size 10 + template< class... T, + typename boost::enable_if_c< sizeof...( T ) == 10, + int >::type = 0> + test( T&&... ); + + // A conversion operation that can convert to any arithmetic type + template< class T, + typename boost::enable_if< boost::is_arithmetic< T >, + int >::type = 0> + operator T() const; + + // A conversion operation that can convert to any pointer type + template< class T, + typename boost::enable_if< boost::is_pointer< T >, + int >::type = 0> + operator T() const; +}; + +int main() +{ + // Works + test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ); + + // Fails as expected + test fail_construction( 1, 2, 3, 4, 5 ); + + // Works by calling the conversion operator enabled for arithmetic types + int arithmetic_object = test_; + + // Works by calling the conversion operator enabled for pointer types + int* pointer_object = test_; + + // Fails as expected + struct {} fail_conversion = test_; +} +`` + +[endsect] + +[section Enabling template class specializations] + +Class template specializations can be enabled or disabled with +`enable_if`. One extra template parameter needs to be added for +the enabler expressions. This parameter has the default value +`void`. For example: + +`` +template +class A { ... }; + +template +class A >::type> { ... }; + +template +class A >::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. + +[endsect] + +[section Overlapping enabler conditions] + +Once the compiler has examined the enabling conditions and +included the function into the overload resolution set, normal +C++ overload resolution 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 +typename enable_if, void>::type +foo(T t) {} + +template +typename enable_if, 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. + +The above discussion applies to using `enable_if` in class +template partial specializations as well. + +[endsect] + +[section:enable_if_lazy Lazy enable_if] + +In some cases it is necessary to avoid instantiating part of a +function signature unless an enabling condition is true. For +example: + +`` +template class mult_traits; + +template +typename enable_if, + typename mult_traits::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::value` is +`true` for some types `A` and `B`, then +`mult_traits::type` is defined. + +Now, trying to invoke (some other overload) of `operator*` +with, say, operand types `C` and `D` for which +`is_multipliable::value` is `false` and +`mult_traits::type` is not defined is an error on some +compilers. 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 +typename lazy_enable_if, + mult_traits >::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. + +[note Referring to one member type or static constant in a +traits class causes all of the members (type and static +constant) of that specialization to be instantiated. +Therefore, if your traits classes can sometimes contain invalid +types, you should use two distinct templates for describing the +conditions and the type mappings. In the above example, +`is_multipliable::value` defines when +`mult_traits::type` is valid.] + +[endsect] + +[section Compiler workarounds] + +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 +typename enable_if, T>::type +foo(T t); + +template +typename disable_if, T>::type +foo(T t); +`` + +Two workarounds can be applied: + +* Use an extra dummy parameter which disambiguates the + functions. Use a default value for it to hide the parameter + from the caller. For example: + `` + template struct dummy { dummy(int) {} }; + + template + typename enable_if, T>::type + foo(T t, dummy<0> = 0); + + template + typename disable_if, T>::type + foo(T t, dummy<1> = 0); + `` +* Define the functions in different namespaces and bring them + into a common namespace with `using` declarations: + `` + namespace A { + template + typename enable_if, T>::type + foo(T t); + } + + namespace B { + template + typename disable_if, 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). + +[endsect] + +[endsect] + +[section Acknowledgements] + +We are grateful to Howard Hinnant, Jason Shirk, Paul +Mensonides, and Richard Smith whose findings have +influenced the library. + +[endsect] + +[section References] + +* [#REF1] \[1\] Jaakko J\u00E4rvi, Jeremiah Willcock, Howard + Hinnant, and Andrew Lumsdaine. Function overloading based on + arbitrary properties of types. /C++ Users Journal/, + 21(6):25--32, June 2003. +* [#REF2] \[2\] Jaakko J\u00E4rvi, Jeremiah Willcock, and + Andrew Lumsdaine. Concept-controlled polymorphism. In Frank + Pfennig and Yannis Smaragdakis, editors, /Generative + Programming and Component Engineering/, volume 2830 of + /LNCS/, pages 228--244. Springer Verlag, September 2003. +* [#REF3] \[3\] David Vandevoorde and Nicolai M. Josuttis. + /C++ Templates: The Complete Guide/. Addison-Wesley, 2002. + +[endsect] + +[endsect] diff --git a/doc/lightweight_test.qbk b/doc/lightweight_test.qbk index fa8f4c4..8f7ce9a 100644 --- a/doc/lightweight_test.qbk +++ b/doc/lightweight_test.qbk @@ -1,33 +1,55 @@ [section:lightweight_test Header ] -If expression is false increases the error count and outputs a -message containing `expression`. +[section BOOST_TEST] `` BOOST_TEST(expression) `` -Increases error count and outputs a message containing -`message`. +If expression is false increases the error count and outputs a +message containing `expression`. + +[endsect] + +[section BOOST_ERROR] `` BOOST_ERROR(message) `` -If `expr1` != `expr2` increases the error count and outputs a -message containing both expressions. +Increases error count and outputs a message containing +`message`. + +[endsect] + +[section BOOST_TEST_EQ] `` BOOST_TEST_EQ(expr1, expr2) `` -If `expr1` == `expr2` increases the error count and outputs a +If `expr1` != `expr2` increases the error count and outputs a message containing both expressions. +[endsect] + +[section BOOST_TEST_NE] + `` BOOST_TEST_NE(expr1, expr2) `` +If `expr1` == `expr2` increases the error count and outputs a +message containing both expressions. + +[endsect] + +[section BOOST_TEST_THROWS] + +`` +BOOST_TEST_THROWS(expr, excep) +`` + If BOOST_NO_EXCEPTIONS is NOT defined and if `expr` does not throw an exception of type `excep`, increases the error count and outputs a message containing the expression. @@ -35,14 +57,32 @@ and outputs a message containing the expression. If BOOST_NO_EXCEPTIONS is defined, this macro expands to nothing and `expr` is not evaluated. -`` -BOOST_TEST_THROWS(expr, excep) -`` +[endsect] -Returns the error count. +[section report_errors] `` int boost::report_errors() `` +Return the error count from `main`. + +Example: + +`` +#include + +void sqr( int x ); // should return x * x + +int main() +{ + BOOST_TEST( sqr( 2 ) == 4 ); + BOOST_TEST_EQ( sqr(-3), 9 ); + + return boost::report_errors(); +} +`` + +[endsect] + [endsect] diff --git a/enable_if.html b/enable_if.html deleted file mode 100644 index 9988f3a..0000000 --- a/enable_if.html +++ /dev/null @@ -1,464 +0,0 @@ - - -enable_if - - - - - - - - - - -
-
- - -

-enable_if

-
-
-Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.
-Copyright 2011 Matt Calabrese.
-
- - -

1  Introduction

- - -The enable_if family of templates is a set of tools to allow a function template or a class template specialization -to include or exclude itself from a set of matching functions or specializations -based on properties of its template arguments. -For example, one can define function templates that -are only enabled for, and thus only match, an arbitrary set of types -defined by a traits class. The enable_if templates can also be -applied to enable class template specializations. Applications of -enable_if are discussed in length -in [1] and [2].
-
- - -

1.1  Synopsis

- - -
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;
-}
-
- - -

1.2  Background

- - -Sensible operation of template function overloading in C++ relies -on the SFINAE (substitution-failure-is-not-an-error) -principle [3]: if an invalid argument -or return type is formed during the instantiation of a function -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; }
-
-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 were 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.
-
-The enable_if templates are tools for controlled creation of the SFINAE -conditions.
-
- - -

2  The enable_if templates

- - -The names of the enable_if templates have three parts: an optional lazy_ tag, -either enable_if or disable_if, and an optional _c tag. -All eight combinations of these parts are supported. -The meaning of the lazy_ tag is described in Section 3.3. -The second part of the name indicates whether a true condition argument should -enable or disable the current overload. -The third part of the name indicates whether the condition argument is a bool value -(_c suffix), or a type containing a static bool constant named value (no suffix). -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>
-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; }
-
-
- - - -

3  Using enable_if

- - -The enable_if templates are defined in -boost/utility/enable_if.hpp, which is included by boost/utility.hpp.
-
-With respect to function templates, enable_if can be used in multiple different ways: - -
    -
  • As the return type of an instantiatied function -
  • As an extra parameter of an instantiated function -
  • As an extra template parameter (useful only in a compiler that supports C++0x default -arguments for function template parameters, see Enabling function -templates in C++0x for details) -
- -In the previous section, the return type form of enable_if was shown. As an example -of using the form of enable_if that works via an extra function parameter, the -foo function in the previous section could also be written -as: -
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.
-
-Which way to write the enabler is largely a matter of taste, but for certain functions, only a -subset of the options is possible: -
  • -Many operators have a fixed number of arguments, thus enable_if must be used either in the -return type or in an extra template parameter. -
  • Functions that have a variadic parameter list must use either the return type form or an extra -template parameter. -
  • Constructors do not have a return type so you must use either an extra function parameter or an -extra template parameter. -
  • Constructors that have a variadic parameter list must an extra template parameter. -
  • Conversion operators can only be written with an extra template parameter. -
- - - -

3.1  Enabling function templates in C++0x

- -In a compiler which supports C++0x default arguments for function template parameters, you can -enable and disable function templates by adding an additional template parameter. This approach -works in all situations where you would use either the return type form of enable_if or -the function parameter form, including operators, constructors, variadic function templates, and -even overloaded conversion operations. - -As an example: - -
#include <boost/type_traits/is_arithmetic.hpp>
-#include <boost/type_traits/is_pointer.hpp>
-#include <boost/utility/enable_if.hpp>
-
-class test
-{
-public:
-  // A constructor that works for any argument list of size 10
-  template< class... T
-          , typename boost::enable_if_c< sizeof...( T ) == 10, int >::type = 0
-          >
-  test( T&&... );
-
-  // A conversion operation that can convert to any arithmetic type
-  template< class T
-          , typename boost::enable_if< boost::is_arithmetic< T >, int >::type = 0
-          >
-  operator T() const;
-
-  // A conversion operation that can convert to any pointer type
-  template< class T
-          , typename boost::enable_if< boost::is_pointer< T >, int >::type = 0
-          >
-  operator T() const;
-};
-
-int main()
-{
-  // Works
-  test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
-
-  // Fails as expected
-  test fail_construction( 1, 2, 3, 4, 5 );
-
-  // Works by calling the conversion operator enabled for arithmetic types
-  int arithmetic_object = test_;
-
-  // Works by calling the conversion operator enabled for pointer types
-  int* pointer_object = test_;
-
-  // Fails as expected
-  struct {} fail_conversion = test_;
-}
-
-
- - - -

3.2  Enabling template class specializations

- - -Class template specializations can be enabled or disabled with enable_if. -One extra template parameter needs to be added for the enabler expressions. -This parameter has the default value void. -For example: -
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.
-
- - -

3.3  Overlapping enabler conditions

- - -Once the compiler has examined the enabling conditions and included the -function into the overload resolution set, normal C++ overload resolution -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>
-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.
-
-The above discussion applies to using enable_if in class template -partial specializations as well.
-
- - -

3.4  Lazy enable_if

- - -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>
-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.
-
-Now, trying to invoke (some other overload) of operator* with, say, operand types C and D -for which is_multipliable<C, D>::value is false -and mult_traits<C, D>::type is not defined is an error on some compilers. -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>
-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.
-
- - -
Note
- -Referring to one member type or static constant in a traits class -causes all of the members (type and static constant) of that -specialization to be instantiated. Therefore, if your traits classes -can sometimes contain invalid types, you should use two distinct -templates for describing the conditions and the type mappings. In the -above example, is_multipliable<T, U>::value defines when -mult_traits<T, U>::type is valid.
-
- - -

3.5  Compiler workarounds

- - -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>
-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: -
  • -Use an extra dummy parameter which disambiguates the functions. Use a default value for -it to hide the parameter from the caller. For example: -
    template <int> 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);
    -

    -
    -
  • Define the functions in different namespaces and bring them into a common -namespace with using declarations: -
    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). -
- - -

4  Acknowledgements

- -We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard -Smith whose findings have influenced the library.
-
- - -

References

-
[1]
-Jaakko Järvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine. -Function overloading based on arbitrary properties of types. -C/C++ Users Journal, 21(6):25--32, June 2003.
-
-
[2]
-Jaakko Järvi, Jeremiah Willcock, and Andrew Lumsdaine. -Concept-controlled polymorphism. -In Frank Pfennig and Yannis Smaragdakis, editors, Generative - Programming and Component Engineering, volume 2830 of LNCS, pages - 228--244. Springer Verlag, September 2003.
-
-
[3]
-David Vandevoorde and Nicolai M. Josuttis. -C++ Templates: The Complete Guide. -Addison-Wesley, 2002.
- -
-

Copyright Jaakko Järvi*, Jeremiah Willcock*, Andrew Lumsdaine*, Matt Calabrese
-{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com
-*Indiana University
-Open Systems Lab
-Use, modification and distribution are 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 -). -

- - - -
-
This document was translated from LATEX by -HEVEA. -
- -