From e33f8b0055bb78072337d65ab1e5cbf6517221bd Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 8 Sep 2013 19:28:44 +0000 Subject: [PATCH] Merged new added components from trunk. Merged other sublibraries which tests are passing for a long time as well. [SVN r85613] --- base_from_member.html | 53 ++++++-- call_traits_test.cpp | 8 +- doc/Jamfile.v2 | 23 +++- doc/explicit_operator_bool.qbk | 68 ++++++++++ include/boost/utility/base_from_member.hpp | 73 +++++++++- include/boost/utility/declval.hpp | 41 +++--- .../utility/detail/result_of_iterate.hpp | 25 +++- include/boost/utility/empty_deleter.hpp | 43 ++++++ .../boost/utility/explicit_operator_bool.hpp | 128 ++++++++++++++++++ include/boost/utility/result_of.hpp | 29 ++-- index.html | 12 +- test/Jamfile.v2 | 5 + test/explicit_operator_bool.cpp | 54 ++++++++ ...it_operator_bool_compile_fail_conv_int.cpp | 40 ++++++ ..._operator_bool_compile_fail_conv_pvoid.cpp | 40 ++++++ ...icit_operator_bool_compile_fail_delete.cpp | 40 ++++++ ...licit_operator_bool_compile_fail_shift.cpp | 40 ++++++ test/result_of_test.cpp | 14 +- utility.htm | 40 ++++++ value_init_test.cpp | 87 ++++++------ 20 files changed, 756 insertions(+), 107 deletions(-) create mode 100644 doc/explicit_operator_bool.qbk create mode 100644 include/boost/utility/empty_deleter.hpp create mode 100644 include/boost/utility/explicit_operator_bool.hpp create mode 100644 test/explicit_operator_bool.cpp create mode 100644 test/explicit_operator_bool_compile_fail_conv_int.cpp create mode 100644 test/explicit_operator_bool_compile_fail_conv_pvoid.cpp create mode 100644 test/explicit_operator_bool_compile_fail_delete.cpp create mode 100644 test/explicit_operator_bool_compile_fail_shift.cpp diff --git a/base_from_member.html b/base_from_member.html index 21ee6d2..07e144e 100644 --- a/base_from_member.html +++ b/base_from_member.html @@ -129,6 +129,8 @@ particular member type does not need to concern itself with the integer.

Synopsis

+#include <type_traits>  // exposition only
+
 #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
 #define BOOST_BASE_FROM_MEMBER_MAX_ARITY  10
 #endif
@@ -139,6 +141,11 @@ class boost::base_from_member
 protected:
     MemberType  member;
 
+#if C++2011 is in use
+    template< typename ...T >
+    explicit constexpr   base_from_member( T&& ...x )
+     noexcept( std::is_nothrow_constructible<MemberType, T...>::value );
+#else
     base_from_member();
 
     template< typename T1 >
@@ -154,6 +161,7 @@ protected:
      typename T10 >
     base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
      T8 x8, T9 x9, T10 x10 );
+#endif
 };
 
@@ -166,13 +174,29 @@ value of zero if it is omitted. The class template has a protected data member called member that the derived class can use for later base classes (or itself).

-

There is a default constructor and several constructor member -templates. These constructor templates can take as many arguments -(currently up to ten) as possible and pass them to a constructor of -the data member. Since C++ does not allow any way to explicitly state +

If the appropriate features of C++2011 are present, there will be a single +constructor template. It implements "perfect forwarding" to the best +constructor call of member (if any). The constructor template is +marked both constexpr and explicit. The former will +be ignored if the corresponding inner constructor call (of member) +does not have the marker. The latter binds the other way; always taking +effect, even when the inner constructor call does not have the marker. The +constructor template propagates the noexcept status of the inner +constructor call. (The constructor template has a trailing parameter with a +default value that disables the template when its signature is too close to the +signatures of the automatically-defined non-template copy- and/or +move-constructors of base_from_member.)

+ +

On earlier-standard compilers, there is a default constructor and several +constructor member templates. These constructor templates can take as many +arguments (currently up to ten) as possible and pass them to a constructor of +the data member.

+ +

Since C++ does not allow any way to explicitly state the template parameters of a templated constructor, make sure that the arguments are already close as possible to the actual type used in -the data member's desired constructor.

+the data member's desired constructor. Explicit conversions may be +necessary.

The BOOST_BASE_FROM_MEMBER_MAX_ARITY macro constant specifies the maximum argument length for the constructor templates. The constant @@ -180,7 +204,7 @@ may be overridden if more (or less) argument configurations are needed. The constant may be read for code that is expandable like the class template and needs to maintain the same maximum size. (Example code would be a class that uses this class template as a base class for a member with a flexible set of -constructors.)

+constructors.) This constant is ignored when C++2011 features are present.

Usage

@@ -323,11 +347,14 @@ constructor argument for pbase0_type is converted from argument for pbase2_type is converted from int to double. The second constructor argument for pbase3_type is a special case of necessary conversion; all -forms of the null-pointer literal in C++ also look like compile-time -integral expressions, so C++ always interprets such code as an integer -when it has overloads that can take either an integer or a pointer. The -last conversion is necessary for the compiler to call a constructor form -with the exact pointer type used in switcher's constructor.

+forms of the null-pointer literal in C++ (except nullptr from +C++2011) also look like compile-time integral expressions, so C++ always +interprets such code as an integer when it has overloads that can take either +an integer or a pointer. The last conversion is necessary for the compiler to +call a constructor form with the exact pointer type used in +switcher's constructor. (If C++2011's nullptr is +used, it still needs a conversion if multiple pointer types can be accepted in +a constructor call but std::nullptr_t cannot.)

Credits

@@ -360,9 +387,9 @@ with the exact pointer type used in switcher's constructor.


-

Revised: 28 August 2004

+

Revised: 16 February 2012

-

Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution +

Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

diff --git a/call_traits_test.cpp b/call_traits_test.cpp index 72852c4..9e49b68 100644 --- a/call_traits_test.cpp +++ b/call_traits_test.cpp @@ -210,8 +210,10 @@ int main() comparible_UDT u; c1(u); call_traits_checker c2; + call_traits_checker c2b; int i = 2; c2(i); + c2b(one); int* pi = &i; int a[2] = {1,2}; #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) @@ -292,7 +294,11 @@ int main() BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits::reference); BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::const_reference); BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::param_type); - + // test enum: + BOOST_CHECK_TYPE(enum_UDT, boost::call_traits::value_type); + BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits::param_type); return 0; } diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index a0ff034..a734cb2 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -6,7 +6,7 @@ project : requirements # Path for links to Boost: boost.root=../../../.. - + # Some general style settings: table.footnote.number.format=1 footnote.number.format=1 @@ -59,7 +59,6 @@ boostbook standalone_declval toc.max.depth=1 # How far down we go with TOC's generate.section.toc.level=1 - ; xml string_ref : string_ref.qbk ; @@ -79,5 +78,23 @@ boostbook standalone_string_ref toc.max.depth=1 # How far down we go with TOC's generate.section.toc.level=1 - + ; + +xml explicit_operator_bool : explicit_operator_bool.qbk ; +boostbook standalone_explicit_operator_bool + : + explicit_operator_bool + : + # File name of HTML output: + root.filename=explicit_operator_bool + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=0 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=0 + # How far down sections get TOC's + toc.section.depth=1 + # Max depth in each TOC: + toc.max.depth=1 + # How far down we go with TOC's + generate.section.toc.level=1 ; diff --git a/doc/explicit_operator_bool.qbk b/doc/explicit_operator_bool.qbk new file mode 100644 index 0000000..4a7e4b1 --- /dev/null +++ b/doc/explicit_operator_bool.qbk @@ -0,0 +1,68 @@ +[/ + / Copyright (c) 2013 Andrey Semashev + / + / Distributed under 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) + /] + +[article BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL + [quickbook 1.5] + [authors [Semashev, Andrey]] + [copyright 2013 Andrey Semashev] + [license + Distributed under 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]) + ] +] + +[/===============] +[section Overview] +[/===============] + +`BOOST_EXPLICIT_OPERATOR_BOOL()` and `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` are compatibility helper macros that expand to an explicit conversion operator to `bool`. For compilers not supporting explicit conversion operators introduced in C++11 the macros expand to a conversion operator that implements the [@http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool safe bool idiom]. In case if the compiler is not able to handle safe bool idiom well the macros expand to a regular conversion operator to `bool`. + +[endsect] + + +[/===============] +[section Examples] +[/===============] + +Both macros are intended to be placed within a user's class definition. The generated conversion operators will be implemented in terms of `operator!()` that should be defined by user in this class. In case of `BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()` the generated conversion operator will be declared `constexpr` which requires the corresponding `operator!()` to also be `constexpr`. + + template< typename T > + class my_ptr + { + T* m_p; + + public: + BOOST_EXPLICIT_OPERATOR_BOOL() + + bool operator!() const + { + return !m_p; + } + }; + +Now `my_ptr` can be used in conditional expressions, similarly to a regular pointer: + + my_ptr< int > p; + if (p) + std::cout << "true" << std::endl; + +[endsect] + +[/===============] +[section History] +[/===============] + +[heading boost 1.55] + +* The macro was extracted from Boost.Log. + +[endsect] + + + + diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp index 04aabb5..e32ecb8 100644 --- a/include/boost/utility/base_from_member.hpp +++ b/include/boost/utility/base_from_member.hpp @@ -1,6 +1,6 @@ // boost utility/base_from_member.hpp header file --------------------------// -// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and +// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and // distribution are subject to the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or a copy at // .) @@ -10,10 +10,15 @@ #ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP #define BOOST_UTILITY_BASE_FROM_MEMBER_HPP +#include #include #include #include #include +#include +#include +#include +#include // Base-from-member arity configuration macro ------------------------------// @@ -53,6 +58,59 @@ namespace boost { +namespace detail +{ + +// Type-unmarking class template -------------------------------------------// + +// Type-trait to get the raw type, i.e. the type without top-level reference nor +// cv-qualification, from a type expression. Mainly for function arguments, any +// reference part is stripped first. + +// Contributed by Daryle Walker + +template < typename T > +struct remove_cv_ref +{ + typedef typename ::boost::remove_cv::type>::type type; + +}; // boost::detail::remove_cv_ref + +// Unmarked-type comparison class template ---------------------------------// + +// Type-trait to check if two type expressions have the same raw type. + +// Contributed by Daryle Walker, based on a work-around by Luc Danton + +template < typename T, typename U > +struct is_related + : public ::boost::is_same< + typename ::boost::detail::remove_cv_ref::type, + typename ::boost::detail::remove_cv_ref::type > +{}; + +// Enable-if-on-unidentical-unmarked-type class template -------------------// + +// Enable-if on the first two type expressions NOT having the same raw type. + +// Contributed by Daryle Walker, based on a work-around by Luc Danton + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template +struct enable_if_unrelated + : public ::boost::enable_if_c +{}; + +template +struct enable_if_unrelated + : public ::boost::disable_if< ::boost::detail::is_related > +{}; +#endif + +} // namespace boost::detail + + // Base-from-member class template -----------------------------------------// // Helper to initialize a base object so a derived class can use this @@ -68,12 +126,25 @@ class base_from_member protected: MemberType member; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \ + !(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)) + template ::type> + explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) + BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType( + static_cast(x)... )) ) // no std::is_nothrow_constructible... + : member( static_cast(x)... ) // ...nor std::forward needed + {} +#else base_from_member() : member() {} BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY), BOOST_PRIVATE_CTR_DEF, _ ) +#endif }; // boost::base_from_member diff --git a/include/boost/utility/declval.hpp b/include/boost/utility/declval.hpp index d74610c..a4ab2c8 100644 --- a/include/boost/utility/declval.hpp +++ b/include/boost/utility/declval.hpp @@ -1,49 +1,44 @@ -// common_type.hpp ---------------------------------------------------------// +// declval.hpp -------------------------------------------------------------// // Copyright 2010 Vicente J. Botet Escriba // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt -#ifndef BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP -#define BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP +#ifndef BOOST_UTILITY_DECLVAL_HPP +#define BOOST_UTILITY_DECLVAL_HPP #include //----------------------------------------------------------------------------// #include -//#include //----------------------------------------------------------------------------// // // // C++03 implementation of // +// 20.2.4 Function template declval [declval] // // Written by Vicente J. Botet Escriba // -//~ 20.3.4 Function template declval [declval] -//~ 1 The library provides the function template declval to simplify the definition of expressions which occur as -//~ unevaluated operands. -//~ 2 Remarks: If this function is used, the program is ill-formed. -//~ 3 Remarks: The template parameter T of declval may be an incomplete type. -//~ [ Example: - -//~ template -//~ decltype(static_cast(declval())) convert(From&&); - -//~ declares a function template convert which only participats in overloading if the type From can be -//~ explicitly converted to type To. For another example see class template common_type (20.7.6.6). —end -//~ example ] // // +// 1 The library provides the function template declval to simplify the +// definition of expressions which occur as unevaluated operands. +// 2 Remarks: If this function is used, the program is ill-formed. +// 3 Remarks: The template parameter T of declval may be an incomplete type. +// [ Example: +// +// template +// decltype(static_cast(declval())) convert(From&&); +// +// declares a function template convert which only participates in overloading +// if the type From can be explicitly converted to type To. For another example +// see class template common_type (20.9.7.6). -end example ] //----------------------------------------------------------------------------// namespace boost { -//#if !defined(BOOST_NO_RVALUE_REFERENCES) template typename add_rvalue_reference::type declval() BOOST_NOEXCEPT; // as unevaluated operand -//#else -// template -// typename add_lvalue_reference::type declval() BOOST_NOEXCEPT; // as unevaluated operand -//#endif + } // namespace boost -#endif // BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP +#endif // BOOST_UTILITY_DECLVAL_HPP diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 17fd4d5..5192172 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,10 +38,25 @@ struct tr1_result_of #endif #ifdef BOOST_RESULT_OF_USE_DECLTYPE - -// Uses declval following N3225 20.7.7.6 when F is not a pointer. template -struct result_of +struct result_of + : detail::cpp0x_result_of { }; +#endif // BOOST_RESULT_OF_USE_DECLTYPE + +#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +template +struct result_of + : mpl::if_, detail::has_result >, + tr1_result_of, + detail::cpp0x_result_of >::type { }; +#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +namespace detail { + +template +struct cpp0x_result_of : mpl::if_< is_member_function_pointer , detail::tr1_result_of_impl< @@ -54,8 +69,6 @@ struct result_of >::type {}; -namespace detail { - #ifdef BOOST_NO_SFINAE_EXPR template @@ -139,7 +152,7 @@ struct cpp0x_result_of_impl diff --git a/include/boost/utility/empty_deleter.hpp b/include/boost/utility/empty_deleter.hpp new file mode 100644 index 0000000..ba919cd --- /dev/null +++ b/include/boost/utility/empty_deleter.hpp @@ -0,0 +1,43 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file empty_deleter.hpp + * \author Andrey Semashev + * \date 22.04.2007 + * + * This header contains an \c empty_deleter implementation. This is an empty + * function object that receives a pointer and does nothing with it. + * Such empty deletion strategy may be convenient, for example, when + * constructing shared_ptrs that point to some object that should not be + * deleted (i.e. a variable on the stack or some global singleton, like std::cout). + */ + +#ifndef BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ +#define BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +//! A function object that does nothing and can be used as an empty deleter for \c shared_ptr +struct empty_deleter +{ + //! Function object result type + typedef void result_type; + /*! + * Does nothing + */ + void operator() (const volatile void*) const BOOST_NOEXCEPT {} +}; + +} // namespace boost + +#endif // BOOST_UTILITY_EMPTY_DELETER_HPP_INCLUDED_ diff --git a/include/boost/utility/explicit_operator_bool.hpp b/include/boost/utility/explicit_operator_bool.hpp new file mode 100644 index 0000000..650caff --- /dev/null +++ b/include/boost/utility/explicit_operator_bool.hpp @@ -0,0 +1,128 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool.hpp + * \author Andrey Semashev + * \date 08.03.2009 + * + * This header defines a compatibility macro that implements an unspecified + * \c bool operator idiom, which is superseded with explicit conversion operators in + * C++11. + */ + +#ifndef BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ +#define BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +/*! + * \brief The macro defines an explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE explicit operator bool () const\ + {\ + return !this->operator! ();\ + } + +/*! + * \brief The macro defines a constexpr explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const\ + {\ + return !this->operator! ();\ + } + +#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG) +// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it +#define BOOST_NO_UNSPECIFIED_BOOL +#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG) + +#if !defined(BOOST_NO_UNSPECIFIED_BOOL) + +namespace boost { + +namespace detail { + +#if !defined(_MSC_VER) && !defined(__IBMCPP__) + + struct unspecified_bool + { + // NOTE TO THE USER: If you see this in error messages then you tried + // to apply an unsupported operator on the object that supports + // explicit conversion to bool. + struct OPERATORS_NOT_ALLOWED; + static void true_value(OPERATORS_NOT_ALLOWED*) {} + }; + typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*); + +#else + + // MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't + struct unspecified_bool + { + // NOTE TO THE USER: If you see this in error messages then you tried + // to apply an unsupported operator on the object that supports + // explicit conversion to bool. + struct OPERATORS_NOT_ALLOWED; + void true_value(OPERATORS_NOT_ALLOWED*) {} + }; + typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*); + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + +#else // !defined(BOOST_NO_UNSPECIFIED_BOOL) + +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE operator bool () const\ + {\ + return !this->operator! ();\ + } + +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const\ + {\ + return !this->operator! ();\ + } + +#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL) + +#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +#endif // BOOST_UTILITY_EXPLICIT_OPERATOR_BOOL_HPP_INCLUDED_ diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 97e9618..a530c3a 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -38,18 +38,27 @@ // Use the decltype-based version of result_of by default if the compiler // supports N3276 . -// The user can force the choice by defining either BOOST_RESULT_OF_USE_DECLTYPE or -// BOOST_RESULT_OF_USE_TR1, but not both! -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1) -# error Both BOOST_RESULT_OF_USE_DECLTYPE and BOOST_RESULT_OF_USE_TR1 cannot be defined at the same time. +// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE, +// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one! +#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \ + (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \ + (defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) +# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \ + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time. +#endif + +#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) +# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined. #endif #ifndef BOOST_RESULT_OF_USE_TR1 # ifndef BOOST_RESULT_OF_USE_DECLTYPE -# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE) -# define BOOST_RESULT_OF_USE_DECLTYPE -# else -# define BOOST_RESULT_OF_USE_TR1 +# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif # endif # endif #endif @@ -64,8 +73,12 @@ namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result) + template struct tr1_result_of_impl; +template struct cpp0x_result_of; + #ifdef BOOST_NO_SFINAE_EXPR // There doesn't seem to be any other way to turn this off such that the presence of diff --git a/index.html b/index.html index 367fa93..41c8c15 100644 --- a/index.html +++ b/index.html @@ -14,22 +14,29 @@

But that doesn't mean there isn't useful stuff here. Take a look:

+ addressof
assert
base_from_member
+ BOOST_BINARY
call_traits
checked_delete
compressed_pair
current_function
declval
enable_if
- iterator_adaptors
- generator iterator adaptors
+ in_place_factory
+ iterator_adaptors
+ generator iterator adaptors
+ next/prior
+ noncopyable
operators
+ result_of
swap
throw_exception
utility
string_ref
value_init + BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL


@@ -43,4 +50,3 @@ 07 November, 2006

- diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index cec9727..548dcba 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -48,5 +48,10 @@ test-suite utility [ compile-fail ../initialized_test_fail1.cpp ] [ compile-fail ../initialized_test_fail2.cpp ] [ run ../verify_test.cpp ] + [ run explicit_operator_bool.cpp ] + [ compile-fail explicit_operator_bool_compile_fail_conv_int.cpp ] + [ compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp ] + [ compile-fail explicit_operator_bool_compile_fail_delete.cpp ] + [ compile-fail explicit_operator_bool_compile_fail_shift.cpp ] ; diff --git a/test/explicit_operator_bool.cpp b/test/explicit_operator_bool.cpp new file mode 100644 index 0000000..07dd01b --- /dev/null +++ b/test/explicit_operator_bool.cpp @@ -0,0 +1,54 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool_compile.cpp + * \author Andrey Semashev + * \date 17.07.2010 + * + * \brief This test checks that explicit operator bool can be used in + * the valid contexts. + */ + +#define BOOST_TEST_MODULE explicit_operator_bool_compile + +#include + +namespace { + + // A test object that has the operator of explicit conversion to bool + struct checkable1 + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + + struct checkable2 + { + BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL() + BOOST_CONSTEXPR bool operator! () const + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable1 val1; + if (val1) + { + checkable2 val2; + if (val2) + return 0; + } + + return 1; +} diff --git a/test/explicit_operator_bool_compile_fail_conv_int.cpp b/test/explicit_operator_bool_compile_fail_conv_int.cpp new file mode 100644 index 0000000..384f2ab --- /dev/null +++ b/test/explicit_operator_bool_compile_fail_conv_int.cpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool_compile_fail_conv_int.cpp + * \author Andrey Semashev + * \date 17.07.2010 + * + * \brief This test checks that explicit operator bool cannot be used in + * an unintended context. + */ + +#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_int + +#include + +namespace { + + // A test object that has the operator of explicit conversion to bool + struct checkable + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable val; + int n = val; + + return 0; +} diff --git a/test/explicit_operator_bool_compile_fail_conv_pvoid.cpp b/test/explicit_operator_bool_compile_fail_conv_pvoid.cpp new file mode 100644 index 0000000..0c007ba --- /dev/null +++ b/test/explicit_operator_bool_compile_fail_conv_pvoid.cpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool_compile_fail_conv_pvoid.cpp + * \author Andrey Semashev + * \date 17.07.2010 + * + * \brief This test checks that explicit operator bool cannot be used in + * an unintended context. + */ + +#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_conv_pvoid + +#include + +namespace { + + // A test object that has the operator of explicit conversion to bool + struct checkable + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable val; + void* p = val; + + return 0; +} diff --git a/test/explicit_operator_bool_compile_fail_delete.cpp b/test/explicit_operator_bool_compile_fail_delete.cpp new file mode 100644 index 0000000..d780f94 --- /dev/null +++ b/test/explicit_operator_bool_compile_fail_delete.cpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool_compile_fail_delete.cpp + * \author Andrey Semashev + * \date 17.07.2010 + * + * \brief This test checks that explicit operator bool cannot be used in + * an unintended context. + */ + +#define BOOST_TEST_MODULE util_explicit_operator_bool_delete + +#include + +namespace { + + // A test object that has the operator of explicit conversion to bool + struct checkable + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable val; + delete val; + + return 0; +} diff --git a/test/explicit_operator_bool_compile_fail_shift.cpp b/test/explicit_operator_bool_compile_fail_shift.cpp new file mode 100644 index 0000000..ce563a6 --- /dev/null +++ b/test/explicit_operator_bool_compile_fail_shift.cpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under 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) + */ +/*! + * \file explicit_operator_bool_compile_fail_shift.cpp + * \author Andrey Semashev + * \date 17.07.2010 + * + * \brief This test checks that explicit operator bool cannot be used in + * an unintended context. + */ + +#define BOOST_TEST_MODULE explicit_operator_bool_compile_fail_shift + +#include + +namespace { + + // A test object that has the operator of explicit conversion to bool + struct checkable + { + BOOST_EXPLICIT_OPERATOR_BOOL() + bool operator! () const + { + return false; + } + }; + +} // namespace + +int main(int, char*[]) +{ + checkable val; + val << 2; + + return 0; +} diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index d06ec64..9ea72f1 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -5,6 +5,12 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Examples: +// To run the default test: +// $ cd libs/utility/test && bjam +// To test decltype on g++ 2.7: +// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE" + #include // For more information, see http://www.boost.org/libs/utility @@ -190,7 +196,7 @@ int main() BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); // Prior to decltype, result_of could not deduce the return type - // nullary function objects unless they exposed a result_type. + // of nullary function objects unless they exposed a result_type. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -273,7 +279,7 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type,int>::value)); -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) BOOST_STATIC_ASSERT((is_same::type, short>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); @@ -301,10 +307,10 @@ int main() #endif #endif -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) int i = 123; sfinae_test(sfinae_test_f, i); -#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) return 0; } diff --git a/utility.htm b/utility.htm index 974776e..1101cc6 100644 --- a/utility.htm +++ b/utility.htm @@ -259,6 +259,46 @@ typedef boost::result_of< represent the return type of operator() given a call expression.

+

Additionally, boost::result_of + provides a third mode of operation, which some users + may find convenient. When + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + is defined, boost::result_of behaves as + follows. If the function object has a member + type result_type or member + template result<>, then + boost::result_of will use the TR1 + protocol. Otherwise, + boost::result_of will + use decltype. Using TR1 with + a declytpe fallback may workaround + certain problems at the cost of portability. For + example: +

    +
  • Deficient compiler: If your code + requires boost::result_of to work + with incomplete return types but your + compiler's decltype implementation + does not support incomplete return types, then you + can use the TR1 protocol as a workaround. Support + for incomplete return types was added late in the + C++11 standardization process + (see N3276) + and is not implemented by some compilers.
  • + +
  • Deficient legacy code: If your existing TR1 + function object advertises a different type than + the actual result type deduced + by decltype, then using TR1 with a + decltype fallback will allow you to + work with both your existing TR1 function objects + and new C++11 function object. This situation + could occur if your legacy function objects + misused the TR1 protocol. See the documentation on + known differences + between boost::result_of and TR1.
  • +
+

This implementation of result_of requires class template partial specialization, the diff --git a/value_init_test.cpp b/value_init_test.cpp index 98b8860..bee8e10 100644 --- a/value_init_test.cpp +++ b/value_init_test.cpp @@ -22,7 +22,7 @@ #pragma hdrstop #endif -#include "boost/test/minimal.hpp" +#include // // Sample POD type @@ -215,7 +215,7 @@ template void check_initialized_value ( T const& y ) { T initializedValue = boost::initialized_value ; - BOOST_CHECK ( y == initializedValue ) ; + BOOST_TEST ( y == initializedValue ) ; } #ifdef __BORLANDC__ @@ -245,128 +245,125 @@ void check_initialized_value( NonPOD const& ) template bool test ( T const& y, T const& z ) { - const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter(); + const int errors_before_test = boost::detail::test_errors(); check_initialized_value(y); boost::value_initialized x ; - BOOST_CHECK ( y == x ) ; - BOOST_CHECK ( y == boost::get(x) ) ; + BOOST_TEST ( y == x ) ; + BOOST_TEST ( y == boost::get(x) ) ; static_cast(x) = z ; boost::get(x) = z ; - BOOST_CHECK ( x == z ) ; + BOOST_TEST ( x == z ) ; boost::value_initialized const x_c ; - BOOST_CHECK ( y == x_c ) ; - BOOST_CHECK ( y == boost::get(x_c) ) ; + BOOST_TEST ( y == x_c ) ; + BOOST_TEST ( y == boost::get(x_c) ) ; T& x_c_ref = const_cast( boost::get(x_c) ) ; x_c_ref = z ; - BOOST_CHECK ( x_c == z ) ; + BOOST_TEST ( x_c == z ) ; boost::value_initialized const copy1 = x; - BOOST_CHECK ( boost::get(copy1) == boost::get(x) ) ; + BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ; boost::value_initialized copy2; copy2 = x; - BOOST_CHECK ( boost::get(copy2) == boost::get(x) ) ; + BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ; boost::shared_ptr > ptr( new boost::value_initialized ); - BOOST_CHECK ( y == *ptr ) ; + BOOST_TEST ( y == *ptr ) ; #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) boost::value_initialized cx ; - BOOST_CHECK ( y == cx ) ; - BOOST_CHECK ( y == boost::get(cx) ) ; + BOOST_TEST ( y == cx ) ; + BOOST_TEST ( y == boost::get(cx) ) ; boost::value_initialized const cx_c ; - BOOST_CHECK ( y == cx_c ) ; - BOOST_CHECK ( y == boost::get(cx_c) ) ; + BOOST_TEST ( y == cx_c ) ; + BOOST_TEST ( y == boost::get(cx_c) ) ; #endif - return boost::minimal_test::errors_counter() == counter_before_test ; + return boost::detail::test_errors() == errors_before_test ; } -int test_main(int, char **) +int main(int, char **) { - BOOST_CHECK ( test( 0,1234 ) ) ; - BOOST_CHECK ( test( 0.0,12.34 ) ) ; - BOOST_CHECK ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ; - BOOST_CHECK ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ; + BOOST_TEST ( test( 0,1234 ) ) ; + BOOST_TEST ( test( 0.0,12.34 ) ) ; + BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ; + BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ; NonPOD NonPOD_object( std::string("NonPOD_object") ); - BOOST_CHECK ( test( 0, &NonPOD_object ) ) ; + BOOST_TEST ( test( 0, &NonPOD_object ) ) ; AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 }; AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 }; - BOOST_CHECK ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) ); + BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) ); StringAndInt stringAndInt0; StringAndInt stringAndInt1; stringAndInt0.i = 0; stringAndInt1.i = 1; stringAndInt1.s = std::string("1"); - BOOST_CHECK ( test(stringAndInt0, stringAndInt1) ); + BOOST_TEST ( test(stringAndInt0, stringAndInt1) ); StructWithDestructor structWithDestructor0; StructWithDestructor structWithDestructor1; structWithDestructor0.i = 0; structWithDestructor1.i = 1; - BOOST_CHECK ( test(structWithDestructor0, structWithDestructor1) ); + BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) ); StructWithVirtualFunction structWithVirtualFunction0; StructWithVirtualFunction structWithVirtualFunction1; structWithVirtualFunction0.i = 0; structWithVirtualFunction1.i = 1; - BOOST_CHECK ( test(structWithVirtualFunction0, structWithVirtualFunction1) ); + BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) ); DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0; DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1; static_cast(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct; static_cast(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct; - BOOST_CHECK ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) ); + BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) ); AggregatePODStructWrapper aggregatePODStructWrapper0; AggregatePODStructWrapper aggregatePODStructWrapper1; aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct; aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct; - BOOST_CHECK ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) ); + BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) ); ArrayOfBytes zeroInitializedArrayOfBytes = { 0 }; boost::value_initialized valueInitializedArrayOfBytes; - BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0); + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0); boost::value_initialized valueInitializedArrayOfBytes2; valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes; - BOOST_CHECK (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0); + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0); boost::value_initialized copyFunctionCallTester1; - BOOST_CHECK ( ! get(copyFunctionCallTester1).is_copy_constructed); - BOOST_CHECK ( ! get(copyFunctionCallTester1).is_assignment_called); + BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called); boost::value_initialized copyFunctionCallTester2 = boost::value_initialized(copyFunctionCallTester1); - BOOST_CHECK ( get(copyFunctionCallTester2).is_copy_constructed); - BOOST_CHECK ( ! get(copyFunctionCallTester2).is_assignment_called); + BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called); boost::value_initialized copyFunctionCallTester3; copyFunctionCallTester3 = boost::value_initialized(copyFunctionCallTester1); - BOOST_CHECK ( ! get(copyFunctionCallTester3).is_copy_constructed); - BOOST_CHECK ( get(copyFunctionCallTester3).is_assignment_called); + BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed); + BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called); boost::value_initialized swapFunctionCallTester1; boost::value_initialized swapFunctionCallTester2; get(swapFunctionCallTester1).data = 1; get(swapFunctionCallTester2).data = 2; boost::swap(swapFunctionCallTester1, swapFunctionCallTester2); - BOOST_CHECK( get(swapFunctionCallTester1).data == 2 ); - BOOST_CHECK( get(swapFunctionCallTester2).data == 1 ); - BOOST_CHECK( get(swapFunctionCallTester1).is_custom_swap_called ); - BOOST_CHECK( get(swapFunctionCallTester2).is_custom_swap_called ); + BOOST_TEST( get(swapFunctionCallTester1).data == 2 ); + BOOST_TEST( get(swapFunctionCallTester2).data == 1 ); + BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called ); + BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called ); - return 0; + return boost::report_errors(); } -unsigned int expected_failures = 0; - -