forked from boostorg/core
More documentation for core
This commit is contained in:
1 parent
260dbdd9ac
commit
649adfd98f
5 files changed
+531
-492
No files matched your search
@@ -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]
|
||||
|
||||
|
||||
+13
-12
@@ -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]
|
||||
@@ -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]
|
||||
+51
-11
@@ -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]
|
||||
Reference in new issue
Block a user