1
0
forked from boostorg/core

Merge branch 'master' into develop

This commit is contained in:
Glen Fernandes
2014-06-02 14:08:47 -07:00
5 changed files with 531 additions and 492 deletions

View File

@@ -37,7 +37,7 @@ namespace boost
[section checked_delete]
[section `template<class T> void checked_delete(T * p);`]
[section template<class T> 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<class T> void checked_array_delete(T * p);`]
[section template<class T> 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<class T> struct checked_deleter
};
``
[section `void checked_deleter<T>::operator()(T * p) const;`]
[section void checked_deleter<T>::operator()(T * p) const;]
* *Requires:* `T` must be a complete type. The expression
`delete p` must be well-formed.
@@ -91,10 +91,11 @@ template<class T> struct checked_array_deleter
};
``
[section `void checked_array_deleter<T>::operator()(T * p) const;`]
[section void checked_array_deleter<T>::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]

View File

@@ -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]

461
doc/enable_if.qbk Normal file
View File

@@ -0,0 +1,461 @@
[section:enable_if Header <boost/core/enable_if.hpp>]
[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 <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;
}
``
[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 <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.
[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 <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; }
``
[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 <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.
[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 <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_;
}
``
[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 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.
[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 <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.
[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 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.]
[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 <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).
[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]

View File

@@ -1,33 +1,55 @@
[section:lightweight_test Header <boost/core/lightweight_test.hpp>]
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 <boost/core/lightweight_test.hpp>
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]

View File

@@ -1,464 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>enable_if</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="Microsoft FrontPage 5.0">
</HEAD>
<BODY >
<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<BR>
<BR>
<h1>
<img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1>
<BR>
<BR>
Copyright 2003 Jaakko J&auml;rvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
Copyright 2011 Matt Calabrese.<BR>
<BR>
<!--TOC section Introduction-->
<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="introduction"></A>
The <TT>enable_if</TT> 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 <TT>enable_if</TT> templates can also be
applied to enable class template specializations. Applications of
<TT>enable_if</TT> are discussed in length
in&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and&nbsp;[<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
<BR>
<!--TOC subsection Synopsis-->
<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;Synopsis</H3><!--SEC END -->
<A NAME="sec:synopsis"></A>
<PRE>namespace boost {
template &lt;class Cond, class T = void&gt; struct enable_if;
template &lt;class Cond, class T = void&gt; struct disable_if;
template &lt;class Cond, class T&gt; struct lazy_enable_if;
template &lt;class Cond, class T&gt; struct lazy_disable_if;
template &lt;bool B, class T = void&gt; struct enable_if_c;
template &lt;bool B, class T = void&gt; struct disable_if_c;
template &lt;bool B, class T&gt; struct lazy_enable_if_c;
template &lt;bool B, class T&gt; struct lazy_disable_if_c;
}
</PRE>
<!--TOC subsection Background-->
<H3><A NAME="htoc3">1.2</A>&nbsp;&nbsp;Background</H3><!--SEC END -->
<A NAME="sec:background"></A>
Sensible operation of template function overloading in C++ relies
on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
principle&nbsp;[<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: 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&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
demonstrates why this is important:
<PRE>int negate(int i) { return -i; }
template &lt;class F&gt;
typename F::result_type negate(const F&amp; f) { return -f(); }
</PRE>
Suppose the compiler encounters the call <TT>negate(1)</TT>. 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
<TT>F</TT> as <TT>int</TT> would result in:
<PRE>int::result_type negate(const int&amp;);
</PRE>
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 <TT>negate</TT> is simply removed from the overload resolution set.<BR>
<BR>
The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
conditions.<BR>
<BR>
<!--TOC section The <TT>enable_if</TT> templates-->
<H2><A NAME="htoc4">2</A>&nbsp;&nbsp;The <TT>enable_if</TT> templates</H2><!--SEC END -->
<A NAME="enable_if"></A>
The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
All eight combinations of these parts are supported.
The meaning of the <TT>lazy_</TT> tag is described in Section&nbsp;<A HREF="#sec:enable_if_lazy">3.3</A>.
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 <TT>bool</TT> value
(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
The latter version interoperates with Boost.MPL. <BR>
<BR>
The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
unqualified but they are in the <TT>boost</TT> namespace).
<PRE>template &lt;bool B, class T = void&gt;
struct enable_if_c {
typedef T type;
};
template &lt;class T&gt;
struct enable_if_c&lt;false, T&gt; {};
template &lt;class Cond, class T = void&gt;
struct enable_if : public enable_if_c&lt;Cond::value, T&gt; {};
</PRE>
An instantiation of the <TT>enable_if_c</TT> template with the parameter
<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
to be <TT>T</TT>. If <TT>B</TT> is
<TT>false</TT>, no such member is defined. Thus
<TT>enable_if_c&lt;B, T&gt;::type</TT> is either a valid or an invalid type
expression, depending on the value of <TT>B</TT>.
When valid, <TT>enable_if_c&lt;B, T&gt;::type</TT> equals <TT>T</TT>.
The <TT>enable_if_c</TT> 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 <A HREF="../type_traits/index.html">Boost type_traits library</A>):
<PRE>template &lt;class T&gt;
typename enable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
foo(T t) { return t; }
</PRE>
The <TT>disable_if_c</TT> template is provided as well, and has the
same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
function is enabled for all non-arithmetic types.
<PRE>template &lt;class T&gt;
typename disable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
bar(T t) { return t; }
</PRE>
For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
<TT>value</TT> as the condition argument.
The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> 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 <TT>foo</TT> can be alternatively written as:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t) { return t; }
</PRE>
<!--TOC section Using <TT>enable_if</TT>-->
<H2><A NAME="htoc5">3</A>&nbsp;&nbsp;Using <TT>enable_if</TT></H2><!--SEC END -->
<A NAME="sec:using_enable_if"></A>
The <TT>enable_if</TT> templates are defined in
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
<BR>
With respect to function templates, <TT>enable_if</TT> can be used in multiple different ways:
<UL>
<LI>As the return type of an instantiatied function
<LI>As an extra parameter of an instantiated function
<LI>As an extra template parameter (useful only in a compiler that supports C++0x default
arguments for function template parameters, see <A href="#sec:enable_if_0x">Enabling function
templates in C++0x</a> for details)
</UL>
In the previous section, the return type form of <TT>enable_if</TT> was shown. As an example
of using the form of <TT>enable_if</TT> that works via an extra function parameter, the
<TT>foo</TT> function in the previous section could also be written
as:
<PRE>template &lt;class T&gt;
T foo(T t, typename enable_if&lt;boost::is_arithmetic&lt;T&gt; &gt;::type* dummy = 0);
</PRE>Hence, an extra parameter of type <TT>void*</TT> 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 <TT>enable_if</TT>, as the default
<TT>void</TT> gives the desired behavior.<BR>
<BR>
Which way to write the enabler is largely a matter of taste, but for certain functions, only a
subset of the options is possible:
<UL><LI>
Many operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used either in the
return type or in an extra template parameter.
<LI>Functions that have a variadic parameter list must use either the return type form or an extra
template parameter.
<LI>Constructors do not have a return type so you must use either an extra function parameter or an
extra template parameter.
<LI>Constructors that have a variadic parameter list must an extra template parameter.
<LI>Conversion operators can only be written with an extra template parameter.
</UL>
<!--TOC subsection Enabling function templates in C++0x-->
<A NAME="sec:enable_if_0x"></A>
<H3><A NAME="htoc6">3.1</A>&nbsp;&nbsp;Enabling function templates in C++0x</H3><!--SEC END -->
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 <TT>enable_if</TT> or
the function parameter form, including operators, constructors, variadic function templates, and
even overloaded conversion operations.
As an example:
<PRE>#include &lt;boost/type_traits/is_arithmetic.hpp&gt;
#include &lt;boost/type_traits/is_pointer.hpp&gt;
#include &lt;boost/utility/enable_if.hpp&gt;
class test
{
public:
// A constructor that works for any argument list of size 10
template&lt; class... T
, typename boost::enable_if_c&lt; sizeof...( T ) == 10, int &gt;::type = 0
&gt;
test( T&amp;&amp;... );
// A conversion operation that can convert to any arithmetic type
template&lt; class T
, typename boost::enable_if&lt; boost::is_arithmetic&lt; T &gt;, int &gt;::type = 0
&gt;
operator T() const;
// A conversion operation that can convert to any pointer type
template&lt; class T
, typename boost::enable_if&lt; boost::is_pointer&lt; T &gt;, int &gt;::type = 0
&gt;
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_;
}
</PRE>
<!--TOC subsection Enabling template class specializations-->
<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
<A NAME="sec:enable_if_classes"></A>
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
One extra template parameter needs to be added for the enabler expressions.
This parameter has the default value <TT>void</TT>.
For example:
<PRE>template &lt;class T, class Enable = void&gt;
class A { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_integral&lt;T&gt; &gt;::type&gt; { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_float&lt;T&gt; &gt;::type&gt; { ... };
</PRE>Instantiating <TT>A</TT> 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 <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
is the correct value.<BR>
<BR>
<!--TOC subsection Overlapping enabler conditions-->
<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
<A NAME="sec:overlapping_conditions"></A>
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:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_integral&lt;T&gt;, void&gt;::type
foo(T t) {}
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, void&gt;::type
foo(T t) {}
</PRE>
All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
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.<BR>
<BR>
The above discussion applies to using <TT>enable_if</TT> in class template
partial specializations as well.<BR>
<BR>
<!--TOC subsection Lazy <TT>enable_if</TT>-->
<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
<A NAME="sec:enable_if_lazy"></A>
In some cases it is necessary to avoid instantiating part of a
function signature unless an enabling condition is true. For example:
<PRE>template &lt;class T, class U&gt; class mult_traits;
template &lt;class T, class U&gt;
typename enable_if&lt;is_multipliable&lt;T, U&gt;, typename mult_traits&lt;T, U&gt;::type&gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
class specifies for which types to enable the operator. Whenever
<TT>is_multipliable&lt;A, B&gt;::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
then <TT>mult_traits&lt;A, B&gt;::type</TT> is defined.<BR>
<BR>
Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>
for which <TT>is_multipliable&lt;C, D&gt;::value</TT> is <TT>false</TT>
and <TT>mult_traits&lt;C, D&gt;::type</TT> 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 <TT>lazy_enable_if</TT>
and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
situations:
<PRE>template&lt;class T, class U&gt;
typename lazy_enable_if&lt;is_multipliable&lt;T, U&gt;, mult_traits&lt;T, U&gt; &gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
that defines a nested type named <TT>type</TT> whenever the first
parameter (the condition) is true.<BR>
<BR>
<!--TOC paragraph Note-->
<H5>Note</H5><!--SEC END -->
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, <TT>is_multipliable&lt;T, U&gt;::value</TT> defines when
<TT>mult_traits&lt;T, U&gt;::type</TT> is valid.<BR>
<BR>
<!--TOC subsection Compiler workarounds-->
<H3><A NAME="htoc10">3.5</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
<A NAME="sec:workarounds"></A>
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:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
</PRE>Two workarounds can be applied:
<UL><LI>
Use an extra dummy parameter which disambiguates the functions. Use a default value for
it to hide the parameter from the caller. For example:
<PRE>template &lt;int&gt; struct dummy { dummy(int) {} };
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;0&gt; = 0);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;1&gt; = 0);
</PRE><BR>
<BR>
<LI>Define the functions in different namespaces and bring them into a common
namespace with <TT>using</TT> declarations:
<PRE>namespace A {
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
namespace B {
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
using A::foo;
using B::foo;
</PRE>
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).
</UL>
<!--TOC section Acknowledgements-->
<H2><A NAME="htoc11">4</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
Smith whose findings have influenced the library.<BR>
<BR>
<!--TOC section References-->
<H2>References</H2><!--SEC END -->
<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
Function overloading based on arbitrary properties of types.
<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
<BR>
<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, and Andrew Lumsdaine.
Concept-controlled polymorphism.
In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
228--244. Springer Verlag, September 2003.<BR>
<BR>
<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
David Vandevoorde and Nicolai&nbsp;M. Josuttis.
<EM>C++ Templates: The Complete Guide</EM>.
Addison-Wesley, 2002.</DL>
<hr/>
<p>Copyright Jaakko J&auml;rvi<sup>*</sup>, Jeremiah Willcock<sup>*</sup>, Andrew Lumsdaine<sup>*</sup>, Matt Calabrese<BR>
<EM>{jajarvi|jewillco|lums}@osl.iu.edu, rivorus@gmail.com</EM><BR>
<sup>*</sup>Indiana University<BR>
Open Systems Lab<br/>
Use, modification and distribution are subject to the
Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt
</a>).
</p>
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2>
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>