From d6cb9a9176294bf42507cfe062ba97d799b11966 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Thu, 16 Feb 2012 18:24:34 +0000 Subject: [PATCH 01/90] Fixed a bug in BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST: a typo VOId -> VOID. Fixed a bug in scope_exit.hpp: An extra trailing \ in a macro definition (compiled only when BOOST_NO_VARIADIC_MACROS is defined). Renamed LocalFunction and ScopeExit tests and examples from _err to _error. Updated LocalFunction docs. [SVN r77042] --- identity_type/doc/identity_type.qbk | 6 +++--- identity_type/test/Jamfile.v2 | 2 +- identity_type/test/{var_err.cpp => var_error.cpp} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename identity_type/test/{var_err.cpp => var_error.cpp} (97%) diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk index d5107a3..2723d33 100644 --- a/identity_type/doc/identity_type.qbk +++ b/identity_type/doc/identity_type.qbk @@ -21,16 +21,16 @@ This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas. -[import ../test/var_err.cpp] +[import ../test/var_error.cpp] [import ../test/var.cpp] [import ../test/template.cpp] [import ../test/tmp_assert.cpp] [section Motivation] -Consider the following macro which declares a variable named `var`/n/ with the specified /type/ (see also [@../../test/var_err.cpp =var_err.cpp=]): +Consider the following macro which declares a variable named `var`/n/ with the specified /type/ (see also [@../../test/var_error.cpp =var_error.cpp=]): -[var_err] +[var_error] The first macro invocation works correctly declaring a variable named `var1` of type `int`. However, the second macro invocation fails generating a preprocessor error similar to the following: diff --git a/identity_type/test/Jamfile.v2 b/identity_type/test/Jamfile.v2 index 2f0bdac..482c0c0 100644 --- a/identity_type/test/Jamfile.v2 +++ b/identity_type/test/Jamfile.v2 @@ -7,7 +7,7 @@ import testing ; -compile-fail var_err.cpp ; +compile-fail var_error.cpp ; run var.cpp ; run template.cpp ; run tmp_assert.cpp ; diff --git a/identity_type/test/var_err.cpp b/identity_type/test/var_error.cpp similarity index 97% rename from identity_type/test/var_err.cpp rename to identity_type/test/var_error.cpp index 7ba0c52..b69817d 100644 --- a/identity_type/test/var_err.cpp +++ b/identity_type/test/var_error.cpp @@ -7,7 +7,7 @@ #include -//[var_err +//[var_error #define VAR(type, n) type var ## n VAR( int, 1 ); // OK. From 0db9276e8c635c3d935287cb97accd94ed7ecd6c Mon Sep 17 00:00:00 2001 From: Daryle Walker Date: Fri, 17 Feb 2012 01:55:33 +0000 Subject: [PATCH 02/90] Fixed (hopefully) conflict between boost::base_from_member's C++11 constructor template and the automatically defined non-template copy- and/or move-constructors. [SVN r77046] --- base_from_member.html | 24 ++++---- include/boost/utility/base_from_member.hpp | 64 +++++++++++++++++++++- 2 files changed, 75 insertions(+), 13 deletions(-) diff --git a/base_from_member.html b/base_from_member.html index df4add2..07e144e 100644 --- a/base_from_member.html +++ b/base_from_member.html @@ -174,16 +174,18 @@ 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).

-

If the variadic template arguments and r-value reference 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.

+

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 @@ -385,7 +387,7 @@ a constructor call but std::nullptr_t cannot.)


-

Revised: 11 February 2012

+

Revised: 16 February 2012

Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp index 8148077..8d17522 100644 --- a/include/boost/utility/base_from_member.hpp +++ b/include/boost/utility/base_from_member.hpp @@ -15,6 +15,10 @@ #include #include #include +#include +#include +#include +#include // Base-from-member arity configuration macro ------------------------------// @@ -54,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_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 @@ -69,8 +126,11 @@ class base_from_member protected: MemberType member; -#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL) - template +#if !defined(BOOST_NO_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) + 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... From 2891cb52d6ff086e24e6bf79c284eb71e7e1ad9c Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Fri, 17 Feb 2012 21:02:00 +0000 Subject: [PATCH 03/90] Added Boost.Utility/IdentityType and Boost.Functional/OverloadedFunction to status/Jamfile.v2 list of regression tests. Updated Boost.ScopeExit documentation. [SVN r77059] --- identity_type/doc/html/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index c0dc1ee..240c80d 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -8,7 +8,7 @@ can be passed to macros even when they contain commas.

Consider the following macro which declares a variable named varn with the specified - type (see also var_err.cpp): + type (see also var_error.cpp):

#define VAR(type, n) type var ## n
 
@@ -215,7 +215,7 @@
 
 BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not require variadic macros).

This macro must be prefixed by typename when used within templates. However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on an abstract types requires to add and remove a reference to the type.



[1] Using variadic macros, it would be possible to use a single set of parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) From 54c78121c2338a84e3516a64439a98e2a5b5cfe3 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Sat, 18 Feb 2012 19:29:35 +0000 Subject: [PATCH 04/90] Updated ScopeExit "world" tests making person a struct instead of a class. Added a code comment to Utility/IdentityType tmp_assert test. [SVN r77071] --- identity_type/test/tmp_assert.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/identity_type/test/tmp_assert.cpp b/identity_type/test/tmp_assert.cpp index 17755cb..f482999 100644 --- a/identity_type/test/tmp_assert.cpp +++ b/identity_type/test/tmp_assert.cpp @@ -19,7 +19,7 @@ template struct abstract { static const bool value = b; - virtual void f(T const& x) = 0; + virtual void f(T const& x) = 0; // Pure virtual function. }; TMP_ASSERT( @@ -38,13 +38,15 @@ TMP_ASSERT( /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) +// Specify only extra parenthesis `((...))`. TMP_ASSERT_PAREN(( boost::is_const const> )); +// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro. TMP_ASSERT( BOOST_IDENTITY_TYPE((boost::is_const const>)) ); //] //[tmp_assert_alternative_always -TMP_ASSERT_PAREN(( boost::is_const )); // Always extra `()`. -TMP_ASSERT( boost::is_const ); // No extra `()` and no macro. +TMP_ASSERT_PAREN(( boost::is_const )); // Always extra `((...))`. +TMP_ASSERT( boost::is_const ); // No extra `((...))` and no macro. //] int main() { return 0; } From 5825b6c3299ed9079438976f0245ed70933434a6 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Mon, 20 Feb 2012 20:17:07 +0000 Subject: [PATCH 05/90] Fixed test indentation and updated docs. [SVN r77080] --- identity_type/doc/html/index.html | 119 +++++++++++++++------------- identity_type/doc/identity_type.qbk | 33 ++++---- identity_type/test/template.cpp | 10 +-- identity_type/test/tmp_assert.cpp | 8 +- identity_type/test/var.cpp | 6 +- identity_type/test/var_error.cpp | 4 +- 6 files changed, 96 insertions(+), 84 deletions(-) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index 240c80d..cc6f4b5 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -7,13 +7,14 @@ This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas.

- Consider the following macro which declares a variable named varn with the specified - type (see also var_error.cpp): + Consider the following macro which declares a variable named varn + with the specified type (see also + var_error.cpp):

#define VAR(type, n) type var ## n
 
-VAR( int, 1 );                  // OK.
-VAR( std::map<int, char>, 2 );  // Error.
+VAR(int, 1);                    // OK.
+VAR(std::map<int, char>, 2);    // Error.
 

The first macro invocation works correctly declaring a variable named var1 of type int. @@ -45,7 +46,7 @@ the type expression with the commas outside the macro (see also var.cpp):

typedef std::map<int, char> map_type;
-VAR( map_type, 3 ); // OK.
+VAR(map_type, 3); // OK.
 

When this is not possible or desired (e.g., see the function template f in the section below), the library header @@ -56,7 +57,7 @@

#include <boost/utility/identity_type.hpp>
 
-VAR( BOOST_IDENTITY_TYPE((std::map<int, char>)), 4 ); // OK.
+VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
 

This macro expands to an expression that evaluates (at compile-time) to the @@ -71,14 +72,15 @@

This macro must be prefixed by typename when used within templates. For example, let's program a macro that declares - a function parameter named argn - with the specified type (see also template.cpp): + a function parameter named argn + with the specified type (see also + template.cpp):

#define ARG(type, n) type arg ## n
 
 template<typename T>
 void f( // Prefix macro with `typename` in templates.
-    ARG( typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1 )
+    ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)
 ) {
     std::cout << arg1[0] << std::endl;
 }
@@ -87,20 +89,20 @@
 

std::map<int, char> a;
 a[0] = 'a';
 
-f<char>(a); // OK.
-// f(a);    // But error.
+f<char>(a); // OK...
+// f(a);    // ... but error.
 

- However, note that the template parameter type char - must be explicitly specified when invoking the function f<char>(a). In fact, + However, note that the template parameter char + must be manually specified when invoking the function f<char>(a). In fact, when the BOOST_IDENTITY_TYPE macro is used to wrap a function template parameter, the template parameter - can no longer be implicitly determined by the compiler form the function call - as in f(a). (This - limitation does not apply to class templates because class template parameters - must always be explicitly specified.) In other words, without using the BOOST_IDENTITY_TYPE macro, C++ would - normally be able to implicitly deduce the function template parameter as shown - below: + can no longer be automatically deduced by the compiler form the function call + as in f(a). [2] (This limitation does not apply to class templates because class + template parameters must always be explicitly specified.) In other words, without + using the BOOST_IDENTITY_TYPE + macro, C++ would normally be able to automatically deduce the function template + parameter as shown below:

template<typename T>
 void g(
@@ -110,14 +112,14 @@
 }
 

-

g<char>(a); // OK.
-g(a);       // Also OK.
+

g<char>(a); // OK...
+g(a);       // ... and also OK.
 

- On some compilers (e.g., GCC), using this macro on abstract types (i.e., a - class with one or more pure virtual functions) generates a compiler error. - This can be worked around by manipulating the type adding and removing a reference - to it. + On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes + with one or more pure virtual functions) generates a compiler error. This can + be worked around by manipulating the type adding and removing a reference to + it.

Let's program a macro that performs a static assertion on a Template Meta-Programming (TMP) meta-function (similarly to Boost.MPL BOOST_MPL_ASSERT). The BOOST_IDENTITY_TYPE macro can be used @@ -132,7 +134,7 @@ template<typename T, bool b> struct abstract { static const bool value = b; - virtual void f(T const& x) = 0; + virtual void f(T const& x) = 0; // Pure virtual function. }; TMP_ASSERT( @@ -147,29 +149,32 @@

The BOOST_IDENTITY_TYPE macro - can be used either in the call of the user-defined macro (as shown by the examples - so far), or internally to the definition of the user macro. When BOOST_IDENTITY_TYPE is used internally, - the call of the user macro will only have to specify the extra parenthesis - (see also tmp_assert.cpp): + can be used either when calling a user-defined macro (as shown by the examples + so far), or internally in the definition of a user-defined macro (as shown + below). When BOOST_IDENTITY_TYPE + is used in the user macro definition, the call of the user macro will only + have to specify the extra parenthesis (see also tmp_assert.cpp):

#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
     /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
     BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
 
-TMP_ASSERT_PAREN(( boost::is_const<std::map<int, char> const> ));
-TMP_ASSERT( BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)) );
+// Specify only extra parenthesis `((...))`.
+TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
+// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
+TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
 

However, note that the user will always have to specify the extra parenthesis even when the macro parameters contain no comma:

-

TMP_ASSERT_PAREN(( boost::is_const<int const> )); // Always extra `()`.
-TMP_ASSERT( boost::is_const<int const> ); // No extra `()` and no macro.
+

TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
+TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
 

In some cases, using BOOST_IDENTITY_TYPE - internally might provide the best syntax for the user. For example, this is - the case for BOOST_MPL_ASSERT + within the user macro definition might provide the best syntax for the user. + For example, this is the case for BOOST_MPL_ASSERT because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis ((...)) instead of using BOOST_IDENTITY_TYPE: @@ -181,22 +186,21 @@ ));

However, in other situations it might be preferable to not require the extra - parenthesis in common cases and handle commas as special cases using the BOOST_IDENTITY_TYPE. For example, this - is the case for BOOST_LOCAL_FUNCTION - for which always requiring the extra parenthesis ((...)) - around the types would lead to an unnatural syntax for the local function parameter - types: + parenthesis in the common cases and handle commas as special cases using BOOST_IDENTITY_TYPE. For example, this + is the case for BOOST_LOCAL_FUNCTION for which always + requiring the extra parenthesis ((...)) + around the types would lead to an unnatural syntax for the local function signature:

int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
     return x + y;
 } BOOST_LOCAL_FUNCTION_NAME(add)
 

Instead requiring the user to specify BOOST_IDENTITY_TYPE - when needed allows for the more natural syntax BOOST_LOCAL_FUNCTION(int& + only when needed allows for the more natural syntax BOOST_LOCAL_FUNCTION(int& x, int& y) in the common cases when the parameter types contain no comma.

- The implementation of this library macro is equivalent to the following: [2] + The implementation of this library macro is equivalent to the following: [3]

#include <boost/type_traits/function_traits.hpp>
 
 #define BOOST_IDENTITY_TYPE(parenthesized_type) \
@@ -204,24 +208,29 @@
 

Essentially, the type is wrapped between round parenthesis (std::map<int, char>) - so it can be passed as a macro parameter even if it contain commas. Then the - parenthesized type is transformed into the type of a function returning void and with the specified type as the type - of the first and only argument void + so it can be passed as a single macro parameter even if it contains commas. + Then the parenthesized type is transformed into the type of a function returning + void and with the specified type + as the type of the first and only argument void (std::map<int, char>). Finally, the type of the first argument - arg1_type is extracted therefore - obtaining the original type from the parenthesized type (effectively stripping - the parenthesis from around the type). + arg1_type is extracted at compile-time + using the function_traits meta-function + therefore obtaining the original type from the parenthesized type (effectively + stripping the extra parenthesis from around the specified type).

Reference

Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas.

 
 BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not require variadic macros).

This macro must be prefixed by typename when used within templates. However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on an abstract types requires to add and remove a reference to the type.



[1] - Using variadic macros, it would be possible to use a single set of parenthesis - BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) - but variadic macros are not part of C++03 (even if nowadays they are supported - by most modern compilers and they are also part of C++11). -

[2] + Using variadic macros, it would be possible to require a single set of extra + parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 + (even if nowadays they are supported by most modern compilers and they are + also part of C++11). +

[2] + This is because the implementation of BOOST_IDENTITY_TYPE + wraps the specified type within a meta-function. +

[3] There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation. This code is for explanatory purposes only. diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk index 2723d33..3ef0b12 100644 --- a/identity_type/doc/identity_type.qbk +++ b/identity_type/doc/identity_type.qbk @@ -28,7 +28,7 @@ This library allows to wrap type expressions within round parenthesis so they ca [section Motivation] -Consider the following macro which declares a variable named `var`/n/ with the specified /type/ (see also [@../../test/var_error.cpp =var_error.cpp=]): +Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]): [var_error] @@ -68,7 +68,7 @@ In fact, a total of two sets of round parenthesis must be used: The parenthesis This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (because it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]). [footnote -Using variadic macros, it would be possible to use a single set of parenthesis `BOOST_IDENTITY_TYPE(`/type/`)` instead of two `BOOST_IDENTITY_TYPE((`/type/`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11). +Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11). ] [endsect] @@ -76,15 +76,18 @@ Using variadic macros, it would be possible to use a single set of parenthesis ` [section Templates] This macro must be prefixed by `typename` when used within templates. -For example, let's program a macro that declares a function parameter named `arg`/n/ with the specified /type/ (see also [@../../test/template.cpp =template.cpp=]): +For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]): [template_f_decl] [template_f_call] -However, note that the template parameter type `char` must be explicitly specified when invoking the function `f(a)`. -In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be implicitly determined by the compiler form the function call as in `f(a)`. +However, note that the template parameter `char` must be manually specified when invoking the function `f(a)`. +In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as in `f(a)`. +[footnote +This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function. +] (This limitation does not apply to class templates because class template parameters must always be explicitly specified.) -In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to implicitly deduce the function template parameter as shown below: +In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below: [template_g_decl] [template_g_call] @@ -93,7 +96,7 @@ In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ woul [section Abstract Types] -On some compilers (e.g., GCC), using this macro on abstract types (i.e., a class with one or more pure virtual functions) generates a compiler error. +On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error. This can be worked around by manipulating the type adding and removing a reference to it. Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]). @@ -106,8 +109,8 @@ In this case, if the meta-function is an abstract type, it needs to be manipulat [section Annex: Usage] -The [macroref BOOST_IDENTITY_TYPE] macro can be used either in the call of the user-defined macro (as shown by the examples so far), or internally to the definition of the user macro. -When [macroref BOOST_IDENTITY_TYPE] is used internally, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): +The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally in the definition of a user-defined macro (as shown below). +When [macroref BOOST_IDENTITY_TYPE] is used in the user macro definition, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): [tmp_assert_alternative] @@ -115,7 +118,7 @@ However, note that the user will /always/ have to specify the extra parenthesis [tmp_assert_alternative_always] -In some cases, using [macroref BOOST_IDENTITY_TYPE] internally might provide the best syntax for the user. +In some cases, using [macroref BOOST_IDENTITY_TYPE] within the user macro definition might provide the best syntax for the user. For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]: BOOST_MPL_ASSERT(( // Natural syntax. @@ -125,14 +128,14 @@ For example, this is the case for `BOOST_MPL_ASSERT` because the majority of tem > )); -However, in other situations it might be preferable to not require the extra parenthesis in common cases and handle commas as special cases using the [macroref BOOST_IDENTITY_TYPE]. -For example, this is the case for `BOOST_LOCAL_FUNCTION` for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function parameter types: +However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE]. +For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature: int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax. return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) -Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma. +Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma. [endsect] @@ -149,9 +152,9 @@ This code is for explanatory purposes only. #define BOOST_IDENTITY_TYPE(parenthesized_type) \ boost::function_traits::arg1_type -Essentially, the type is wrapped between round parenthesis `(std::map)` so it can be passed as a macro parameter even if it contain commas. +Essentially, the type is wrapped between round parenthesis `(std::map)` so it can be passed as a single macro parameter even if it contains commas. Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map)`. -Finally, the type of the first argument `arg1_type` is extracted therefore obtaining the original type from the parenthesized type (effectively stripping the parenthesis from around the type). +Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type). [endsect] diff --git a/identity_type/test/template.cpp b/identity_type/test/template.cpp index ec42628..dfc1097 100644 --- a/identity_type/test/template.cpp +++ b/identity_type/test/template.cpp @@ -14,7 +14,7 @@ template void f( // Prefix macro with `typename` in templates. - ARG( typename BOOST_IDENTITY_TYPE((std::map)), 1 ) + ARG(typename BOOST_IDENTITY_TYPE((std::map)), 1) ) { std::cout << arg1[0] << std::endl; } @@ -34,13 +34,13 @@ int main() { std::map a; a[0] = 'a'; - f(a); // OK. - // f(a); // But error. + f(a); // OK... + // f(a); // ... but error. //] //[template_g_call - g(a); // OK. - g(a); // Also OK. + g(a); // OK... + g(a); // ... and also OK. //] return 0; diff --git a/identity_type/test/tmp_assert.cpp b/identity_type/test/tmp_assert.cpp index f482999..b8be643 100644 --- a/identity_type/test/tmp_assert.cpp +++ b/identity_type/test/tmp_assert.cpp @@ -39,14 +39,14 @@ TMP_ASSERT( BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) // Specify only extra parenthesis `((...))`. -TMP_ASSERT_PAREN(( boost::is_const const> )); +TMP_ASSERT_PAREN((boost::is_const const>)); // Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro. -TMP_ASSERT( BOOST_IDENTITY_TYPE((boost::is_const const>)) ); +TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const const>))); //] //[tmp_assert_alternative_always -TMP_ASSERT_PAREN(( boost::is_const )); // Always extra `((...))`. -TMP_ASSERT( boost::is_const ); // No extra `((...))` and no macro. +TMP_ASSERT_PAREN((boost::is_const)); // Always extra `((...))`. +TMP_ASSERT(boost::is_const); // No extra `((...))` and no macro. //] int main() { return 0; } diff --git a/identity_type/test/var.cpp b/identity_type/test/var.cpp index 896aa03..9ed165d 100644 --- a/identity_type/test/var.cpp +++ b/identity_type/test/var.cpp @@ -9,17 +9,17 @@ #define VAR(type, n) type var ## n -VAR( int, 1 ); // OK. +VAR(int, 1); // OK. //[var_typedef typedef std::map map_type; -VAR( map_type, 3 ); // OK. +VAR(map_type, 3); // OK. //] //[var_ok #include -VAR( BOOST_IDENTITY_TYPE((std::map)), 4 ); // OK. +VAR(BOOST_IDENTITY_TYPE((std::map)), 4); // OK. //] int main() { return 0; } diff --git a/identity_type/test/var_error.cpp b/identity_type/test/var_error.cpp index b69817d..efb9743 100644 --- a/identity_type/test/var_error.cpp +++ b/identity_type/test/var_error.cpp @@ -10,8 +10,8 @@ //[var_error #define VAR(type, n) type var ## n -VAR( int, 1 ); // OK. -VAR( std::map, 2 ); // Error. +VAR(int, 1); // OK. +VAR(std::map, 2); // Error. //] int main() { return 0; } From 2a6cd0c9c4ab9cd5dd04d32699d6731bea4edec4 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Thu, 22 Mar 2012 20:54:20 +0000 Subject: [PATCH 06/90] Split Utility/IdentityType and Functional/OverloadedFunction tests into smaller tests. Updated docs for ScopeExit, LocalFunction, Utility/IdentityType, and Functional/OverloadedFunction. [SVN r77484] --- identity_type/doc/html/index.html | 26 +++++++++++--- identity_type/doc/identity_type.qbk | 24 +++++++++---- identity_type/test/Jamfile.v2 | 4 ++- identity_type/test/abstract.cpp | 35 +++++++++++++++++++ identity_type/test/noncopyable.cpp | 25 +++++++++++++ .../test/{tmp_assert.cpp => paren.cpp} | 32 ++++------------- 6 files changed, 110 insertions(+), 36 deletions(-) create mode 100644 identity_type/test/abstract.cpp create mode 100644 identity_type/test/noncopyable.cpp rename identity_type/test/{tmp_assert.cpp => paren.cpp} (65%) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index cc6f4b5..b7a5b38 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -2,7 +2,8 @@ Caminiti

Distributed under 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) -

This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas. @@ -126,7 +127,7 @@ to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters). In this case, if the meta-function is an abstract type, it needs to be manipulated adding - and removing a reference to it (see also tmp_assert.cpp): + and removing a reference to it (see also abstract.cpp):

#define TMP_ASSERT(metafunction) \
     BOOST_STATIC_ASSERT(metafunction::value)
@@ -147,20 +148,36 @@
     >::type
 );
 

+

+ The authors originally developed and tested the library on: +

  1. + GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features + enabled -std=c++0x) on + Cygwin. +
  2. + Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. +

+ See the library regressions + test results for detailed information on supported compilers and platforms.

The BOOST_IDENTITY_TYPE macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally in the definition of a user-defined macro (as shown below). When BOOST_IDENTITY_TYPE is used in the user macro definition, the call of the user macro will only - have to specify the extra parenthesis (see also tmp_assert.cpp): + have to specify the extra parenthesis (see also paren.cpp):

#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
     /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
     BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
 
+#define TMP_ASSERT(metafunction) \
+    BOOST_STATIC_ASSERT(metafunction::value)
+
 // Specify only extra parenthesis `((...))`.
 TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
+
 // Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
 TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
 

@@ -169,6 +186,7 @@ the extra parenthesis even when the macro parameters contain no comma:

TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
+
 TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
 

@@ -221,7 +239,7 @@ BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not require variadic macros).

This macro must be prefixed by typename when used within templates. However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on an abstract types requires to add and remove a reference to the type.



[1] Using variadic macros, it would be possible to require a single set of extra parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk index 3ef0b12..de8cfa1 100644 --- a/identity_type/doc/identity_type.qbk +++ b/identity_type/doc/identity_type.qbk @@ -24,7 +24,8 @@ This library allows to wrap type expressions within round parenthesis so they ca [import ../test/var_error.cpp] [import ../test/var.cpp] [import ../test/template.cpp] -[import ../test/tmp_assert.cpp] +[import ../test/abstract.cpp] +[import ../test/paren.cpp] [section Motivation] @@ -101,22 +102,33 @@ This can be worked around by manipulating the type adding and removing a referen Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]). The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters). -In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): +In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]): -[tmp_assert_abstract] +[abstract] + +[endsect] + +[section Compilers and Platforms] + +The authors originally developed and tested the library on: + +# GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin. +# Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. + +See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for detailed information on supported compilers and platforms. [endsect] [section Annex: Usage] The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally in the definition of a user-defined macro (as shown below). -When [macroref BOOST_IDENTITY_TYPE] is used in the user macro definition, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/tmp_assert.cpp =tmp_assert.cpp=]): +When [macroref BOOST_IDENTITY_TYPE] is used in the user macro definition, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]): -[tmp_assert_alternative] +[paren] However, note that the user will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma: -[tmp_assert_alternative_always] +[paren_always] In some cases, using [macroref BOOST_IDENTITY_TYPE] within the user macro definition might provide the best syntax for the user. For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]: diff --git a/identity_type/test/Jamfile.v2 b/identity_type/test/Jamfile.v2 index 482c0c0..5cb5036 100644 --- a/identity_type/test/Jamfile.v2 +++ b/identity_type/test/Jamfile.v2 @@ -10,5 +10,7 @@ import testing ; compile-fail var_error.cpp ; run var.cpp ; run template.cpp ; -run tmp_assert.cpp ; +run abstract.cpp ; +run noncopyable.cpp ; +run paren.cpp ; diff --git a/identity_type/test/abstract.cpp b/identity_type/test/abstract.cpp new file mode 100644 index 0000000..39b10c3 --- /dev/null +++ b/identity_type/test/abstract.cpp @@ -0,0 +1,35 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under 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) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include +#include + +//[abstract +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template +struct abstract { + static const bool value = b; + virtual void f(T const& x) = 0; // Pure virtual function. +}; + +TMP_ASSERT( + boost::remove_reference< // Add and remove + BOOST_IDENTITY_TYPE(( // reference for + boost::add_reference< // abstract type. + abstract + >::type + )) + >::type +); +//] + +int main() { return 0; } + diff --git a/identity_type/test/noncopyable.cpp b/identity_type/test/noncopyable.cpp new file mode 100644 index 0000000..2819e68 --- /dev/null +++ b/identity_type/test/noncopyable.cpp @@ -0,0 +1,25 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under 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) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include + +//[noncopyable +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template +struct noncopyable : boost::noncopyable { + static const T value = init; +}; + +TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable))); +//] + +int main() { return 0; } + diff --git a/identity_type/test/tmp_assert.cpp b/identity_type/test/paren.cpp similarity index 65% rename from identity_type/test/tmp_assert.cpp rename to identity_type/test/paren.cpp index b8be643..51b355f 100644 --- a/identity_type/test/tmp_assert.cpp +++ b/identity_type/test/paren.cpp @@ -8,44 +8,26 @@ #include #include #include -#include -#include #include -//[tmp_assert_abstract -#define TMP_ASSERT(metafunction) \ - BOOST_STATIC_ASSERT(metafunction::value) - -template -struct abstract { - static const bool value = b; - virtual void f(T const& x) = 0; // Pure virtual function. -}; - -TMP_ASSERT( - boost::remove_reference< // Add and remove - BOOST_IDENTITY_TYPE(( // reference for - boost::add_reference< // abstract type. - abstract - >::type - )) - >::type -); -//] - -//[tmp_assert_alternative +//[paren #define TMP_ASSERT_PAREN(parenthesized_metafunction) \ /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + // Specify only extra parenthesis `((...))`. TMP_ASSERT_PAREN((boost::is_const const>)); + // Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro. TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const const>))); //] -//[tmp_assert_alternative_always +//[paren_always TMP_ASSERT_PAREN((boost::is_const)); // Always extra `((...))`. + TMP_ASSERT(boost::is_const); // No extra `((...))` and no macro. //] From 9fa5d635251a721933519fed7048e0bf4f121ece Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sun, 25 Mar 2012 15:58:40 +0000 Subject: [PATCH 07/90] Utility: Apply patch for 6570: Adding noexcept to boost::declval [SVN r77539] --- include/boost/utility/declval.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/utility/declval.hpp b/include/boost/utility/declval.hpp index 41ec3dc..123f776 100644 --- a/include/boost/utility/declval.hpp +++ b/include/boost/utility/declval.hpp @@ -13,6 +13,7 @@ //----------------------------------------------------------------------------// #include +#include //----------------------------------------------------------------------------// // // @@ -36,9 +37,13 @@ namespace boost { +#if !defined(BOOST_NO_RVALUE_REFERENCES) template typename add_rvalue_reference::type declval(); //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 From 799b066e7de6a601c3ecc4698ad1c2e516c4a82c Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sun, 25 Mar 2012 18:28:24 +0000 Subject: [PATCH 08/90] Utility: Added doc for Adding noexcept to boost::declval [SVN r77543] --- doc/declval.qbk | 23 +++++++++++++++++------ doc/html/declval.html | 35 ++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/doc/declval.qbk b/doc/declval.qbk index 8b59178..9774422 100644 --- a/doc/declval.qbk +++ b/doc/declval.qbk @@ -1,7 +1,6 @@ [/ / Copyright (c) 2008 Howard Hinnant - / Copyright (c) 2008 Beman Dawes - / Copyright (c) 2009-20010 Vicente J. Botet Escriba + / Copyright (c) 2009-20012 Vicente J. Botet Escriba / / 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) @@ -10,11 +9,9 @@ [article Declval [quickbook 1.5] [authors [Hinnant, Howard]] - [authors [Dawes, Beman]] [authors [Botet Escriba, Vicente J.]] [copyright 2008 Howard Hinnant] - [copyright 2008 Beman Dawes] - [copyright 2009-2010 Vicente J. Botet Escriba] + [copyright 2009-2012 Vicente J. Botet Escriba] [license Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -77,7 +74,7 @@ This extremely light-weight function is expected to be part of the daily tool-bo namespace boost { template - typename add_rvalue_reference::type declval(); //noexcept; // as unevaluated operand + typename add_rvalue_reference::type declval() noexcept; // as unevaluated operand } // namespace boost @@ -100,5 +97,19 @@ Declares a function template convert which only participates in overloading if t [endsect] +[/===============] +[section History] +[/===============] + +[heading boost 1.50] + +New Features: + +* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval. + + +[endsect] + + diff --git a/doc/html/declval.html b/doc/html/declval.html index 2810dc4..7791057 100644 --- a/doc/html/declval.html +++ b/doc/html/declval.html @@ -3,7 +3,7 @@ Declval - + @@ -27,17 +27,13 @@ Howard Hinnant

-Beman Dawes -

-

Vicente J. Botet Escriba

-
-
+
-

+

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)

@@ -50,9 +46,10 @@
Overview
Reference
+
History
-
+
@@ -112,7 +109,7 @@ is expected to be part of the daily tool-box of the C++0x programmer.

-
+
@@ -122,7 +119,7 @@
namespace boost {
 
     template <typename T>
-    typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
+    typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
 
 }  // namespace boost
 
@@ -152,9 +149,25 @@ if the type From can be explicitly converted to type To.

+
+ +

+ + boost 1.50 +

+

+ New Features: +

+
  • + #6570 + Adding noexcept to boost::declval. +
+
- +

Last revised: April 06, 2011 at 20:06:10 GMT

Last revised: March 25, 2012 at 18:26:23 GMT


From 2cfe775694987332f19c0da54b26a02b2ae6c570 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sun, 25 Mar 2012 23:17:39 +0000 Subject: [PATCH 09/90] Utility: Fix for Adding noexcept to boost::declval [SVN r77552] --- include/boost/utility/declval.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/utility/declval.hpp b/include/boost/utility/declval.hpp index 123f776..54b3158 100644 --- a/include/boost/utility/declval.hpp +++ b/include/boost/utility/declval.hpp @@ -39,7 +39,7 @@ namespace boost { #if !defined(BOOST_NO_RVALUE_REFERENCES) template - typename add_rvalue_reference::type declval(); //noexcept; // as unevaluated operand + typename add_rvalue_reference::type declval() BOOST_NOEXCEPT; // as unevaluated operand #else template typename add_lvalue_reference::type declval() BOOST_NOEXCEPT; // as unevaluated operand From c11e08b6b71d3a2ae917f1495d344f5eeb2a1ffb Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Mon, 26 Mar 2012 17:07:17 +0000 Subject: [PATCH 10/90] Utility: Rollback unwanted commit while adding noexcept to boost::declval [SVN r77562] --- include/boost/utility/declval.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/utility/declval.hpp b/include/boost/utility/declval.hpp index 54b3158..2924cd7 100644 --- a/include/boost/utility/declval.hpp +++ b/include/boost/utility/declval.hpp @@ -37,13 +37,13 @@ namespace boost { -#if !defined(BOOST_NO_RVALUE_REFERENCES) +//#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 +//#else +// template +// typename add_lvalue_reference::type declval() BOOST_NOEXCEPT; // as unevaluated operand +//#endif } // namespace boost #endif // BOOST_TYPE_TRAITS_EXT_DECLVAL__HPP From acf8b66a4f88d0ffb7c2a93c59cd2683a49b751b Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sun, 1 Apr 2012 20:38:36 +0000 Subject: [PATCH 11/90] Applied patch from Michel Morin to fix #6755. Updated copyright to recognize contributors from the past several years. [SVN r77702] --- include/boost/utility/detail/result_of_iterate.hpp | 7 ++++++- test/result_of_test.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 1ec857a..29fcd78 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -5,6 +5,11 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012. +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or +// copy at http://www.boost.org/LICENSE_1_0.txt) + // For more information, see http://www.boost.org/libs/utility #if !defined(BOOST_PP_IS_ITERATING) # error Boost result_of - do not include this file! @@ -40,7 +45,7 @@ template struct result_of : mpl::if_< - mpl::or_< is_pointer, is_member_function_pointer > + is_member_function_pointer , detail::tr1_result_of_impl< typename remove_cv::type, typename remove_cv::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 39f6c3b..52018d1 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -193,7 +193,6 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -205,6 +204,7 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, double>::value)); BOOST_STATIC_ASSERT((is_same::type, const double>::value)); From a7e8d28621a4803cb61f728a7542dce0872f5c9d Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Tue, 10 Apr 2012 21:53:28 +0000 Subject: [PATCH 12/90] Updated IdentityType docs. [SVN r77902] --- identity_type/doc/html/index.html | 85 ++++++++++++------------- identity_type/doc/identity_type.qbk | 43 +++++-------- include/boost/utility/identity_type.hpp | 11 ++-- 3 files changed, 64 insertions(+), 75 deletions(-) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index b7a5b38..b2f2e30 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -2,8 +2,7 @@ Caminiti

Distributed under 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) -

This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas. @@ -37,21 +36,23 @@ 2

Note that, differently from the compiler, the preprocessor only recognizes - round parameters (). Angular - <> or squared [] parenthesis are not used by the preprocessor - when parsing the macro parameters. + round parenthesis (). Angular + <> and squared [] parenthesis are not recognized by the preprocessor + when parsing macro parameters.

In some cases, it might be possible to workaround this issue by avoiding to - pass the type expression to the macro all together. For example, in some cases - a typedef can be used to specify - the type expression with the commas outside the macro (see also var.cpp): + pass the type expression to the macro all together. For example, in the case + above a typedef could have been + used to specify the type expression with the commas outside the macro (see + also var.cpp):

typedef std::map<int, char> map_type;
 VAR(map_type, 3); // OK.
 

- When this is not possible or desired (e.g., see the function template f in the section below), the library header - boost/utility/identity_type.hpp + When this is neither possible nor desired (e.g., see the function template + f in the section below), this + library header boost/utility/identity_type.hpp defines a macro BOOST_IDENTITY_TYPE which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also var.cpp). @@ -61,15 +62,21 @@ VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.

- This macro expands to an expression that evaluates (at compile-time) to the - specified type. The specified type is never split into multiple macro parameters - because it is always wrapped by a set of extra round parenthesis (). In fact, a total of two sets of round parenthesis - must be used: The parenthesis to invoke the macro BOOST_IDENTITY_TYPE(...) plus the inner parenthesis to wrap the + The BOOST_IDENTITY_TYPE macro + expands to an expression that evaluates (at compile-time) to the specified + type. The specified type is never split into multiple macro parameters because + it is always wrapped by a set of extra round parenthesis (). + In fact, a total of two sets of round parenthesis must be used: The parenthesis + to invoke the macro BOOST_IDENTITY_TYPE(...) plus the inner parenthesis to wrap the type passed to the macro BOOST_IDENTITY_TYPE((...)).

This macro works on any C++03 - compiler (because it does not use variadic - macros). [1] + compiler (and it does not use variadic + macros). [1] The authors originally developed and tested this library using + GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled + -std=c++0x) on Cygwin + and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library regressions + test results for more information on supported compilers and platforms.

This macro must be prefixed by typename when used within templates. For example, let's program a macro that declares @@ -95,11 +102,12 @@

However, note that the template parameter char - must be manually specified when invoking the function f<char>(a). In fact, + must be manually specified when invoking the function as in f<char>(a). In fact, when the BOOST_IDENTITY_TYPE macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call - as in f(a). [2] (This limitation does not apply to class templates because class + as f(a) would + have done. [2] (This limitation does not apply to class templates because class template parameters must always be explicitly specified.) In other words, without using the BOOST_IDENTITY_TYPE macro, C++ would normally be able to automatically deduce the function template @@ -119,8 +127,7 @@

On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error. This can - be worked around by manipulating the type adding and removing a reference to - it. + be avoided by manipulating the type adding and removing a reference to it.

Let's program a macro that performs a static assertion on a Template Meta-Programming (TMP) meta-function (similarly to Boost.MPL BOOST_MPL_ASSERT). The BOOST_IDENTITY_TYPE macro can be used @@ -148,25 +155,13 @@ >::type );

-

- The authors originally developed and tested the library on: -

  1. - GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features - enabled -std=c++0x) on - Cygwin. -
  2. - Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. -

- See the library regressions - test results for detailed information on supported compilers and platforms.

The BOOST_IDENTITY_TYPE macro can be used either when calling a user-defined macro (as shown by the examples - so far), or internally in the definition of a user-defined macro (as shown - below). When BOOST_IDENTITY_TYPE - is used in the user macro definition, the call of the user macro will only - have to specify the extra parenthesis (see also paren.cpp): + so far), or internally when implementing a user-defined macro (as shown below). + When BOOST_IDENTITY_TYPE is + used in the implementation of the user-defined macro, the caller of the user + macro will have to specify the extra parenthesis (see also paren.cpp):

#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
     /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
@@ -182,7 +177,7 @@
 TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
 

- However, note that the user will always have to specify + However, note that the caller will always have to specify the extra parenthesis even when the macro parameters contain no comma:

TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
@@ -191,8 +186,8 @@
 

In some cases, using BOOST_IDENTITY_TYPE - within the user macro definition might provide the best syntax for the user. - For example, this is the case for BOOST_MPL_ASSERT + in the implementation of the user-defined macro might provide the best syntax + for the caller. For example, this is the case for BOOST_MPL_ASSERT because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis ((...)) instead of using BOOST_IDENTITY_TYPE: @@ -215,7 +210,9 @@ Instead requiring the user to specify BOOST_IDENTITY_TYPE only when needed allows for the more natural syntax BOOST_LOCAL_FUNCTION(int& x, int& y) in the common cases when the parameter types - contain no comma. + contain no comma (while still allowing to specify parameter types with commas + as special cases using BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& + x, int& y)).

The implementation of this library macro is equivalent to the following: [3] @@ -239,8 +236,8 @@ BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

-

This macro works on any C++03 compiler (it does not require variadic macros).

This macro must be prefixed by typename when used within templates. However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on an abstract types requires to add and remove a reference to the type.



[1] +BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+

This macro works on any C++03 compiler (it does not use variadic macros).

This macro must be prefixed by typename when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type.



[1] Using variadic macros, it would be possible to require a single set of extra parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are @@ -250,6 +247,6 @@ wraps the specified type within a meta-function.

[3] There is absolutely no guarantee that the macro is actually implemented using - the code listed in this documentation. This code is for explanatory purposes - only. + the code listed in this documentation. The listed code is for explanatory + purposes only.

diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk index de8cfa1..ede7510 100644 --- a/identity_type/doc/identity_type.qbk +++ b/identity_type/doc/identity_type.qbk @@ -47,30 +47,32 @@ The preprocessor interprets that unwrapped comma as a separation between macro p # `char>` # `2` -Note that, differently from the compiler, the preprocessor only recognizes round parameters `()`. -Angular `<>` or squared `[]` parenthesis are not used by the preprocessor when parsing the macro parameters. +Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`. +Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters. [endsect] [section Solution] In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together. -For example, in some cases a `typedef` can be used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]): +For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]): [var_typedef] -When this is not possible or desired (e.g., see the function template `f` in the section below), the library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]). +When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]). [var_ok] -This macro expands to an expression that evaluates (at compile-time) to the specified type. +The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type. The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`. In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`. -This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (because it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]). +This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]). [footnote Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11). ] +The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. +See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms. [endsect] @@ -82,8 +84,8 @@ For example, let's program a macro that declares a function parameter named `arg [template_f_decl] [template_f_call] -However, note that the template parameter `char` must be manually specified when invoking the function `f(a)`. -In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as in `f(a)`. +However, note that the template parameter `char` must be manually specified when invoking the function as in `f(a)`. +In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done. [footnote This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function. ] @@ -98,7 +100,7 @@ In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ woul [section Abstract Types] On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error. -This can be worked around by manipulating the type adding and removing a reference to it. +This can be avoided by manipulating the type adding and removing a reference to it. Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]). The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters). @@ -108,29 +110,18 @@ In this case, if the meta-function is an abstract type, it needs to be manipulat [endsect] -[section Compilers and Platforms] - -The authors originally developed and tested the library on: - -# GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin. -# Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. - -See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for detailed information on supported compilers and platforms. - -[endsect] - [section Annex: Usage] -The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally in the definition of a user-defined macro (as shown below). -When [macroref BOOST_IDENTITY_TYPE] is used in the user macro definition, the call of the user macro will only have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]): +The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below). +When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]): [paren] -However, note that the user will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma: +However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma: [paren_always] -In some cases, using [macroref BOOST_IDENTITY_TYPE] within the user macro definition might provide the best syntax for the user. +In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller. For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]: BOOST_MPL_ASSERT(( // Natural syntax. @@ -147,7 +138,7 @@ For example, this is the case for [@http://www.boost.org/libs/local_function `BO return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) -Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma. +Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map))& x, int& y)`). [endsect] @@ -156,7 +147,7 @@ Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when n The implementation of this library macro is equivalent to the following: [footnote There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation. -This code is for explanatory purposes only. +The listed code is for explanatory purposes only. ] #include diff --git a/include/boost/utility/identity_type.hpp b/include/boost/utility/identity_type.hpp index c297c49..4a1f6c4 100644 --- a/include/boost/utility/identity_type.hpp +++ b/include/boost/utility/identity_type.hpp @@ -28,14 +28,15 @@ This type expression can contain an arbitrary number of commas. } @EndParams -This macro works on any C++03 compiler (it does not require variadic macros). +This macro works on any C++03 compiler (it does not use variadic macros). This macro must be prefixed by typename when used within templates. -However, the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to -be explicitly specified when calling the function template). +Note that the compiler will not be able to automatically determine function +template parameters when they are wrapped with this macro (these parameters +need to be explicitly specified when calling the function template). -On some compilers (like GCC), using this macro on an abstract types requires to -add and remove a reference to the type. +On some compilers (like GCC), using this macro on abstract types requires to +add and remove a reference to the specified type. */ #define BOOST_IDENTITY_TYPE(parenthesized_type) \ /* must NOT prefix this with `::` to work with parenthesized syntax */ \ From 2637dfcc592c0a1e985ac889e1e589fd469801d2 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 11 Apr 2012 00:05:56 +0000 Subject: [PATCH 13/90] result_of uses decltype on compilers that implement N3276 [SVN r77903] --- .../utility/detail/result_of_iterate.hpp | 6 +-- include/boost/utility/result_of.hpp | 18 +++++++ utility.htm | 53 ++++++++++++------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 29fcd78..5cf30b6 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // defined(BOOST_NO_DECLTYPE) +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template : tr1_result_of { }; #endif -#endif // defined(BOOST_NO_DECLTYPE) +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) #undef BOOST_RESULT_OF_ARGS diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 77c26fe..93b7264 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -30,6 +30,24 @@ # define BOOST_RESULT_OF_NUM_ARGS 16 #endif +// 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. +#endif + +#ifndef BOOST_RESULT_OF_USE_TR1 +# ifndef BOOST_RESULT_OF_USE_DECLTYPE +# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif +# endif +#endif + namespace boost { template struct result_of; diff --git a/utility.htm b/utility.htm index 474a338..65ead22 100644 --- a/utility.htm +++ b/utility.htm @@ -161,14 +161,12 @@ void f() { resides in the header <boost/utility/result_of.hpp>.

-

If your compiler supports decltype, - then you can enable automatic result type deduction by - defining the macro BOOST_RESULT_OF_USE_DECLTYPE, - as in the following example.

+

If your compiler's support for decltype is + adequate, result_of automatically uses it to + deduce the result type of your callable.

-
#define BOOST_RESULT_OF_USE_DECLTYPE
-#include <boost/utility/result_of.hpp>
+                
#include <boost/utility/result_of.hpp>
 
 struct functor {
     template<class T>
@@ -180,21 +178,29 @@ struct functor {
 
 typedef boost::result_of<
     functor(int)
->::type type;
+>::type type; // type is int
-

If decltype is not enabled, +

You can test whether result_of is using + decltype checking if the macro + BOOST_RESULT_OF_USE_DECLTYPE is defined after + including result_of.hpp. You can also force + result_of to use decltype by + defining BOOST_RESULT_OF_USE_DECLTYPE prior + to including result_of.hpp.

+ +

If decltype is not used, then automatic result type deduction of function objects is not possible. Instead, result_of uses the following protocol to allow the programmer to specify a type. When F is a class type with a member type result_type, result_of<F(T1, T2, ..., - TN)> is + TN)>::type is F::result_type. When F does not contain result_type, result_of<F(T1, T2, ..., - TN)> is F::result<F(T1, + TN)>::type is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0. Note that it is the @@ -221,22 +227,29 @@ typedef boost::result_of< typedef boost::result_of< functor(int) ->::type type; +>::type type; // type is int -

In a future - release, BOOST_RESULT_OF_USE_DECLTYPE - may be enabled by default on compilers that - support decltype, so if you use the above - protocol please take care to ensure that - the result_type - and result<> members accurately - represent the result type. If you wish to continue to +

If you are writing a reusable function object + that should work with result_of, for + maximum portability, you might consider following + the above protocol even if your compiler has + proper decltype support. If you do, + take care to ensure that the + result_type and + result<> members accurately + represent the return type of + operator().

+ +

If you wish to continue to use the protocol on compilers that support decltype, use boost::tr1_result_of, which is also defined - in <boost/utility/result_of.hpp>.

+ in <boost/utility/result_of.hpp>. You can also define the macro + BOOST_RESULT_OF_USE_TR1, which causes + result_of to use the convention described + above instead of decltype.

This implementation of result_of From df9315101ee8202d6041fa484a7844a019436578 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 11 Apr 2012 00:13:10 +0000 Subject: [PATCH 14/90] whoops [SVN r77904] --- .../utility/detail/result_of_iterate.hpp | 6 +-- include/boost/utility/result_of.hpp | 18 ------- utility.htm | 53 +++++++------------ 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 5cf30b6..29fcd78 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#ifdef BOOST_RESULT_OF_USE_DECLTYPE +#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#else // defined(BOOST_NO_DECLTYPE) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template : tr1_result_of { }; #endif -#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#endif // defined(BOOST_NO_DECLTYPE) #undef BOOST_RESULT_OF_ARGS diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 93b7264..77c26fe 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -30,24 +30,6 @@ # define BOOST_RESULT_OF_NUM_ARGS 16 #endif -// 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. -#endif - -#ifndef BOOST_RESULT_OF_USE_TR1 -# ifndef BOOST_RESULT_OF_USE_DECLTYPE -# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE) -# define BOOST_RESULT_OF_USE_DECLTYPE -# else -# define BOOST_RESULT_OF_USE_TR1 -# endif -# endif -#endif - namespace boost { template struct result_of; diff --git a/utility.htm b/utility.htm index 65ead22..474a338 100644 --- a/utility.htm +++ b/utility.htm @@ -161,12 +161,14 @@ void f() { resides in the header <boost/utility/result_of.hpp>.

-

If your compiler's support for decltype is - adequate, result_of automatically uses it to - deduce the result type of your callable.

+

If your compiler supports decltype, + then you can enable automatic result type deduction by + defining the macro BOOST_RESULT_OF_USE_DECLTYPE, + as in the following example.

-
#include <boost/utility/result_of.hpp>
+                
#define BOOST_RESULT_OF_USE_DECLTYPE
+#include <boost/utility/result_of.hpp>
 
 struct functor {
     template<class T>
@@ -178,29 +180,21 @@ struct functor {
 
 typedef boost::result_of<
     functor(int)
->::type type; // type is int
+>::type type;
-

You can test whether result_of is using - decltype checking if the macro - BOOST_RESULT_OF_USE_DECLTYPE is defined after - including result_of.hpp. You can also force - result_of to use decltype by - defining BOOST_RESULT_OF_USE_DECLTYPE prior - to including result_of.hpp.

- -

If decltype is not used, +

If decltype is not enabled, then automatic result type deduction of function objects is not possible. Instead, result_of uses the following protocol to allow the programmer to specify a type. When F is a class type with a member type result_type, result_of<F(T1, T2, ..., - TN)>::type is + TN)> is F::result_type. When F does not contain result_type, result_of<F(T1, T2, ..., - TN)>::type is F::result<F(T1, + TN)> is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0. Note that it is the @@ -227,29 +221,22 @@ typedef boost::result_of< typedef boost::result_of< functor(int) ->::type type; // type is int +>::type type; -

If you are writing a reusable function object - that should work with result_of, for - maximum portability, you might consider following - the above protocol even if your compiler has - proper decltype support. If you do, - take care to ensure that the - result_type and - result<> members accurately - represent the return type of - operator().

- -

If you wish to continue to +

In a future + release, BOOST_RESULT_OF_USE_DECLTYPE + may be enabled by default on compilers that + support decltype, so if you use the above + protocol please take care to ensure that + the result_type + and result<> members accurately + represent the result type. If you wish to continue to use the protocol on compilers that support decltype, use boost::tr1_result_of, which is also defined - in <boost/utility/result_of.hpp>. You can also define the macro - BOOST_RESULT_OF_USE_TR1, which causes - result_of to use the convention described - above instead of decltype.

+ in <boost/utility/result_of.hpp>.

This implementation of result_of From 4111de6f687d2a3fb4b22e8f4c377b625de6a4cb Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 11 Apr 2012 00:28:33 +0000 Subject: [PATCH 15/90] result_of uses decltype on compilers that implement N3276 [SVN r77905] --- .../utility/detail/result_of_iterate.hpp | 6 +-- include/boost/utility/result_of.hpp | 18 +++++++ test/result_of_test.cpp | 6 ++- utility.htm | 53 ++++++++++++------- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 29fcd78..5cf30b6 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // defined(BOOST_NO_DECLTYPE) +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template : tr1_result_of { }; #endif -#endif // defined(BOOST_NO_DECLTYPE) +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) #undef BOOST_RESULT_OF_ARGS diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 77c26fe..93b7264 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -30,6 +30,24 @@ # define BOOST_RESULT_OF_NUM_ARGS 16 #endif +// 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. +#endif + +#ifndef BOOST_RESULT_OF_USE_TR1 +# ifndef BOOST_RESULT_OF_USE_DECLTYPE +# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif +# endif +#endif + namespace boost { template struct result_of; diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 52018d1..c006d35 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -5,7 +5,11 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_RESULT_OF_USE_DECLTYPE +#include + +#ifndef BOOST_NO_DECLTYPE +# define BOOST_RESULT_OF_USE_DECLTYPE +#endif // For more information, see http://www.boost.org/libs/utility #include diff --git a/utility.htm b/utility.htm index 474a338..65ead22 100644 --- a/utility.htm +++ b/utility.htm @@ -161,14 +161,12 @@ void f() { resides in the header <boost/utility/result_of.hpp>.

-

If your compiler supports decltype, - then you can enable automatic result type deduction by - defining the macro BOOST_RESULT_OF_USE_DECLTYPE, - as in the following example.

+

If your compiler's support for decltype is + adequate, result_of automatically uses it to + deduce the result type of your callable.

-
#define BOOST_RESULT_OF_USE_DECLTYPE
-#include <boost/utility/result_of.hpp>
+                
#include <boost/utility/result_of.hpp>
 
 struct functor {
     template<class T>
@@ -180,21 +178,29 @@ struct functor {
 
 typedef boost::result_of<
     functor(int)
->::type type;
+>::type type; // type is int
-

If decltype is not enabled, +

You can test whether result_of is using + decltype checking if the macro + BOOST_RESULT_OF_USE_DECLTYPE is defined after + including result_of.hpp. You can also force + result_of to use decltype by + defining BOOST_RESULT_OF_USE_DECLTYPE prior + to including result_of.hpp.

+ +

If decltype is not used, then automatic result type deduction of function objects is not possible. Instead, result_of uses the following protocol to allow the programmer to specify a type. When F is a class type with a member type result_type, result_of<F(T1, T2, ..., - TN)> is + TN)>::type is F::result_type. When F does not contain result_type, result_of<F(T1, T2, ..., - TN)> is F::result<F(T1, + TN)>::type is F::result<F(T1, T2, ..., TN)>::type when N > 0 or void when N = 0. Note that it is the @@ -221,22 +227,29 @@ typedef boost::result_of< typedef boost::result_of< functor(int) ->::type type; +>::type type; // type is int -

In a future - release, BOOST_RESULT_OF_USE_DECLTYPE - may be enabled by default on compilers that - support decltype, so if you use the above - protocol please take care to ensure that - the result_type - and result<> members accurately - represent the result type. If you wish to continue to +

If you are writing a reusable function object + that should work with result_of, for + maximum portability, you might consider following + the above protocol even if your compiler has + proper decltype support. If you do, + take care to ensure that the + result_type and + result<> members accurately + represent the return type of + operator().

+ +

If you wish to continue to use the protocol on compilers that support decltype, use boost::tr1_result_of, which is also defined - in <boost/utility/result_of.hpp>.

+ in <boost/utility/result_of.hpp>. You can also define the macro + BOOST_RESULT_OF_USE_TR1, which causes + result_of to use the convention described + above instead of decltype.

This implementation of result_of From b9411f807f8a13ed3f59da5b827f62fc66d50dac Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Fri, 13 Apr 2012 01:02:02 +0000 Subject: [PATCH 16/90] Added Lorenzo Caminiti to maintainers.txt and libraries.htm. [SVN r77945] --- identity_type/doc/html/index.html | 6 +++--- identity_type/doc/identity_type.qbk | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index b2f2e30..2374aed 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -4,8 +4,8 @@ file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt)

- This library allows to wrap type expressions within round parenthesis so they - can be passed to macros even when they contain commas. + This library allows to wrap types within round parenthesis so they can always + be passed as macro parameters.

Consider the following macro which declares a variable named varn with the specified type (see also @@ -236,7 +236,7 @@ BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not use variadic macros).

This macro must be prefixed by typename when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type.



[1] Using variadic macros, it would be possible to require a single set of extra parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 diff --git a/identity_type/doc/identity_type.qbk b/identity_type/doc/identity_type.qbk index ede7510..1c97616 100644 --- a/identity_type/doc/identity_type.qbk +++ b/identity_type/doc/identity_type.qbk @@ -19,7 +19,7 @@ [category Utilities] ] -This library allows to wrap type expressions within round parenthesis so they can be passed to macros even when they contain commas. +This library allows to wrap types within round parenthesis so they can always be passed as macro parameters. [import ../test/var_error.cpp] [import ../test/var.cpp] From d5cacff7c6e349e71856a11e2b3c591f4aca33e0 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 25 Apr 2012 17:41:51 +0000 Subject: [PATCH 17/90] only use decltype when Boost.Config says it's ok [SVN r78195] --- include/boost/utility/detail/result_of_iterate.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 5cf30b6..f63faa4 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#ifdef BOOST_RESULT_OF_USE_DECLTYPE +#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#else // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template : tr1_result_of { }; #endif -#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#endif // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) #undef BOOST_RESULT_OF_ARGS From 36bc0a72acc95c062db3eeeb9edbf03fc66c04d0 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Sat, 28 Apr 2012 02:35:08 +0000 Subject: [PATCH 18/90] Updated docs. [SVN r78234] --- identity_type/doc/Jamfile.v2 | 2 +- identity_type/doc/html/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/identity_type/doc/Jamfile.v2 b/identity_type/doc/Jamfile.v2 index 29ea0a9..1fa4cc7 100644 --- a/identity_type/doc/Jamfile.v2 +++ b/identity_type/doc/Jamfile.v2 @@ -15,7 +15,7 @@ doxygen reference : ../../../../boost/utility/identity_type.hpp WARN_IF_UNDOCUMENTED=NO HIDE_UNDOC_MEMBERS=YES HIDE_UNDOC_CLASSES=YES - ALIASES=" Params=\"Parameters: \" Param{2}=\"\" EndParams=\"
\\1\\2
\" Returns=\"Returns:\" Note=\"Note:\" Warning=\"Warning:\" See=\"See:\" RefSect{1}=\"\\xmlonly\\1\\endxmlonly\" RefSectId{2}=\"\\xmlonly\\2\\endxmlonly\" RefClass{1}=\"\\xmlonly\\1\\endxmlonly\" RefFunc{1}=\"\\xmlonly\\1\\endxmlonly\" RefMacro{1}=\"\\xmlonly\\1\\endxmlonly\" " + ALIASES=" Params=\"Parameters: \" Param{2}=\"\" EndParams=\"
\\1\\2
\" Returns=\"Returns:\" Note=\"Note:\" Warning=\"Warning:\" See=\"See:\" RefSect{2}=\"\\xmlonly\\2\\endxmlonly\" RefClass{1}=\"\\xmlonly\\1\\endxmlonly\" RefFunc{1}=\"\\xmlonly\\1\\endxmlonly\" RefMacro{1}=\"\\xmlonly\\1\\endxmlonly\" " ; # This target must be called "index" so to generate "index.html" file. diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index 2374aed..cd4a495 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -236,7 +236,7 @@ BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not use variadic macros).

This macro must be prefixed by typename when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type.



[1] Using variadic macros, it would be possible to require a single set of extra parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 From 923caf44101210c24b0f59a8ac824e7b48c3ac64 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Mon, 30 Apr 2012 14:07:24 +0000 Subject: [PATCH 19/90] Fix for GCC-4.3.x. [SVN r78268] --- include/boost/utility/base_from_member.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp index 8d17522..67faa3b 100644 --- a/include/boost/utility/base_from_member.hpp +++ b/include/boost/utility/base_from_member.hpp @@ -128,7 +128,8 @@ protected: #if !defined(BOOST_NO_RVALUE_REFERENCES) && \ !defined(BOOST_NO_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) + !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \ + !(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)) template ::type> explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) From eb613e1b16aa325c4e37bd2c9075dcb6b64e94f6 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Mon, 7 May 2012 18:54:38 +0000 Subject: [PATCH 20/90] Resolved all LocalFunctions to-dos. Still trying to pin-point a VACPP internal error. [SVN r78371] --- identity_type/doc/html/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/identity_type/doc/html/index.html b/identity_type/doc/html/index.html index cd4a495..13869db 100644 --- a/identity_type/doc/html/index.html +++ b/identity_type/doc/html/index.html @@ -236,7 +236,7 @@ BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
 
-BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

This macro works on any C++03 compiler (it does not use variadic macros).

This macro must be prefixed by typename when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type.



[1] Using variadic macros, it would be possible to require a single set of extra parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 From 5fe00c4322261cbad20f78a1bdb2d366341c10ba Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Sat, 26 May 2012 20:39:22 +0000 Subject: [PATCH 21/90] Added identity_type.hpp to utility.hpp. Added static to Addable data members because they are references. Marked a couple of regression tests for release compilers. [SVN r78653] --- include/boost/utility.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/utility.hpp b/include/boost/utility.hpp index b909f29..82177c8 100644 --- a/include/boost/utility.hpp +++ b/include/boost/utility.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include From 8036d4370f7c67634143a8acea238915032ba96e Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Mon, 28 May 2012 18:44:24 +0000 Subject: [PATCH 22/90] Utility/declval: update history. [SVN r78729] --- doc/declval.qbk | 2 +- include/boost/utility/declval.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/declval.qbk b/doc/declval.qbk index 9774422..7bf5cb5 100644 --- a/doc/declval.qbk +++ b/doc/declval.qbk @@ -103,7 +103,7 @@ Declares a function template convert which only participates in overloading if t [heading boost 1.50] -New Features: +Fixes: * [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval. diff --git a/include/boost/utility/declval.hpp b/include/boost/utility/declval.hpp index 2924cd7..d74610c 100644 --- a/include/boost/utility/declval.hpp +++ b/include/boost/utility/declval.hpp @@ -13,7 +13,7 @@ //----------------------------------------------------------------------------// #include -#include +//#include //----------------------------------------------------------------------------// // // From a201cbe64621478f48d5a076bec7c95eb4de0caf Mon Sep 17 00:00:00 2001 From: John Maddock Date: Thu, 7 Jun 2012 12:32:56 +0000 Subject: [PATCH 23/90] Changes required to build PDF versions of docs. [SVN r78845] --- identity_type/doc/Jamfile.v2 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/identity_type/doc/Jamfile.v2 b/identity_type/doc/Jamfile.v2 index 1fa4cc7..0e1dd1b 100644 --- a/identity_type/doc/Jamfile.v2 +++ b/identity_type/doc/Jamfile.v2 @@ -29,3 +29,16 @@ boostbook doc : index boost.root=../../../../.. ; +# +# This is very imperfect - it results in both html and pdf docs being built, +# for some reason I can't get the "onehtml" format specified above to play nice +# with the usual incantations for mixed pdf/html builds. JM 06/2012. +# +boostbook pdf_doc : index + : + pdf + html:no + ; + +install pdf_doc_install : pdf_doc : . identity_type.pdf PDF ; + From 3558d61c51e77aa0fadd5e321bde925f27c922cb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 11 Jun 2012 01:33:10 +0000 Subject: [PATCH 24/90] Make the new pdf install rules explicit, and fix intrusive's. [SVN r78877] --- identity_type/doc/Jamfile.v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/identity_type/doc/Jamfile.v2 b/identity_type/doc/Jamfile.v2 index 0e1dd1b..07ca29e 100644 --- a/identity_type/doc/Jamfile.v2 +++ b/identity_type/doc/Jamfile.v2 @@ -41,4 +41,4 @@ boostbook pdf_doc : index ; install pdf_doc_install : pdf_doc : . identity_type.pdf PDF ; - +explicit pdf_doc_install ; From 37c5395e7a9207a05385e4d332f0ec7a55017e2e Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Tue, 10 Jul 2012 03:43:13 +0000 Subject: [PATCH 25/90] Ticket #7094, thanks 1czajnik [SVN r79398] --- include/boost/exception.hpp | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 include/boost/exception.hpp diff --git a/include/boost/exception.hpp b/include/boost/exception.hpp deleted file mode 100644 index 6424159..0000000 --- a/include/boost/exception.hpp +++ /dev/null @@ -1,11 +0,0 @@ -//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. - -//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) - -#ifndef UUID_1D94A7C6054E11DB9804B622A1EF5492 -#define UUID_1D94A7C6054E11DB9804B622A1EF5492 - -#error The header has been deprecated. Please #include instead. - -#endif From ff0cb364168707e47378fe87d68586131f957e8f Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sat, 1 Sep 2012 20:00:33 +0000 Subject: [PATCH 26/90] Fixes [6754]. Minor edits to documentation. [SVN r80352] --- test/result_of_test.cpp | 106 ++++++++++++++++++++++------------------ utility.htm | 34 ++++++------- 2 files changed, 76 insertions(+), 64 deletions(-) diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index c006d35..3f6da9e 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -7,10 +7,6 @@ #include -#ifndef BOOST_NO_DECLTYPE -# define BOOST_RESULT_OF_USE_DECLTYPE -#endif - // For more information, see http://www.boost.org/libs/utility #include #include @@ -66,6 +62,9 @@ struct int_result_type_and_float_result_of_and_char_return_template char operator()(char); }; +template +struct cv_overload_check {}; + struct result_of_member_function_template { template struct result; @@ -73,13 +72,13 @@ struct result_of_member_function_template template struct result { typedef That type; }; template typename result::type operator()(T); - template struct result { typedef const That type; }; + template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) const; - template struct result { typedef volatile That type; }; + template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) volatile; - template struct result { typedef const volatile That type; }; + template struct result { typedef cv_overload_check type; }; template typename result::type operator()(T) const volatile; template struct result { typedef That & type; }; @@ -95,13 +94,16 @@ struct result_of_member_function_template template typename result::type operator()(T const volatile &, T); }; -struct no_result_type_or_result_of +struct no_result_type_or_result { - int operator()(double); - short operator()(double) const; - unsigned int operator()(); - unsigned short operator()() volatile; - const unsigned short operator()() const volatile; + short operator()(double); + cv_overload_check operator()(double) const; + cv_overload_check operator()(double) volatile; + cv_overload_check operator()(double) const volatile; + int operator()(); + cv_overload_check operator()() const; + cv_overload_check operator()() volatile; + cv_overload_check operator()() const volatile; #if !defined(BOOST_NO_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); @@ -110,13 +112,16 @@ struct no_result_type_or_result_of }; template -struct no_result_type_or_result_of_template +struct no_result_type_or_result_template { - int operator()(double); - short operator()(double) const; - unsigned int operator()(); - unsigned short operator()() volatile; - const unsigned short operator()() const volatile; + short operator()(double); + cv_overload_check operator()(double) const; + cv_overload_check operator()(double) volatile; + cv_overload_check operator()(double) const volatile; + int operator()(); + cv_overload_check operator()() const; + cv_overload_check operator()() volatile; + cv_overload_check operator()() const volatile; #if !defined(BOOST_NO_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); @@ -161,7 +166,7 @@ int main() // Prior to decltype, result_of could not deduce the return type // nullary function objects unless they exposed a result_type. -#if !defined(BOOST_NO_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); @@ -173,14 +178,11 @@ int main() BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); #endif - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); - // Prior to decltype, result_of ignored a nested result<> if // result_type was defined. After decltype, result_of deduces the // actual return type of the function object, ignoring both // result<> and result_type. -#if !defined(BOOST_NO_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, char>::value)); BOOST_STATIC_ASSERT((is_same(char)>::type, char>::value)); #else @@ -188,6 +190,9 @@ int main() BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); #endif + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -211,18 +216,18 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, double>::value)); - BOOST_STATIC_ASSERT((is_same::type, const double>::value)); - BOOST_STATIC_ASSERT((is_same::type, volatile double>::value)); - BOOST_STATIC_ASSERT((is_same::type, const volatile double>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, double>::value)); - BOOST_STATIC_ASSERT((is_same::type, const double>::value)); - BOOST_STATIC_ASSERT((is_same::type, volatile double>::value)); - BOOST_STATIC_ASSERT((is_same::type, const volatile double>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, int &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); @@ -235,24 +240,31 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type,int>::value)); -#if !defined(BOOST_NO_DECLTYPE) - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, unsigned int>::value)); - BOOST_STATIC_ASSERT((is_same::type, short>::value)); - BOOST_STATIC_ASSERT((is_same::type, unsigned short>::value)); - BOOST_STATIC_ASSERT((is_same::type, const unsigned short>::value)); - BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); - BOOST_STATIC_ASSERT((is_same(void)>::type, unsigned int>::value)); - BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value)); - BOOST_STATIC_ASSERT((is_same(void)>::type, unsigned short>::value)); - BOOST_STATIC_ASSERT((is_same(void)>::type, const unsigned short>::value)); +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + 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)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + + BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); #if !defined(BOOST_NO_RVALUE_REFERENCES) - BOOST_STATIC_ASSERT((is_same::type, short>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, long>::value)); - BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value)); - BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value)); - BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value)); + BOOST_STATIC_ASSERT((is_same::type, short>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, long>::value)); + BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value)); #endif #endif diff --git a/utility.htm b/utility.htm index 65ead22..73bd692 100644 --- a/utility.htm +++ b/utility.htm @@ -163,7 +163,7 @@ void f() {

If your compiler's support for decltype is adequate, result_of automatically uses it to - deduce the result type of your callable.

+ deduce the result type of your callable object.

#include <boost/utility/result_of.hpp>
@@ -182,7 +182,7 @@ typedef boost::result_of<
                 

You can test whether result_of is using - decltype checking if the macro + decltype by checking if the macro BOOST_RESULT_OF_USE_DECLTYPE is defined after including result_of.hpp. You can also force result_of to use decltype by @@ -230,27 +230,27 @@ typedef boost::result_of< >::type type; // type is int -

If you are writing a reusable function object - that should work with result_of, for +

Since decltype is a new language + feature recently standardized in C++11, + if you are writing a function object + to be used with result_of, for maximum portability, you might consider following the above protocol even if your compiler has - proper decltype support. If you do, - take care to ensure that the + proper decltype support. If you wish to continue to + use the protocol on compilers that + support decltype, there are two options: + You can use boost::tr1_result_of, which is also + defined in <boost/utility/result_of.hpp>. + Alternatively, you can define the macro + BOOST_RESULT_OF_USE_TR1, which causes + result_of to use the protocol described + above instead of decltype. If you choose to + follow the protocol, take care to ensure that the result_type and result<> members accurately represent the return type of operator().

-

If you wish to continue to - use the protocol on compilers that - support decltype, - use boost::tr1_result_of, which is also - defined - in <boost/utility/result_of.hpp>. You can also define the macro - BOOST_RESULT_OF_USE_TR1, which causes - result_of to use the convention described - above instead of decltype.

-

This implementation of result_of requires class template partial specialization, the @@ -266,7 +266,7 @@ typedef boost::result_of< N1836, or, for motivation and design rationale, the result_of proposal.

- Contributed by Doug Gregor.

+

Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others

Class templates for the Base-from-Member Idiom

See separate documentation.

From e8440e8855126312d568db2b7c99c4f050440999 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 8 Sep 2012 13:54:41 +0000 Subject: [PATCH 27/90] Added result_of usage guideline. [SVN r80445] --- utility.htm | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/utility.htm b/utility.htm index 73bd692..09a8632 100644 --- a/utility.htm +++ b/utility.htm @@ -230,6 +230,51 @@ typedef boost::result_of< >::type type; // type is int +

The result template must be specialized for every valid calling signature of the function object. + If the operator() accepts arguments by (possibly const) reference and/or is const + qualified, the result specialization must take this into account. Type traits + and more generic specializations may help to reduce the number of result specializations. This way result_of users + will be able to specify argument types exactly according to the function object call expression. For example:

+ +
+
struct functor {
+    template<class> struct result;
+
+    // Use template parameter F to match the function object. This will allow result deduction for both const and non-const functor.
+    template<class F, class T>
+    struct result<F(T)> {
+        // When argument type is matched like above, remember that the type may be a (const-qualified) reference.
+        // Use type traits to transform the argument type.
+        typedef typename remove_cv<typename remove_reference<T>::type>::type argument_type;
+        typedef argument_type type;
+    };
+
+    // The operator can be called on both const and non-const functor. The argument can be lvalue or rvalue.
+    template<class T>
+    T operator()(T const& x) const
+    {
+        return x;
+    }
+};
+
+// All following result_of uses are valid and result in int
+typedef boost::result_of< functor(int) >::type type1; // the argument is rvalue
+functor f;
+type1 r1 = f(10);
+
+typedef boost::result_of< const functor(int) >::type type2; // the function object is const
+const functor cf;
+type2 r2 = cf(10);
+
+typedef boost::result_of< functor(int&) >::type type3; // the argument is lvalue
+int a = 10;
+type3 r3 = f(a);
+
+typedef boost::result_of< functor(int const&) >::type type4; // the argument is const lvalue
+const int ca = 10;
+type4 r4 = f(ca);
+
+

Since decltype is a new language feature recently standardized in C++11, if you are writing a function object From e9bbb50eb465fc31ebdc793f97ab07e69015ba0f Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sat, 8 Sep 2012 15:32:35 +0000 Subject: [PATCH 28/90] reverting [80445] which is still under discussion on the mailing list [SVN r80452] --- utility.htm | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/utility.htm b/utility.htm index 09a8632..73bd692 100644 --- a/utility.htm +++ b/utility.htm @@ -230,51 +230,6 @@ typedef boost::result_of< >::type type; // type is int -

The result template must be specialized for every valid calling signature of the function object. - If the operator() accepts arguments by (possibly const) reference and/or is const - qualified, the result specialization must take this into account. Type traits - and more generic specializations may help to reduce the number of result specializations. This way result_of users - will be able to specify argument types exactly according to the function object call expression. For example:

- -
-
struct functor {
-    template<class> struct result;
-
-    // Use template parameter F to match the function object. This will allow result deduction for both const and non-const functor.
-    template<class F, class T>
-    struct result<F(T)> {
-        // When argument type is matched like above, remember that the type may be a (const-qualified) reference.
-        // Use type traits to transform the argument type.
-        typedef typename remove_cv<typename remove_reference<T>::type>::type argument_type;
-        typedef argument_type type;
-    };
-
-    // The operator can be called on both const and non-const functor. The argument can be lvalue or rvalue.
-    template<class T>
-    T operator()(T const& x) const
-    {
-        return x;
-    }
-};
-
-// All following result_of uses are valid and result in int
-typedef boost::result_of< functor(int) >::type type1; // the argument is rvalue
-functor f;
-type1 r1 = f(10);
-
-typedef boost::result_of< const functor(int) >::type type2; // the function object is const
-const functor cf;
-type2 r2 = cf(10);
-
-typedef boost::result_of< functor(int&) >::type type3; // the argument is lvalue
-int a = 10;
-type3 r3 = f(a);
-
-typedef boost::result_of< functor(int const&) >::type type4; // the argument is const lvalue
-const int ca = 10;
-type4 r4 = f(ca);
-
-

Since decltype is a new language feature recently standardized in C++11, if you are writing a function object From a4e332c4c096d42010fb55dce7db5085c817dae7 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sun, 16 Sep 2012 00:39:41 +0000 Subject: [PATCH 29/90] updated docs to include guidelines, changes and various suggestions from Andrey Semashev, JeffLee Hellrung and others [SVN r80535] --- utility.htm | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 325 insertions(+), 6 deletions(-) diff --git a/utility.htm b/utility.htm index 73bd692..c46c515 100644 --- a/utility.htm +++ b/utility.htm @@ -143,7 +143,7 @@ void f() {

Class template result_of

The class template result_of helps determine the type of a - call expression. Given an lvalue f of + call expression. For example, given an lvalue f of type F and lvalues t1, t2, ..., tN of types T1, T2, ..., @@ -163,12 +163,16 @@ void f() {

If your compiler's support for decltype is adequate, result_of automatically uses it to - deduce the result type of your callable object.

+ deduce the type of the call expression, in which case + result_of<F(T1, T2, ..., + TN)>::type names the type + decltype(boost::declval<F>()(boost::declval<T1>(), + boost::declval<T2>(), ..., + boost::declval<TN>())), as in the + following example.

-
#include <boost/utility/result_of.hpp>
-
-struct functor {
+                
struct functor {
     template<class T>
     T operator()(T x)
     {
@@ -249,7 +253,7 @@ typedef boost::result_of<
                 result_type and
                 result<> members accurately
                 represent the return type of
-                operator().

+ operator() given a call expression.

This implementation of result_of @@ -266,6 +270,321 @@ typedef boost::result_of< N1836, or, for motivation and design rationale, the result_of proposal.

+ + +

Usage guidelines for boost::result_of

+
+ +

The following are general suggestions about when + and how to use boost::result_of.

+ +
    +
  1. If you are targeting C++11 and are not concerned + about portability to non-compliant compilers or + previous versions of the standard, then use + std::result_of. If std::result_of + meets your needs, then there's no reason to stop using + it.
  2. + +
  3. If you are targeting C++11 but may port your code + to legacy compilers at some time in the future, then + use boost::result_of with + decltype. When decltype is + used boost::result_of + and std::result_of are usually + interchangeable. See the documentation on + known differences + between boost::result_of and C++11 result_of.
  4. + +
  5. If compiler portability is required, + use boost::result_of with the TR1 protocol.
  6. +
+ +

Regardless of how you + configure boost::result_of, it is + important to bear in mind that the return type of a + function may change depending on its arguments, and + additionally, the return type of a member function may + change depending on the cv-qualification of the + object. boost::result_of must be passed + the appropriately cv-qualified types in order to + deduce the corresponding return type. For example: + +

+
struct functor {
+    int& operator()(int);
+    int const& operator()(int) const;
+
+    float& operator()(float&);
+    float const& operator()(float const&);
+};
+
+typedef boost::result_of<
+    functor(int)
+>::type type1; // type1 is int &
+
+typedef boost::result_of<
+    const functor(int)
+>::type type2; // type2 is int const &
+
+typedef boost::result_of<
+    functor(float&)
+>::type type3; // type3 is float &
+
+typedef boost::result_of<
+    functor(float const&)
+>::type type4; // type4 is float const &
+
+ + +

Usage guidelines for the TR1 result_of protocol

+
+ +

On compliant C++11 + compilers, boost::result_of can + use decltype to deduce the type of any + call expression, including calls to function + objects. However, on pre-C++11 compilers or on + compilers without adequate decltype support, + additional scaffolding is needed from function + objects as described above. The following are + suggestions about how to use the TR1 protocol.

+ +
    +
  • When the return type does not depend on the + argument types or the cv-qualification of the + function object, simply + define result_type. There is no need + to use the result template unless the + return type varies.
  • + +
  • Use the protocol specified type when defining + function prototypes. This can help ensure the + actual return type does not get out of sync with + the protocol specification. For example: + +
    +
    struct functor {
    +    typedef int result_type;
    +    result_type operator()(int);
    +};
    +
  • + +
  • Always specify the result + specialization near the corresponding + operator() overload. This can make it + easier to keep the specializations in sync with the + overloads. For example: + +
    +
    struct functor {
    +    template<class> struct result;
    +
    +    template<class F>
    +    struct result<F(int)> {
    +        typedef int& type;
    +    };
    +    result<functor(int)>::type operator()(int);
    +
    +    template<class F>
    +    struct result<const F(int)> {
    +        typedef int const& type;
    +    };
    +    result<const functor(int)>::type operator()(int) const;
    +};
    +
  • + +
  • Use type transformations to simplify + the result template specialization. For + example, the following uses + Boost.TypeTraits + to specialize the result template for + a single operator() that can be called on + both a const and non-const function object with + either an lvalue or rvalue argument. + +
    +
    struct functor {
    +    template<class> struct result;
    +
    +    template<class F, class T>
    +    struct result<F(T)> 
    +        : boost::remove_cv<
    +              typename boost::remove_reference<T>::type
    +          >
    +    {};
    +
    +    template<class T>
    +    T operator()(T const& x) const;
    +};
    +
  • +
+ + +

Known differences between boost::result_of and TR1 result_of

+
+ + When using decltype, boost::result_of + ignores the TR1 protocol and instead deduces the + return type of function objects directly + via decltype. In most situations, users + will not notice a difference, so long as they use the + protocol correctly. The following are situations in + which the type deduced + by boost::result_of is known to differ depending on + whether decltype or the TR1 protocol is + used. + +
    +
  • TR1 protocol misusage + +

    When using the TR1 + protocol, boost::result_of cannot + detect whether the actual type of a call to a + function object is the same as the type specified + by the protocol, which allows for the possibility + of inadvertent mismatches between the specified + type and the actual type. When + using decltype, these subtle bugs + may result in compilation errors. For example:

    + +
    +
    struct functor {
    +   typedef short result_type;
    +   int operator()(short);
    +};
    +
    +#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<boost::result_of<functor(short)>::type, int>::value
    +)); 
    +
    +#else
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<boost::result_of<functor(short)>::type, short>::value
    +));
    +
    +#endif
    +
    + +

    Note that the user can + force boost::result_of to use the TR1 + protocol even on platforms that + support decltype by + defining BOOST_RESULT_OF_USE_TR1.

  • + +
  • Nullary function objects + +

    When using the TR1 protocol, boost::result_of + cannot always deduce the type of calls to + nullary function objects, in which case the + type defaults to void. When using decltype, + boost::result_of always gives the actual type of the + call expression. For example:

    + +
    +
    struct functor {
    +   template<class> struct result {
    +       typedef int type;
    +   };
    +   int operator()();
    +};
    +
    +#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<boost::result_of<functor()>::type, int>::value
    +));
    +
    +#else
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<boost::result_of<functor()>::type, void>::value
    +));
    +
    +#endif
    +
    + +

    Note that there are some workarounds for the + nullary function problem. So long as the return + type does not vary, + result_type can always be used to + specify the return type regardless of arity. If the + return type does vary, then the user can + specialize boost::result_of itself for + nullary calls.

  • + +
  • Non-class prvalues and cv-qualification + +

    When using the TR1 + protocol, boost::result_of will + report the cv-qualified type specified + by result_type or + the result template regardless of + the actual cv-qualification of the call + expression. When using + decltype, boost::result_of + will report the actual type of the call expression, + which is not cv-qualified when the expression is a + non-class prvalue. For example:

    + +
    +
    struct functor {
    +   template<class> struct result;
    +   template<class F, class T> struct result<F(const T)> {
    +       typedef const T type;
    +   };
    +
    +   const short operator()(const short);
    +   int const & operator()(int const &);
    +};
    +
    +// Non-prvalue call expressions work the same with or without decltype.
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<
    +       boost::result_of<functor(int const &)>::type,
    +       int const &
    +::value
    +));
    +
    +// Non-class prvalue call expressions are not actually cv-qualified,
    +// but only the decltype-based result_of reports this accurately.
    +
    +#ifdef BOOST_RESULT_OF_USE_DECLTYPE
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<
    +       boost::result_of<functor(const short)>::type,
    +       short
    +::value
    +));
    +
    +#else
    +
    +BOOST_STATIC_ASSERT((
    +   boost::is_same<
    +       boost::result_of<functor(const short)>::type,
    +       const short
    +::value
    +));
    +
    +#endif
    +
  • +
+ + +

Known differences between boost::result_of and C++11 result_of

+
+ +

When using decltype, boost::result_of + implements most of the C++11 result_of + specification. One known exception is that + boost::result_of does not implement the + requirements regarding pointers to member data.

+

Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others

Class templates for the Base-from-Member Idiom

From b6a55f878c5aaf71121d80c8044a320fc549af13 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Mon, 17 Sep 2012 00:04:55 +0000 Subject: [PATCH 30/90] reverting [78195] in result_of_iterate.hpp to allow users to force result_of to use decltype [SVN r80550] --- include/boost/utility/detail/result_of_iterate.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index f63faa4..5cf30b6 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template : tr1_result_of { }; #endif -#endif // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) #undef BOOST_RESULT_OF_ARGS From ac9f617f7f629270180d8a2d75ce9da603b0161c Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Wed, 19 Sep 2012 23:10:08 +0000 Subject: [PATCH 31/90] SFINAE enabled result_of fixes [7343] [SVN r80605] --- .../utility/detail/result_of_iterate.hpp | 66 ++++++++++++++++++- include/boost/utility/result_of.hpp | 18 ++++- test/result_of_test.cpp | 26 ++++++++ 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 5cf30b6..df05bbf 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -58,17 +58,79 @@ struct result_of namespace detail { +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + template -struct cpp0x_result_of_impl +class is_callable { + typedef char (&pass)[1]; + typedef char (&fail)[2]; + + template + struct sub {}; + template + struct stub {}; + + template + static pass test(sub + , stub< + decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + ) + >* x = 0); + static fail test(...); + +public: + const static bool value = sizeof(pass) == sizeof(test(sub())); + typedef typename boost::mpl::bool_::type type; +}; + +template +struct cpp0x_result_of_impl + : lazy_enable_if< + is_callable + , cpp0x_result_of_impl + > +{}; + +template +struct cpp0x_result_of_impl { typedef decltype( boost::declval()( - BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), declval() BOOST_PP_INTERCEPT) + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) ) ) type; }; +#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template +struct cpp0x_result_of_impl()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + )>::type> { + typedef decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + ) type; +}; + +#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + } // namespace detail #else // defined(BOOST_RESULT_OF_USE_DECLTYPE) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 93b7264..222c9c9 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef BOOST_RESULT_OF_NUM_ARGS # define BOOST_RESULT_OF_NUM_ARGS 16 @@ -59,7 +60,22 @@ namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -template struct cpp0x_result_of_impl; + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template class is_callable; +template struct cpp0x_result_of_impl; + +#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template +struct result_of_always_void +{ + typedef void type; +}; +template struct cpp0x_result_of_impl {}; + +#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) template struct result_of_void_impl diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 3f6da9e..0c2834f 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -129,6 +129,27 @@ struct no_result_type_or_result_template #endif }; +// sfinae_tests are derived from example code from Joel de Guzman, +// which demonstrated the interaction between result_of and SFINAE. +template +typename boost::result_of::type +sfinae_test(F f, Arg const& arg) +{ + return f(arg); +} + +template +typename boost::result_of::type +sfinae_test(F f, Arg& arg) +{ + return f(arg); +} + +int sfinae_test_f(int& i) +{ + return i; +} + struct X {}; int main() @@ -268,5 +289,10 @@ int main() #endif #endif +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + int i = 123; + sfinae_test(sfinae_test_f, i); +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) + return 0; } From 57d65d6a94a39f713dad26705b131754e9ca3821 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Thu, 20 Sep 2012 17:06:34 +0000 Subject: [PATCH 32/90] untab-ify [SVN r80608] --- include/boost/utility/detail/result_of_iterate.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index df05bbf..4d35fc0 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -121,7 +121,7 @@ struct cpp0x_result_of_impl()( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) ) - )>::type> { + )>::type> { typedef decltype( boost::declval()( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) From 1cfe3145b46abbd51857c9535ef64f130c80318d Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sat, 22 Sep 2012 19:15:37 +0000 Subject: [PATCH 33/90] sfinae-friendly result_of implementation for compilers that don't have extended sfinae for expressions [SVN r80636] --- .../utility/detail/result_of_iterate.hpp | 127 +++++++++--------- include/boost/utility/result_of.hpp | 74 ++++++++-- 2 files changed, 126 insertions(+), 75 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 4d35fc0..98063cd 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -23,31 +23,29 @@ #endif #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) -template +template struct tr1_result_of : mpl::if_< mpl::or_< is_pointer, is_member_function_pointer > , boost::detail::tr1_result_of_impl< - typename remove_cv::type, - typename remove_cv::type(BOOST_RESULT_OF_ARGS), + typename remove_cv::type, + typename remove_cv::type(BOOST_RESULT_OF_ARGS), (boost::detail::has_result_type::value)> , boost::detail::tr1_result_of_impl< F, - F(BOOST_RESULT_OF_ARGS), + F(BOOST_RESULT_OF_ARGS), (boost::detail::has_result_type::value)> >::type { }; #endif #ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. -template +template struct result_of : mpl::if_< is_member_function_pointer , detail::tr1_result_of_impl< - typename remove_cv::type, + typename remove_cv::type, typename remove_cv::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false > , detail::cpp0x_result_of_impl< @@ -58,51 +56,60 @@ struct result_of namespace detail { -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#ifdef BOOST_NO_SFINAE_EXPR -template -class is_callable { - typedef char (&pass)[1]; - typedef char (&fail)[2]; +template +struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()); - template - struct sub {}; - template - struct stub {}; - - template - static pass test(sub - , stub< - decltype( - boost::declval()( - BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) - ) - ) - >* x = 0); - static fail test(...); - -public: - const static bool value = sizeof(pass) == sizeof(test(sub())); - typedef typename boost::mpl::bool_::type type; +template +struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) { + R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const; + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; }; -template +template +struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()); + +template +struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION()) + : mpl::eval_if< + is_class::type>, + result_of_wrap_callable, + mpl::identity::type> > + > +{}; + +template +struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) { + typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())::type wrapper_t; + static const bool value = ( + sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type( + (boost::declval()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT)), 0) + )) + ); + typedef mpl::bool_ type; +}; + +template struct cpp0x_result_of_impl : lazy_enable_if< - is_callable + BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) , cpp0x_result_of_impl > {}; -template +template struct cpp0x_result_of_impl { typedef decltype( @@ -112,11 +119,10 @@ struct cpp0x_result_of_impl -struct cpp0x_result_of_impl +struct cpp0x_result_of_impl()( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) @@ -129,15 +135,14 @@ struct cpp0x_result_of_impl +template struct result_of : tr1_result_of { }; #endif @@ -146,27 +151,24 @@ struct result_of #undef BOOST_RESULT_OF_ARGS -#if BOOST_PP_ITERATION() >= 1 +#if BOOST_PP_ITERATION() >= 1 namespace detail { -template +template struct tr1_result_of_impl { typedef R type; }; -template +template struct tr1_result_of_impl { typedef R type; }; #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) -template +template struct tr1_result_of_impl @@ -174,8 +176,7 @@ struct tr1_result_of_impl +template struct tr1_result_of_impl +template struct tr1_result_of_impl +template struct tr1_result_of_impl -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include +#include #include +#include #include #include #include +#include #include #include @@ -61,21 +66,68 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#ifdef BOOST_NO_SFINAE_EXPR + +template T result_of_decay(T); + +struct result_of_private_type +{ + result_of_private_type const &operator,(int) const; +}; + +template +struct result_of_callable_class : C { + result_of_callable_class(); + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; +}; + +typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 +typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 + +template +result_of_no_type result_of_is_private_type(T const &); + +result_of_yes_type result_of_is_private_type(result_of_private_type const &); + +template class Wrapper, typename C> +struct result_of_wrap_callable { + typedef Wrapper type; +}; + +template class Wrapper, typename C> +struct result_of_wrap_callable { + typedef typename result_of_wrap_callable::type &type; +}; + +template class Wrapper, typename C> +struct result_of_wrap_callable { + typedef typename result_of_wrap_callable::type const type; +}; + +template class Wrapper, typename C> +struct result_of_wrap_callable { + typedef typename result_of_wrap_callable::type volatile type; +}; + +template class Wrapper, typename C> +struct result_of_wrap_callable { + typedef typename result_of_wrap_callable::type const volatile type; +}; -template class is_callable; template struct cpp0x_result_of_impl; -#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#else // BOOST_NO_SFINAE_EXPR template struct result_of_always_void { - typedef void type; + typedef void type; }; + template struct cpp0x_result_of_impl {}; -#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#endif // BOOST_NO_SFINAE_EXPR template struct result_of_void_impl From 7148d6c95ebe1492b49c9061bb2aa58e41d8a89d Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 23 Sep 2012 01:11:00 +0000 Subject: [PATCH 34/90] gcc-4.4 doesn't have robust enough support for sfinae-for-expressions [SVN r80654] --- .../utility/detail/result_of_iterate.hpp | 24 ++++----- include/boost/utility/result_of.hpp | 54 ++++++++++--------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 98063cd..f619ee7 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -56,37 +56,37 @@ struct result_of namespace detail { -#ifdef BOOST_NO_SFINAE_EXPR +#ifdef BOOST_RESULT_OF_NO_SFINAE_EXPR template -struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()); +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()); template -struct BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) { +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) { R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const; typedef result_of_private_type const &(*pfn_t)(...); operator pfn_t() const volatile; }; template -struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()); +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()); template -struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()) - : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) {}; template -struct BOOST_PP_CAT(result_of_is_callable_fun_, BOOST_PP_ITERATION()) - : BOOST_PP_CAT(result_of_is_callable_fun_2_, BOOST_PP_ITERATION()) +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) {}; template struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION()) : mpl::eval_if< is_class::type>, - result_of_wrap_callable, - mpl::identity::type> > + result_of_wrap_callable_class, + mpl::identity::type> > > {}; @@ -119,7 +119,7 @@ struct cpp0x_result_of_impl struct cpp0x_result_of_impl struct result_of; @@ -66,7 +70,7 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -#ifdef BOOST_NO_SFINAE_EXPR +#ifdef BOOST_RESULT_OF_NO_SFINAE_EXPR template T result_of_decay(T); @@ -75,13 +79,6 @@ struct result_of_private_type result_of_private_type const &operator,(int) const; }; -template -struct result_of_callable_class : C { - result_of_callable_class(); - typedef result_of_private_type const &(*pfn_t)(...); - operator pfn_t() const volatile; -}; - typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 @@ -90,34 +87,41 @@ result_of_no_type result_of_is_private_type(T const &); result_of_yes_type result_of_is_private_type(result_of_private_type const &); -template class Wrapper, typename C> -struct result_of_wrap_callable { - typedef Wrapper type; +template +struct result_of_callable_class : C { + result_of_callable_class(); + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; }; -template class Wrapper, typename C> -struct result_of_wrap_callable { - typedef typename result_of_wrap_callable::type &type; +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class type; }; -template class Wrapper, typename C> -struct result_of_wrap_callable { - typedef typename result_of_wrap_callable::type const type; +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const type; }; -template class Wrapper, typename C> -struct result_of_wrap_callable { - typedef typename result_of_wrap_callable::type volatile type; +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class volatile type; }; -template class Wrapper, typename C> -struct result_of_wrap_callable { - typedef typename result_of_wrap_callable::type const volatile type; +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const volatile type; +}; + +template +struct result_of_wrap_callable_class { + typedef typename result_of_wrap_callable_class::type &type; }; template struct cpp0x_result_of_impl; -#else // BOOST_NO_SFINAE_EXPR +#else // BOOST_RESULT_OF_NO_SFINAE_EXPR template struct result_of_always_void @@ -127,7 +131,7 @@ struct result_of_always_void template struct cpp0x_result_of_impl {}; -#endif // BOOST_NO_SFINAE_EXPR +#endif // BOOST_RESULT_OF_NO_SFINAE_EXPR template struct result_of_void_impl From 0568a114a8cc5247c2c042f01b0f41d69552549e Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sun, 23 Sep 2012 01:44:39 +0000 Subject: [PATCH 35/90] supress warnings in result_of_iterate.hpp on gcc 4 and up. [SVN r80655] --- include/boost/utility/detail/result_of_iterate.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index f619ee7..7dccf17 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -15,6 +15,12 @@ # error Boost result_of - do not include this file! #endif +// This header generate spurious warnings on gcc, which we supress by +// treating it as a system header. +#if defined(__GNUC__) && (__GNUC__ >= 4) +#pragma GCC system_header +#endif + // CWPro8 requires an argument in a function type specialization #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0 # define BOOST_RESULT_OF_ARGS void From 3d650b7f92fbb30d8e247d387cef44e130807ad3 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 23 Sep 2012 02:08:32 +0000 Subject: [PATCH 36/90] nicer work-around for gcc warnings [SVN r80656] --- .../boost/utility/detail/result_of_iterate.hpp | 8 +------- include/boost/utility/result_of.hpp | 15 ++++++++------- test/result_of_test.cpp | 12 ++++++++++++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 7dccf17..23aa650 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -15,12 +15,6 @@ # error Boost result_of - do not include this file! #endif -// This header generate spurious warnings on gcc, which we supress by -// treating it as a system header. -#if defined(__GNUC__) && (__GNUC__ >= 4) -#pragma GCC system_header -#endif - // CWPro8 requires an argument in a function type specialization #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0 # define BOOST_RESULT_OF_ARGS void @@ -101,7 +95,7 @@ struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) { typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())::type wrapper_t; static const bool value = ( sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type( - (boost::declval()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT)), 0) + (boost::declval()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT)), result_of_weird_type()) )) ); typedef mpl::bool_ type; diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index f6add2f..4695fa4 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -74,18 +74,19 @@ template struct tr1_result_of_im template T result_of_decay(T); -struct result_of_private_type -{ - result_of_private_type const &operator,(int) const; +struct result_of_private_type {}; + +struct result_of_weird_type { + template + friend result_of_weird_type operator,(T const &, result_of_weird_type); + friend result_of_private_type operator,(result_of_private_type, result_of_weird_type); }; typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 -template -result_of_no_type result_of_is_private_type(T const &); - -result_of_yes_type result_of_is_private_type(result_of_private_type const &); +result_of_no_type result_of_is_private_type(result_of_weird_type); +result_of_yes_type result_of_is_private_type(result_of_private_type); template struct result_of_callable_class : C { diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 0c2834f..61592f5 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -160,6 +160,10 @@ int main() typedef int (&func_ref)(float, double); typedef int (*func_ptr_0)(); typedef int (&func_ref_0)(); + typedef void (*func_ptr_void)(float, double); + typedef void (&func_ref_void)(float, double); + typedef void (*func_ptr_void_0)(); + typedef void (&func_ref_void_0)(); typedef int (X::*mem_func_ptr)(float); typedef int (X::*mem_func_ptr_c)(float) const; typedef int (X::*mem_func_ptr_v)(float) volatile; @@ -218,6 +222,10 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -228,6 +236,10 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); From 4a08e3d0bf22dd1f093a150d7fa842e10dc47b1c Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 26 Sep 2012 18:47:08 +0000 Subject: [PATCH 37/90] remove workaround for gcc-4.4, boost.config is correct now [SVN r80712] --- include/boost/utility/detail/result_of_iterate.hpp | 6 +++--- include/boost/utility/result_of.hpp | 12 +++--------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 23aa650..17fd4d5 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -56,7 +56,7 @@ struct result_of namespace detail { -#ifdef BOOST_RESULT_OF_NO_SFINAE_EXPR +#ifdef BOOST_NO_SFINAE_EXPR template struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()); @@ -119,7 +119,7 @@ struct cpp0x_result_of_impl struct cpp0x_result_of_impl struct result_of; @@ -70,9 +66,7 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -#ifdef BOOST_RESULT_OF_NO_SFINAE_EXPR - -template T result_of_decay(T); +#ifdef BOOST_NO_SFINAE_EXPR struct result_of_private_type {}; @@ -122,7 +116,7 @@ struct result_of_wrap_callable_class { template struct cpp0x_result_of_impl; -#else // BOOST_RESULT_OF_NO_SFINAE_EXPR +#else // BOOST_NO_SFINAE_EXPR template struct result_of_always_void @@ -132,7 +126,7 @@ struct result_of_always_void template struct cpp0x_result_of_impl {}; -#endif // BOOST_RESULT_OF_NO_SFINAE_EXPR +#endif // BOOST_NO_SFINAE_EXPR template struct result_of_void_impl From 93f6e3473b50de24df6631d3f18ff31ab8b13329 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 28 Sep 2012 08:47:35 +0000 Subject: [PATCH 38/90] friendlier wrt overloaded comma [SVN r80732] --- include/boost/utility/result_of.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 72d9ff2..f0e084a 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -71,15 +71,14 @@ template struct tr1_result_of_im struct result_of_private_type {}; struct result_of_weird_type { - template - friend result_of_weird_type operator,(T const &, result_of_weird_type); friend result_of_private_type operator,(result_of_private_type, result_of_weird_type); }; typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 -result_of_no_type result_of_is_private_type(result_of_weird_type); +template +result_of_no_type result_of_is_private_type(T const &); result_of_yes_type result_of_is_private_type(result_of_private_type); template From 3cca2755cf10e61bdf5339c8f592623cc74c42f1 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 3 Oct 2012 23:08:44 +0000 Subject: [PATCH 39/90] add missing close tag [SVN r80834] --- utility.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility.htm b/utility.htm index c46c515..94920c3 100644 --- a/utility.htm +++ b/utility.htm @@ -168,7 +168,7 @@ void f() { TN)>::type
names the type decltype(boost::declval<F>()(boost::declval<T1>(), boost::declval<T2>(), ..., - boost::declval<TN>())), as in the + boost::declval<TN>())), as in the following example.

From 943af35553467440f94be135de5e9e0370eba14c Mon Sep 17 00:00:00 2001 From: Michel Morin Date: Tue, 30 Oct 2012 16:51:16 +0000 Subject: [PATCH 40/90] Tweak comments (removing a non-ascii character, updating references to the C++11 standard, etc.) and rename the include guard macro. [SVN r81112] --- include/boost/utility/declval.hpp | 41 ++++++++++++++----------------- 1 file changed, 18 insertions(+), 23 deletions(-) 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 From c55d5ca7de0f86bec6771b9422a45ebfddfd3fac Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 26 Nov 2012 20:32:24 +0000 Subject: [PATCH 41/90] Removed usage of deprecated macros in Boost.Utility; specifically result_of [SVN r81574] --- include/boost/utility/result_of.hpp | 2 +- test/result_of_test.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index f0e084a..4a20254 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -46,7 +46,7 @@ #ifndef BOOST_RESULT_OF_USE_TR1 # ifndef BOOST_RESULT_OF_USE_DECLTYPE -# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_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 diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 61592f5..d06ec64 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -104,7 +104,7 @@ struct no_result_type_or_result cv_overload_check operator()() const; cv_overload_check operator()() volatile; cv_overload_check operator()() const volatile; -#if !defined(BOOST_NO_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); long operator()(int const&); @@ -122,7 +122,7 @@ struct no_result_type_or_result_template cv_overload_check operator()() const; cv_overload_check operator()() volatile; cv_overload_check operator()() const volatile; -#if !defined(BOOST_NO_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) short operator()(int&&); int operator()(int&); long operator()(int const&); @@ -291,7 +291,7 @@ int main() BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); -#if !defined(BOOST_NO_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) BOOST_STATIC_ASSERT((is_same::type, short>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, long>::value)); From dc8ffe92b861d4de84788a9f914f5f2bea99eb40 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sat, 8 Dec 2012 18:37:29 +0000 Subject: [PATCH 42/90] Removed use of deprecated macros [SVN r81801] --- include/boost/utility/base_from_member.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp index 67faa3b..e32ecb8 100644 --- a/include/boost/utility/base_from_member.hpp +++ b/include/boost/utility/base_from_member.hpp @@ -96,7 +96,7 @@ struct is_related // Contributed by Daryle Walker, based on a work-around by Luc Danton -#ifndef BOOST_NO_VARIADIC_TEMPLATES +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES template struct enable_if_unrelated : public ::boost::enable_if_c @@ -126,9 +126,9 @@ class base_from_member protected: MemberType member; -#if !defined(BOOST_NO_RVALUE_REFERENCES) && \ - !defined(BOOST_NO_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \ +#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> From 98d793152cc1d0c75d5800050376ce52245bc91c Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sat, 15 Dec 2012 16:38:07 +0000 Subject: [PATCH 43/90] Move string_ref to Boost.Utility; first crack at docs [SVN r81972] --- doc/Jamfile.v2 | 23 +- doc/string_ref.qbk | 100 +++++++ include/boost/utility/string_ref.hpp | 386 +++++++++++++++++++++++++++ index.html | 1 + test/Jamfile.v2 | 2 + test/string_ref_test1.cpp | 111 ++++++++ test/string_ref_test2.cpp | 256 ++++++++++++++++++ 7 files changed, 875 insertions(+), 4 deletions(-) create mode 100644 doc/string_ref.qbk create mode 100644 include/boost/utility/string_ref.hpp create mode 100644 test/string_ref_test1.cpp create mode 100644 test/string_ref_test2.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index b12d71a..10b7c7e 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -62,7 +62,22 @@ boostbook standalone ; - - - - +xml string_ref : string_ref.qbk ; +boostbook standalone + : + string_ref + : + # File name of HTML output: + root.filename=string_ref + # 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/string_ref.qbk b/doc/string_ref.qbk new file mode 100644 index 0000000..0242096 --- /dev/null +++ b/doc/string_ref.qbk @@ -0,0 +1,100 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / + / 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 String_Ref + [quickbook 1.5] + [authors [Clow, Marshall]] + [copyright 2012 Marshall Clow] + [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.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442: +string_ref: a non-owning reference to a string]. + +When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks: + +1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data. + +2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring. + +3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return. + +`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to. + +A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy. + +`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work) + +Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. + +Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does. + +[endsect] + + +[/===============] +[section Examples] +[/===============] + +Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`. + + std::string extract_part ( const std::string &bar ) { + return bar.substr ( 2, 3 ); + } + + if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } + +Let's figure out what happens in this (contrived) example. + +First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well. + +Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data. + +Now let's look at the same code with `string_ref`: + + boost::string_ref extract_part ( boost::string_ref bar ) { + return bar.substr ( 2, 3 ); + } + + if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } + +No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations. + +[endsect] + + +[/=================] +[section:reference Reference ] +[/=================] + +The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` . + +`#include ` + +[endsect] + +[/===============] +[section History] +[/===============] + +[heading boost 1.53] +* Introduced + + +[endsect] + + + + diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp new file mode 100644 index 0000000..d333628 --- /dev/null +++ b/include/boost/utility/string_ref.hpp @@ -0,0 +1,386 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + +*/ + +#ifndef BOOST_STRING_REF_HPP +#define BOOST_STRING_REF_HPP + +#include +#include + +#include +#include +#include +#include + +namespace boost { + + namespace detail { + // A helper functor because sometimes we don't have lambdas + template + class string_ref_traits_eq { + public: + string_ref_traits_eq ( charT ch ) : ch_(ch) {} + bool operator () ( charT val ) const { return traits::eq ( ch_, val ); } + charT ch_; + }; + } + + template class basic_string_ref; + typedef basic_string_ref > string_ref; + typedef basic_string_ref > wstring_ref; + +#ifndef BOOST_NO_CXX11_CHAR16_T + typedef basic_string_ref > u16string_ref; +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + typedef basic_string_ref > u32string_ref; +#endif + + template + class basic_string_ref { + public: + // types + typedef charT value_type; + typedef const charT* pointer; + typedef const charT& reference; + typedef const charT& const_reference; + typedef pointer const_iterator; // impl-defined + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); + + // construct/copy + BOOST_CONSTEXPR basic_string_ref () + : ptr_(NULL), len_(0) {} + + BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) + : ptr_(rhs.ptr_), len_(rhs.len_) {} + + basic_string_ref& operator=(const basic_string_ref &rhs) { + ptr_ = rhs.ptr_; + len_ = rhs.len_; + return *this; + } + + basic_string_ref(const charT* str) + : ptr_(str), len_(traits::length(str)) {} + + template + basic_string_ref(const std::basic_string& str) + : ptr_(str.data()), len_(str.length()) {} + + BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) + : ptr_(str), len_(len) {} + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + template + explicit operator std::basic_string() const { + return std::basic_string ( ptr_, len_ ); + } +#endif + + // iterators + BOOST_CONSTEXPR const_iterator begin() const { return ptr_; } + BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; } + BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; } + BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; } + const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); } + const_reverse_iterator rend() const { return const_reverse_iterator (begin()); } + const_reverse_iterator crend() const { return const_reverse_iterator (begin()); } + + // capacity + BOOST_CONSTEXPR size_type size() const { return len_; } + BOOST_CONSTEXPR size_type length() const { return len_; } + BOOST_CONSTEXPR size_type max_size() const { return len_; } + BOOST_CONSTEXPR bool empty() const { return len_ == 0; } + + // element access + BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; } + + const charT& at(size_t pos) const { + if ( pos >= len_ ) + throw std::out_of_range ( "boost::string_ref::at" ); + return ptr_[pos]; + } + + BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; } + BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; } + BOOST_CONSTEXPR const charT* data() const { return ptr_; } + + // modifiers + void clear() { len_ = 0; } + void remove_prefix(size_type n) { + if ( n > len_ ) + n = len_; + ptr_ += n; + len_ -= n; + } + + void remove_suffix(size_type n) { + if ( n > len_ ) + n = len_; + len_ -= n; + } + + + // basic_string_ref string operations + BOOST_CONSTEXPR + basic_string_ref substr(size_type pos, size_type n=npos) const { +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600) + // Looks like msvc 8 and 9 have a codegen bug when one branch of + // a conditional operator is a throw expression. -EAN 2012/12/04 + if ( pos > size()) throw std::out_of_range ( "string_ref::substr" ); + if ( n == npos || pos + n > size()) n = size () - pos; + return basic_string_ref ( data() + pos, n ); +#else + return pos > size() ? throw std::out_of_range ( "string_ref::substr" ) : + basic_string_ref ( data() + pos, n == npos || pos + n > size() ? size() - pos : n ); +#endif + } + + int compare(basic_string_ref x) const { + int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_)); + return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 ); + } + + bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); } + bool starts_with(basic_string_ref x) const { + return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0; + } + + bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); } + bool ends_with(basic_string_ref x) const { + return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0; + } + + size_type find(basic_string_ref s) const { + const_iterator iter = std::search ( this->cbegin (), this->cend (), + s.cbegin (), s.cend (), traits::eq ); + return iter = this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find(charT c) const { + const_iterator iter = std::find_if ( this->cbegin (), this->cend (), + detail::string_ref_traits_eq ( c )); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type rfind(basic_string_ref s) const { + const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (), + s.crbegin (), s.crend (), traits::eq ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); + } + + size_type rfind(charT c) const { + const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (), + detail::string_ref_traits_eq ( c )); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); + } + + size_type find_first_of(charT c) const { return find (c); } + size_type find_last_of (charT c) const { return rfind (c); } + + size_type find_first_of(basic_string_ref s) const { + const_iterator iter = std::find_first_of + ( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find_last_of(basic_string_ref s) const { + const_reverse_iterator iter = std::find_first_of + ( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter); + } + + size_type find_first_not_of(basic_string_ref s) const { + const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find_first_not_of(charT c) const { + for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter ) + if ( !traits::eq ( c, *iter )) + return std::distance ( this->cbegin (), iter ); + return npos; + } + + size_type find_last_not_of(basic_string_ref s) const { + const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); + } + + size_type find_last_not_of(charT c) const { + for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter ) + if ( !traits::eq ( c, *iter )) + return reverse_distance ( this->crbegin (), iter ); + return npos; + } + + private: + template + size_type reverse_distance ( r_iter first, r_iter last ) const { + return len_ - 1 - std::distance ( first, last ); + } + + template + Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const { + for ( ; first != last ; ++first ) + if ( 0 == traits::find ( s.ptr_, s.len_, *first )) + return first; + return last; + } + + + + const charT *ptr_; + std::size_t len_; + }; + + // Comparison operators + template + bool operator==(basic_string_ref x, basic_string_ref y) { + if ( x.size () != y.size ()) return false; + return x.compare(y) == 0; + } + + template + bool operator!=(basic_string_ref x, basic_string_ref y) { + if ( x.size () != y.size ()) return true; + return x.compare(y) != 0; + } + + template + bool operator<(basic_string_ref x, basic_string_ref y) { + return x.compare(y) < 0; + } + + template + bool operator>(basic_string_ref x, basic_string_ref y) { + return x.compare(y) > 0; + } + + template + bool operator<=(basic_string_ref x, basic_string_ref y) { + return x.compare(y) <= 0; + } + + template + bool operator>=(basic_string_ref x, basic_string_ref y) { + return x.compare(y) >= 0; + } + + + // Inserter + template + std::basic_ostream& + operator<<(std::basic_ostream& os, const basic_string_ref& str) { +#ifdef BOOST_NO_CXX11_RANGE_BASED_FOR + for ( typename basic_string_ref::const_iterator iter = str.begin (); iter != str.end (); ++iter ) + os << *iter; +#else + for ( charT x : str ) + os << x; +#endif + return os; + } + +#if 0 + // numeric conversions + // + // These are short-term implementations. + // In a production environment, I would rather avoid the copying. + // + int stoi (string_ref str, size_t* idx=0, int base=10) { + return std::stoi ( std::string(str), idx, base ); + } + + long stol (string_ref str, size_t* idx=0, int base=10) { + return std::stol ( std::string(str), idx, base ); + } + + unsigned long stoul (string_ref str, size_t* idx=0, int base=10) { + return std::stoul ( std::string(str), idx, base ); + } + + long long stoll (string_ref str, size_t* idx=0, int base=10) { + return std::stoll ( std::string(str), idx, base ); + } + + unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) { + return std::stoull ( std::string(str), idx, base ); + } + + float stof (string_ref str, size_t* idx=0) { + return std::stof ( std::string(str), idx ); + } + + double stod (string_ref str, size_t* idx=0) { + return std::stod ( std::string(str), idx ); + } + + long double stold (string_ref str, size_t* idx=0) { + return std::stold ( std::string(str), idx ); + } + + int stoi (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoi ( std::wstring(str), idx, base ); + } + + long stol (wstring_ref str, size_t* idx=0, int base=10) { + return std::stol ( std::wstring(str), idx, base ); + } + + unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoul ( std::wstring(str), idx, base ); + } + + long long stoll (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoll ( std::wstring(str), idx, base ); + } + + unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoull ( std::wstring(str), idx, base ); + } + + float stof (wstring_ref str, size_t* idx=0) { + return std::stof ( std::wstring(str), idx ); + } + + double stod (wstring_ref str, size_t* idx=0) { + return std::stod ( std::wstring(str), idx ); + } + + long double stold (wstring_ref str, size_t* idx=0) { + return std::stold ( std::wstring(str), idx ); + } +#endif + +} + +#if 0 +namespace std { + // Hashing + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; +} +#endif + +#endif diff --git a/index.html b/index.html index d384487..d5b4884 100644 --- a/index.html +++ b/index.html @@ -34,6 +34,7 @@ swap
throw_exception
utility
+ string_ref
value_init

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d3fc34c..4b2d6e0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -31,6 +31,8 @@ test-suite utility [ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/static ] [ compile result_of_test.cpp ] [ run ../shared_iterator_test.cpp ] + [ run string_ref_test1.cpp ] + [ run string_ref_test2.cpp ] [ run ../value_init_test.cpp ] [ run ../value_init_workaround_test.cpp ] [ run ../initialized_test.cpp ] diff --git a/test/string_ref_test1.cpp b/test/string_ref_test1.cpp new file mode 100644 index 0000000..32ff801 --- /dev/null +++ b/test/string_ref_test1.cpp @@ -0,0 +1,111 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include + +#include + + +#include + +typedef boost::string_ref string_ref; + +// Should be equal +void interop ( const std::string &str, string_ref ref ) { +// BOOST_CHECK ( str == ref ); + BOOST_CHECK ( str.size () == ref.size ()); + BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ())); + BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ())); + } + +void null_tests ( const char *p ) { +// All zero-length string-refs should be equal + string_ref sr1; // NULL, 0 + string_ref sr2 ( NULL, 0 ); + string_ref sr3 ( p, 0 ); + string_ref sr4 ( p ); + sr4.clear (); + + BOOST_CHECK ( sr1 == sr2 ); + BOOST_CHECK ( sr1 == sr3 ); + BOOST_CHECK ( sr2 == sr3 ); + BOOST_CHECK ( sr1 == sr4 ); + } + +// make sure that substrings work just like strings +void test_substr ( const std::string &str ) { + const size_t sz = str.size (); + string_ref ref ( str ); + +// Substrings at the end + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( i ), ref.substr ( i )); + +// Substrings at the beginning + for ( size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( 0, i ), ref.substr ( 0, i )); + +// All possible substrings + for ( size_t i = 0; i < sz; ++i ) + for ( size_t j = i; j < sz; ++j ) + interop ( str.substr ( i, j ), ref.substr ( i, j )); + } + +// make sure that removing prefixes and suffixes work just like strings +void test_remove ( const std::string &str ) { + const size_t sz = str.size (); + std::string work; + string_ref ref; + + for ( size_t i = 1; i <= sz; ++i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( 0, i ); + ref.remove_prefix (i); + } + } + + for ( size_t i = 1; i < sz; ++ i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( work.size () - i, i ); + ref.remove_suffix (i); + } + } + } + +const char *test_strings [] = { + "", + "1", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + NULL + }; + +int test_main( int , char* [] ) { + + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + interop ( *p, *p ); + test_substr ( *p ); + test_remove ( *p ); + null_tests ( *p ); + + p++; + } + + return 0; + } diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp new file mode 100644 index 0000000..dbd5bf9 --- /dev/null +++ b/test/string_ref_test2.cpp @@ -0,0 +1,256 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include // for std::strchr + +#include + +#include + +typedef boost::string_ref string_ref; + +void ends_with ( const char *arg ) { + const size_t sz = strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + const char *p = arg; + + while ( !*p ) { + BOOST_CHECK ( sr.ends_with ( p )); + ++p; + } + + while ( !sr2.empty ()) { + BOOST_CHECK ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + sr2 = arg; + while ( !sr2.empty ()) { + BOOST_CHECK ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + char ch = sz == 0 ? '\0' : arg [ sz - 1 ]; + sr2 = arg; + if ( sz > 0 ) + BOOST_CHECK ( sr2.ends_with ( ch )); + BOOST_CHECK ( !sr2.ends_with ( ++ch )); + BOOST_CHECK ( sr2.ends_with ( string_ref ())); + } + +void starts_with ( const char *arg ) { + const size_t sz = strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + const char *p = arg + std::strlen ( arg ) - 1; + while ( p >= arg ) { + std::string foo ( arg, p + 1 ); + BOOST_CHECK ( sr.starts_with ( foo )); + --p; + } + + while ( !sr2.empty ()) { + BOOST_CHECK ( sr.starts_with ( sr2 )); + sr2.remove_suffix (1); + } + + char ch = *arg; + sr2 = arg; + if ( sz > 0 ) + BOOST_CHECK ( sr2.starts_with ( ch )); + BOOST_CHECK ( !sr2.starts_with ( ++ch )); + BOOST_CHECK ( sr2.starts_with ( string_ref ())); + } + +void reverse ( const char *arg ) { +// Round trip + string_ref sr1 ( arg ); + std::string string1 ( sr1.rbegin (), sr1.rend ()); + string_ref sr2 ( string1 ); + std::string string2 ( sr2.rbegin (), sr2.rend ()); + + BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); + BOOST_CHECK ( string2 == arg ); + BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ())); + } + +// This helper function eliminates signed vs. unsigned warnings +string_ref::size_type ptr_diff ( const char *res, const char *base ) { + BOOST_CHECK ( res >= base ); + return static_cast ( res - base ); + } + +void find ( const char *arg ) { + string_ref sr1; + string_ref sr2; + const char *p; + +// Look for each character in the string(searching from the start) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.find(*p); + BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg ))); + ++p; + } + +// Look for each character in the string (searching from the end) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); + ++p; + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.find(ch); + const char *strp = std::strchr ( arg, ch ); + BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_CHECK ( ptr_diff ( strp, arg ) == pos ); + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.rfind(ch); + const char *strp = std::strrchr ( arg, ch ); + BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_CHECK ( ptr_diff ( strp, arg ) == pos ); + } + + +// Find everything at the start + p = arg; + sr1 = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find(*p); + BOOST_CHECK ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + +// Find everything at the end + sr1 = arg; + p = arg + strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_CHECK ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Find everything at the start + sr1 = arg; + p = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_first_of(*p); + BOOST_CHECK ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + + +// Find everything at the end + sr1 = arg; + p = arg + strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_last_of(*p); + BOOST_CHECK ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Basic sanity checking for "find_first_of / find_first_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 ); + BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_prefix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_first_of(*p); + string_ref::size_type pos2 = sr1.find_first_not_of(*p); + BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); + if ( pos2 != string_ref::npos ) { + for ( size_t i = 0 ; i < pos2; ++i ) + BOOST_CHECK ( sr1[i] == *p ); + BOOST_CHECK ( sr1 [ pos2 ] != *p ); + } + + BOOST_CHECK ( pos2 != pos1 ); + ++p; + } + +// Basic sanity checking for "find_last_of / find_last_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); + BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_suffix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_last_of(*p); + string_ref::size_type pos2 = sr1.find_last_not_of(*p); + BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); + BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ()); + if ( pos2 != string_ref::npos ) { + for ( size_t i = sr1.size () -1 ; i > pos2; --i ) + BOOST_CHECK ( sr1[i] == *p ); + BOOST_CHECK ( sr1 [ pos2 ] != *p ); + } + + BOOST_CHECK ( pos2 != pos1 ); + ++p; + } + + } + +const char *test_strings [] = { + "", + "0", + "abc", + "AAA", // all the same + "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", + "abc\0asdfadsfasf", + NULL + }; + +int test_main( int , char* [] ) { + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + starts_with ( *p ); + ends_with ( *p ); + reverse ( *p ); + find ( *p ); + + p++; + } + + return 0; + } From 71205b6e8434942b3375edc9c99b4526cc0d2c46 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 14 Jan 2013 16:25:56 +0000 Subject: [PATCH 44/90] Updated the string_ref docs with a reference section; committed the generated HTML [SVN r82489] --- doc/Jamfile.v2 | 6 +- doc/html/string_ref.html | 280 +++++++++++++++++++++++++++++++++++++++ doc/string_ref.qbk | 93 +++++++++++-- 3 files changed, 363 insertions(+), 16 deletions(-) create mode 100644 doc/html/string_ref.html diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 10b7c7e..a0ff034 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -43,7 +43,7 @@ using quickbook ; path-constant boost-images : ../../../doc/src/images ; xml declval : declval.qbk ; -boostbook standalone +boostbook standalone_declval : declval : @@ -63,7 +63,7 @@ boostbook standalone ; xml string_ref : string_ref.qbk ; -boostbook standalone +boostbook standalone_string_ref : string_ref : @@ -79,5 +79,5 @@ boostbook standalone toc.max.depth=1 # How far down we go with TOC's generate.section.toc.level=1 - + ; diff --git a/doc/html/string_ref.html b/doc/html/string_ref.html new file mode 100644 index 0000000..0b8a9d1 --- /dev/null +++ b/doc/html/string_ref.html @@ -0,0 +1,280 @@ + + + +String_Ref + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+
+
+
+

+String_Ref

+

+Marshall Clow +

+
+
+

+ 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) +

+
+
+
+
+
+

Table of Contents

+
+
Overview
+
Examples
+
Reference
+
History
+
+
+
+ +

+ Boost.StringRef is an implementation of Jeffrey Yaskin's N3442: + string_ref: a non-owning reference to a string. +

+

+ When you are parsing/processing strings from some external source, frequently + you want to pass a piece of text to a procedure for specialized processing. + The canonical way to do this is as a std::string, + but that has certain drawbacks: +

+

+ 1) If you are processing a buffer of text (say a HTTP response or the contents + of a file), then you have to create the string from the text you want to pass, + which involves memory allocation and copying of data. +

+

+ 2) if a routine receives a constant std::string + and wants to pass a portion of that string to another routine, then it must + create a new string of that substring. +

+

+ 3) A routine receives a constant std::string + and wants to return a portion of the string, then it must create a new string + to return. +

+

+ string_ref is designed to solve + these efficiency problems. A string_ref + is a read-only reference to a contiguous sequence of characters, and provides + much of the functionality of std::string. + A string_ref is cheap to create, + copy and pass by value, because it does not actually own the storage that it + points to. +

+

+ A string_ref is implemented + as a small struct that contains a pointer to the start of the character data + and a count. A string_ref is + cheap to create and cheap to copy. +

+

+ string_ref acts as a container; + it includes all the methods that you would expect in a container, including + iteration support, operator [], + at and size. + It can be used with any of the iterator-based algorithms in the STL - as long + as you don't need to change the underlying data (sort + and remove, for example, will + not work) +

+

+ Besides generic container functionality, string_ref + provides a subset of the interface of std::string. + This makes it easy to replace parameters of type const + std::string & + with boost::string_ref. Like std::string, + string_ref has a static member + variable named npos to denote + the result of failed searches, and to mean "the end". +

+

+ Because a string_ref does not + own the data that it "points to", it introduces lifetime issues into + code that uses it. The programmer must ensure that the data that a string_ref refers to exists as long as the + string_ref does. +

+
+
+ +

+ Integrating string_ref into + your code is fairly simple. Wherever you pass a const + std::string & + or std::string as a parameter, that's a candidate + for passing a boost::string_ref. +

+
std::string extract_part ( const std::string &bar ) {
+    return bar.substr ( 2, 3 );
+    }
+
+if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
+
+

+ Let's figure out what happens in this (contrived) example. +

+

+ First, a temporary string is created from the string literal "ABCDEFG", and it is passed (by reference) + to the routine extract_part. + Then a second string is created in the call std::string::substr + and returned to extract_part + (this copy may be elided by RVO). Then extract_part + returns that string back to the caller (again this copy may be elided). The + first temporary string is deallocated, and front + is called on the second string, and then it is deallocated as well. +

+

+ Two std::strings are created, and two copy operations. + That's (potentially) four memory allocations and deallocations, and the associated + copying of data. +

+

+ Now let's look at the same code with string_ref: +

+
boost::string_ref extract_part ( boost::string_ref bar ) {
+    return bar.substr ( 2, 3 );
+    }
+
+if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
+
+

+ No memory allocations. No copying of character data. No changes to the code + other than the types. There are two string_refs + created, and two string_refs + copied, but those are cheap operations. +

+
+
+ +

+ The header file "string_ref.hpp" defines a template boost::basic_string_ref, + and four specializations - for char + / wchar_t / char16_t + / char32_t . +

+

+ #include <boost/utility/string_ref.hpp> +

+

+ Construction and copying: +

+
BOOST_CONSTEXPR basic_string_ref ();    // Constructs an empty string_ref
+BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
+BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
+template<typename Allocator>
+basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
+basic_string_ref (const basic_string_ref &rhs);
+basic_string_ref& operator=(const basic_string_ref &rhs);
+
+

+ string_ref does not define + a move constructor nor a move-assignment operator because copying a string_ref is just a cheap as moving one. +

+

+ Basic container-like functions: +

+
BOOST_CONSTEXPR size_type size()     const ;
+BOOST_CONSTEXPR size_type length()   const ;
+BOOST_CONSTEXPR size_type max_size() const ;
+BOOST_CONSTEXPR bool empty()         const ;
+
+// All iterators are const_iterators
+BOOST_CONSTEXPR const_iterator  begin() const ;
+BOOST_CONSTEXPR const_iterator cbegin() const ;
+BOOST_CONSTEXPR const_iterator    end() const ;
+BOOST_CONSTEXPR const_iterator   cend() const ;
+const_reverse_iterator         rbegin() const ;
+const_reverse_iterator        crbegin() const ;
+const_reverse_iterator           rend() const ;
+const_reverse_iterator          crend() const ;
+
+

+ Access to the individual elements (all of which are const): +

+
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
+const charT& at(size_t pos) const ;
+BOOST_CONSTEXPR const charT& front() const ;
+BOOST_CONSTEXPR const charT& back()  const ;
+BOOST_CONSTEXPR const charT* data()  const ;
+
+

+ Modifying the string_ref (but + not the underlying data): +

+
void clear();
+void remove_prefix(size_type n);
+void remove_suffix(size_type n);
+
+

+ Searching: +

+
size_type find(basic_string_ref s) const ;
+size_type find(charT c) const ;
+size_type rfind(basic_string_ref s) const ;
+size_type rfind(charT c) const ;
+size_type find_first_of(charT c) const ;
+size_type find_last_of (charT c) const ;
+
+size_type find_first_of(basic_string_ref s) const ;
+size_type find_last_of(basic_string_ref s) const ;
+size_type find_first_not_of(basic_string_ref s) const ;
+size_type find_first_not_of(charT c) const ;
+size_type find_last_not_of(basic_string_ref s) const ;
+size_type find_last_not_of(charT c) const ;
+
+

+ String-like operations: +

+
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
+bool starts_with(charT c) const ;
+bool starts_with(basic_string_ref x) const ;
+bool ends_with(charT c) const ;
+bool ends_with(basic_string_ref x) const ;
+
+
+
+ +

+ + boost + 1.53 +

+
  • + Introduced +
+
+
+ + + +

Last revised: January 14, 2013 at 16:24:14 GMT

+
+
+ + diff --git a/doc/string_ref.qbk b/doc/string_ref.qbk index 0242096..5943eed 100644 --- a/doc/string_ref.qbk +++ b/doc/string_ref.qbk @@ -37,7 +37,7 @@ A `string_ref` is implemented as a small struct that contains a pointer to the s `string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work) -Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. +Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end". Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does. @@ -50,12 +50,12 @@ Because a `string_ref` does not own the data that it "points to", it introduces Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`. - std::string extract_part ( const std::string &bar ) { - return bar.substr ( 2, 3 ); - } - - if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } - + std::string extract_part ( const std::string &bar ) { + return bar.substr ( 2, 3 ); + } + + if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } + Let's figure out what happens in this (contrived) example. First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well. @@ -64,11 +64,11 @@ Two `std::string`s are created, and two copy operations. That's (potentially) fo Now let's look at the same code with `string_ref`: - boost::string_ref extract_part ( boost::string_ref bar ) { - return bar.substr ( 2, 3 ); - } - - if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } + boost::string_ref extract_part ( boost::string_ref bar ) { + return bar.substr ( 2, 3 ); + } + + if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations. @@ -83,6 +83,73 @@ The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, a `#include ` +Construction and copying: + + BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref + BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string + BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair + template + basic_string_ref(const std::basic_string& str); // Constructs from a std::string + basic_string_ref (const basic_string_ref &rhs); + basic_string_ref& operator=(const basic_string_ref &rhs); + +`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one. + +Basic container-like functions: + + BOOST_CONSTEXPR size_type size() const ; + BOOST_CONSTEXPR size_type length() const ; + BOOST_CONSTEXPR size_type max_size() const ; + BOOST_CONSTEXPR bool empty() const ; + + // All iterators are const_iterators + BOOST_CONSTEXPR const_iterator begin() const ; + BOOST_CONSTEXPR const_iterator cbegin() const ; + BOOST_CONSTEXPR const_iterator end() const ; + BOOST_CONSTEXPR const_iterator cend() const ; + const_reverse_iterator rbegin() const ; + const_reverse_iterator crbegin() const ; + const_reverse_iterator rend() const ; + const_reverse_iterator crend() const ; + +Access to the individual elements (all of which are const): + + BOOST_CONSTEXPR const charT& operator[](size_type pos) const ; + const charT& at(size_t pos) const ; + BOOST_CONSTEXPR const charT& front() const ; + BOOST_CONSTEXPR const charT& back() const ; + BOOST_CONSTEXPR const charT* data() const ; + +Modifying the `string_ref` (but not the underlying data): + + void clear(); + void remove_prefix(size_type n); + void remove_suffix(size_type n); + +Searching: + + size_type find(basic_string_ref s) const ; + size_type find(charT c) const ; + size_type rfind(basic_string_ref s) const ; + size_type rfind(charT c) const ; + size_type find_first_of(charT c) const ; + size_type find_last_of (charT c) const ; + + size_type find_first_of(basic_string_ref s) const ; + size_type find_last_of(basic_string_ref s) const ; + size_type find_first_not_of(basic_string_ref s) const ; + size_type find_first_not_of(charT c) const ; + size_type find_last_not_of(basic_string_ref s) const ; + size_type find_last_not_of(charT c) const ; + +String-like operations: + + BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref + bool starts_with(charT c) const ; + bool starts_with(basic_string_ref x) const ; + bool ends_with(charT c) const ; + bool ends_with(basic_string_ref x) const ; + [endsect] [/===============] @@ -91,7 +158,7 @@ The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, a [heading boost 1.53] * Introduced - + [endsect] From f0c62e9e002300f3552f2bd1ec6fbaa937fdb2c0 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 4 Feb 2013 14:14:42 +0000 Subject: [PATCH 45/90] Fix typo in docs; Refs #7974 [SVN r82729] --- in_place_factories.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/in_place_factories.html b/in_place_factories.html index f8a4c7b..8eb7ea8 100644 --- a/in_place_factories.html +++ b/in_place_factories.html @@ -46,7 +46,7 @@ HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_pla

Suppose we have a class

struct X
 {
-  X ( int, std:::string ) ;
+  X ( int, std::string ) ;
 } ;

And a container for it which supports an empty state (that is, which can contain zero objects):

struct C

From 00d151828c0920ce6ce112d59f8b37b66f19ab31 Mon Sep 17 00:00:00 2001
From: Marshall Clow 
Date: Thu, 7 Feb 2013 14:14:53 +0000
Subject: [PATCH 46/90] Fixed typo; Refs #8002

[SVN r82771]
---
 doc/string_ref.qbk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/string_ref.qbk b/doc/string_ref.qbk
index 5943eed..4c6fc79 100644
--- a/doc/string_ref.qbk
+++ b/doc/string_ref.qbk
@@ -54,7 +54,7 @@ Integrating `string_ref` into your code is fairly simple. Wherever you pass a `c
         return bar.substr ( 2, 3 );
         }
         
-    if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
+    if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
     
 Let's figure out what happens in this (contrived) example.
 

From 05af0deaed0706b67459b33e29e452f93ad233d4 Mon Sep 17 00:00:00 2001
From: Marshall Clow 
Date: Mon, 11 Feb 2013 21:49:56 +0000
Subject: [PATCH 47/90] Update Boost.StringRef tests to use newer Boost.Test
 features

[SVN r82825]
---
 test/Jamfile.v2           |  9 +++++++--
 test/string_ref_test1.cpp | 12 +++++-------
 test/string_ref_test2.cpp | 10 +++++-----
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 4b2d6e0..d597cb8 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -8,6 +8,11 @@
 # bring in rules for testing
 import testing ;
 
+alias unit_test_framework
+    : # sources
+        /boost//unit_test_framework
+    ;        
+
 # Please keep the tests ordered by filename
 test-suite utility
     :
@@ -31,8 +36,8 @@ test-suite utility
         [ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/static ]
         [ compile result_of_test.cpp ]
         [ run ../shared_iterator_test.cpp ]
-        [ run string_ref_test1.cpp ]
-        [ run string_ref_test2.cpp ]
+        [ run string_ref_test1.cpp unit_test_framework ]
+        [ run string_ref_test2.cpp unit_test_framework ]
         [ run ../value_init_test.cpp ]
         [ run ../value_init_workaround_test.cpp ]
         [ run ../initialized_test.cpp ]
diff --git a/test/string_ref_test1.cpp b/test/string_ref_test1.cpp
index 32ff801..7524536 100644
--- a/test/string_ref_test1.cpp
+++ b/test/string_ref_test1.cpp
@@ -13,8 +13,8 @@
 
 #include 
 
-
-#include 
+#define BOOST_TEST_MAIN
+#include 
 
 typedef boost::string_ref string_ref;
 
@@ -94,8 +94,8 @@ const char *test_strings [] = {
     NULL
     };
     
-int test_main( int , char* [] ) {
-
+BOOST_AUTO_TEST_CASE( test_main )
+{
     const char **p = &test_strings[0];
 
     while ( *p != NULL ) {
@@ -106,6 +106,4 @@ int test_main( int , char* [] ) {
     
         p++;
         }
-
-    return 0;
-    }
+}
diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
index dbd5bf9..67733ee 100644
--- a/test/string_ref_test2.cpp
+++ b/test/string_ref_test2.cpp
@@ -12,7 +12,8 @@
 
 #include 
 
-#include 
+#define BOOST_TEST_MAIN
+#include 
 
 typedef boost::string_ref string_ref;
 
@@ -240,7 +241,8 @@ const char *test_strings [] = {
     NULL
     };
     
-int test_main( int , char* [] ) {
+BOOST_AUTO_TEST_CASE( test_main )
+{
     const char **p = &test_strings[0];
     
     while ( *p != NULL ) {
@@ -251,6 +253,4 @@ int test_main( int , char* [] ) {
 
         p++;
         }
-
-    return 0;
-    }
+}

From e4d622019f3188564ead405eb834a7a89c3bb0da Mon Sep 17 00:00:00 2001
From: Marshall Clow 
Date: Fri, 15 Feb 2013 16:07:06 +0000
Subject: [PATCH 48/90] Fixed bug in string_ref::find; Refs #8067

[SVN r82901]
---
 include/boost/utility/string_ref.hpp |  6 +-
 test/string_ref_test2.cpp            | 86 ++++++++++++++++++++++++----
 2 files changed, 77 insertions(+), 15 deletions(-)

diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp
index d333628..1be2ac9 100644
--- a/include/boost/utility/string_ref.hpp
+++ b/include/boost/utility/string_ref.hpp
@@ -155,7 +155,7 @@ namespace boost {
             }
         
         int compare(basic_string_ref x) const {
-            int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
+            const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
             return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
             }
         
@@ -172,7 +172,7 @@ namespace boost {
         size_type find(basic_string_ref s) const {
             const_iterator iter = std::search ( this->cbegin (), this->cend (), 
                                                 s.cbegin (), s.cend (), traits::eq );
-            return iter = this->cend () ? npos : std::distance ( this->cbegin (), iter );
+            return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
         
         size_type find(charT c) const {
@@ -198,7 +198,7 @@ namespace boost {
         
         size_type find_first_of(basic_string_ref s) const {
             const_iterator iter = std::find_first_of 
-            	( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
+                ( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
             return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
         
diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
index 67733ee..4624fb9 100644
--- a/test/string_ref_test2.cpp
+++ b/test/string_ref_test2.cpp
@@ -95,23 +95,33 @@ void find ( const char *arg ) {
     const char *p;
 
 //  Look for each character in the string(searching from the start)
-  p = arg;
-  sr1 = arg;
-  while ( *p ) {
-    string_ref::size_type pos = sr1.find(*p);
-    BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
-    ++p;
-    }
+    p = arg;
+    sr1 = arg;
+    while ( *p ) {
+      string_ref::size_type pos = sr1.find(*p);
+      BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
+      ++p;
+      }
   
 //  Look for each character in the string (searching from the end)
     p = arg;
     sr1 = arg;
     while ( *p ) {
-    string_ref::size_type pos = sr1.rfind(*p);
-    BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
-    ++p;
-    }
+      string_ref::size_type pos = sr1.rfind(*p);
+      BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
+      ++p;
+      }
 
+//	Look for pairs on characters (searching from the start)
+    sr1 = arg;
+    p = arg;
+	while ( *p && *(p+1)) {
+		string_ref sr3 ( p, 2 );
+		string_ref::size_type pos = sr1.find ( sr3 );
+		BOOST_CHECK ( pos != string_ref::npos && pos <= ( p - arg ));
+		p++;
+		}
+		
     sr1 = arg;
     p = arg;
 //  for all possible chars, see if we find them in the right place.
@@ -231,6 +241,56 @@ void find ( const char *arg ) {
 
     }
 
+#if 0
+void to_string ( const char *arg ) {
+    string_ref sr1;
+	std::string str1;
+	std::string str2;
+
+	str1.assign ( arg );
+	sr1 = arg;
+//	str2 = sr1.to_string > ();
+	str2 = sr1.to_string ();
+	BOOST_CHECK ( str1 == str2 );
+
+#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+	std::string str3 = static_cast ( sr1 );
+	BOOST_CHECK ( str1 == str3 );
+#endif
+    }
+
+void compare ( const char *arg ) {
+    string_ref sr1;
+	std::string str1;
+	std::string str2 = str1;
+
+	str1.assign ( arg );
+	sr1 = arg;
+	BOOST_CHECK ( sr1  == str1);	// compare string and string_ref
+	BOOST_CHECK ( str1 == sr1 );	// compare string_ref and string
+	BOOST_CHECK ( sr1  == arg );	// compare string_ref and pointer
+	BOOST_CHECK ( arg  == sr1 );	// compare pointer and string_ref
+
+	if ( sr1.size () > 0 ) {
+		(*str1.rbegin())++;
+		BOOST_CHECK ( sr1  != str1 );
+		BOOST_CHECK ( str1 != sr1 );
+		BOOST_CHECK ( sr1 < str1 );
+		BOOST_CHECK ( sr1 <= str1 );
+		BOOST_CHECK ( str1 > sr1 );
+		BOOST_CHECK ( str1 >= sr1 );
+
+		(*str1.rbegin()) -= 2;
+		BOOST_CHECK ( sr1  != str1 );
+		BOOST_CHECK ( str1 != sr1 );
+		BOOST_CHECK ( sr1 > str1 );
+		BOOST_CHECK ( sr1 >= str1 );
+		BOOST_CHECK ( str1 < sr1 );
+		BOOST_CHECK ( str1 <= sr1 );
+		}
+    }
+#endif
+
 const char *test_strings [] = {
     "",
     "0",
@@ -250,7 +310,9 @@ BOOST_AUTO_TEST_CASE( test_main )
         ends_with ( *p );
         reverse ( *p );
         find ( *p );
-
+//        to_string ( *p );
+//		compare ( *p );
+		
         p++;
         }
 }

From 6e2c1b6b53fdc571dbd81453159029582fbf39ff Mon Sep 17 00:00:00 2001
From: Marshall Clow 
Date: Fri, 15 Feb 2013 16:12:30 +0000
Subject: [PATCH 49/90] Added to_string and better comparisons to
 Boost.StringRef

[SVN r82902]
---
 include/boost/utility/string_ref.hpp | 68 +++++++++++++++++++++++++++-
 test/string_ref_test2.cpp            |  9 ++--
 2 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp
index 1be2ac9..657e9b6 100644
--- a/include/boost/utility/string_ref.hpp
+++ b/include/boost/utility/string_ref.hpp
@@ -34,6 +34,8 @@ namespace boost {
             bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
             charT ch_;
             };
+            
+        template struct __identity { typedef T type; };
         }
     
     template class basic_string_ref;
@@ -94,6 +96,10 @@ namespace boost {
             }
 #endif
         
+        std::basic_string to_string () const {
+            return std::basic_string ( ptr_, len_ );
+            }
+
         // iterators
         BOOST_CONSTEXPR const_iterator   begin() const { return ptr_; }
         BOOST_CONSTEXPR const_iterator  cbegin() const { return ptr_; }
@@ -252,38 +258,98 @@ namespace boost {
         std::size_t len_;
         };
     
-    // Comparison operators
+
+//  Comparison operators (3 for each operation)
+//  Equality
     template
     bool operator==(basic_string_ref x, basic_string_ref y) {
         if ( x.size () != y.size ()) return false;
         return x.compare(y) == 0;
         }
+    template
+    bool operator==(basic_string_ref x, typename detail::__identity >::type y) {
+        if ( x.size () != y.size ()) return false;
+        return x.compare(y) == 0;
+        }
+    template
+    bool operator==(typename detail::__identity >::type x, basic_string_ref y) {
+        if ( x.size () != y.size ()) return false;
+        return x.compare(y) == 0;
+        }
     
+//  Inequality
     template
     bool operator!=(basic_string_ref x, basic_string_ref y) {
         if ( x.size () != y.size ()) return true;
         return x.compare(y) != 0;
         }
+    template
+    bool operator!=(basic_string_ref x, typename detail::__identity >::type y) {
+        if ( x.size () != y.size ()) return true;
+        return x.compare(y) != 0;
+        }
+    template
+    bool operator!=(typename detail::__identity >::type x, basic_string_ref y) {
+        if ( x.size () != y.size ()) return true;
+        return x.compare(y) != 0;
+        }
 
+//  Less than
     template
     bool operator<(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) < 0;
         }
+    template
+    bool operator<(basic_string_ref x, typename detail::__identity >::type y) {
+        return x.compare(y) < 0;
+        }
+    template
+    bool operator<(typename detail::__identity >::type x, basic_string_ref y) {
+        return x.compare(y) < 0;
+        }
 
+//  Greater than
     template
     bool operator>(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) > 0;
         }
+    template
+    bool operator>(basic_string_ref x, typename detail::__identity >::type y) {
+        return x.compare(y) > 0;
+        }
+    template
+    bool operator>(typename detail::__identity >::type x, basic_string_ref y) {
+        return x.compare(y) > 0;
+        }
 
+//  Less than or equal to
     template
     bool operator<=(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) <= 0;
         }
+    template
+    bool operator<=(basic_string_ref x, typename detail::__identity >::type y) {
+        return x.compare(y) <= 0;
+        }
+    template
+    bool operator<=(typename detail::__identity >::type x, basic_string_ref y) {
+        return x.compare(y) <= 0;
+        }
 
+//  Greater than or equal to
     template
     bool operator>=(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) >= 0;
         }
+    template
+    bool operator>=(basic_string_ref x, typename detail::__identity >::type y) {
+        return x.compare(y) >= 0;
+        }
+    template
+    bool operator>=(typename detail::__identity >::type x, basic_string_ref y) {
+        return x.compare(y) >= 0;
+        }
+
 
     
     // Inserter
diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
index 4624fb9..c4885a4 100644
--- a/test/string_ref_test2.cpp
+++ b/test/string_ref_test2.cpp
@@ -118,7 +118,7 @@ void find ( const char *arg ) {
 	while ( *p && *(p+1)) {
 		string_ref sr3 ( p, 2 );
 		string_ref::size_type pos = sr1.find ( sr3 );
-		BOOST_CHECK ( pos != string_ref::npos && pos <= ( p - arg ));
+		BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast( p - arg ));
 		p++;
 		}
 		
@@ -241,7 +241,7 @@ void find ( const char *arg ) {
 
     }
 
-#if 0
+
 void to_string ( const char *arg ) {
     string_ref sr1;
 	std::string str1;
@@ -289,7 +289,6 @@ void compare ( const char *arg ) {
 		BOOST_CHECK ( str1 <= sr1 );
 		}
     }
-#endif
 
 const char *test_strings [] = {
     "",
@@ -310,8 +309,8 @@ BOOST_AUTO_TEST_CASE( test_main )
         ends_with ( *p );
         reverse ( *p );
         find ( *p );
-//        to_string ( *p );
-//		compare ( *p );
+        to_string ( *p );
+		compare ( *p );
 		
         p++;
         }

From 9284a649366936ea82524c27377f242c828f1f69 Mon Sep 17 00:00:00 2001
From: Eric Niebler 
Date: Sun, 17 Feb 2013 23:56:10 +0000
Subject: [PATCH 50/90] disable annoying msvc warning, refs #7663

[SVN r82960]
---
 include/boost/utility/result_of.hpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp
index 4a20254..97e9618 100644
--- a/include/boost/utility/result_of.hpp
+++ b/include/boost/utility/result_of.hpp
@@ -68,6 +68,13 @@ template struct tr1_result_of_im
 
 #ifdef BOOST_NO_SFINAE_EXPR
 
+// There doesn't seem to be any other way to turn this off such that the presence of
+// the user-defined operator,() below doesn't cause spurious warning all over the place,
+// so unconditionally turn it off.
+#if BOOST_MSVC
+#  pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used
+#endif
+
 struct result_of_private_type {};
 
 struct result_of_weird_type {

From e0e16be802f64826c15d1fe42a19308cd445fdf5 Mon Sep 17 00:00:00 2001
From: Eric Niebler 
Date: Mon, 25 Feb 2013 06:30:00 +0000
Subject: [PATCH 51/90] fix breakage of string_ref logical ops, detabify,
 remove trailing whitespace

[SVN r83147]
---
 include/boost/utility/string_ref.hpp | 270 +++++++++++++++++----------
 test/string_ref_test1.cpp            |  26 +--
 test/string_ref_test2.cpp            | 107 +++++------
 3 files changed, 234 insertions(+), 169 deletions(-)

diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp
index 657e9b6..6d5cace 100644
--- a/include/boost/utility/string_ref.hpp
+++ b/include/boost/utility/string_ref.hpp
@@ -1,11 +1,11 @@
-/* 
+/*
    Copyright (c) Marshall Clow 2012-2012.
 
    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)
 
     For more information, see http://www.boost.org
-    
+
     Based on the StringRef implementation in LLVM (http://llvm.org) and
     N3422 by Jeffrey Yasskin
         http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
@@ -24,7 +24,7 @@
 #include 
 
 namespace boost {
-    
+
     namespace detail {
     //  A helper functor because sometimes we don't have lambdas
         template 
@@ -34,10 +34,8 @@ namespace boost {
             bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
             charT ch_;
             };
-            
-        template struct __identity { typedef T type; };
         }
-    
+
     template class basic_string_ref;
     typedef basic_string_ref >        string_ref;
     typedef basic_string_ref >    wstring_ref;
@@ -49,7 +47,7 @@ namespace boost {
 #ifndef BOOST_NO_CXX11_CHAR32_T
     typedef basic_string_ref > u32string_ref;
 #endif
-    
+
     template
     class basic_string_ref {
     public:
@@ -65,7 +63,7 @@ namespace boost {
         typedef std::size_t size_type;
         typedef ptrdiff_t difference_type;
         static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
-        
+
         // construct/copy
         BOOST_CONSTEXPR basic_string_ref ()
             : ptr_(NULL), len_(0) {}
@@ -78,7 +76,7 @@ namespace boost {
             len_ = rhs.len_;
             return *this;
             }
-            
+
         basic_string_ref(const charT* str)
             : ptr_(str), len_(traits::length(str)) {}
 
@@ -95,7 +93,7 @@ namespace boost {
             return std::basic_string ( ptr_, len_ );
             }
 #endif
-        
+
         std::basic_string to_string () const {
             return std::basic_string ( ptr_, len_ );
             }
@@ -109,13 +107,13 @@ namespace boost {
                 const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); }
                 const_reverse_iterator    rend() const { return const_reverse_iterator (begin()); }
                 const_reverse_iterator   crend() const { return const_reverse_iterator (begin()); }
-        
+
         // capacity
         BOOST_CONSTEXPR size_type size()     const { return len_; }
         BOOST_CONSTEXPR size_type length()   const { return len_; }
         BOOST_CONSTEXPR size_type max_size() const { return len_; }
         BOOST_CONSTEXPR bool empty()         const { return len_ == 0; }
-        
+
         // element access
         BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; }
 
@@ -124,11 +122,11 @@ namespace boost {
                 throw std::out_of_range ( "boost::string_ref::at" );
             return ptr_[pos];
             }
-            
+
         BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; }
         BOOST_CONSTEXPR const charT& back()  const { return ptr_[len_-1]; }
         BOOST_CONSTEXPR const charT* data()  const { return ptr_; }
-        
+
         // modifiers
         void clear() { len_ = 0; }
         void remove_prefix(size_type n) {
@@ -137,14 +135,14 @@ namespace boost {
             ptr_ += n;
             len_ -= n;
             }
-            
+
         void remove_suffix(size_type n) {
             if ( n > len_ )
                 n = len_;
             len_ -= n;
             }
-            
-        
+
+
         // basic_string_ref string operations
         BOOST_CONSTEXPR
         basic_string_ref substr(size_type pos, size_type n=npos) const {
@@ -159,78 +157,78 @@ namespace boost {
                 basic_string_ref ( data() + pos, n == npos || pos + n > size() ? size() - pos : n );
 #endif
             }
-        
+
         int compare(basic_string_ref x) const {
             const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_));
             return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
             }
-        
+
         bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
         bool starts_with(basic_string_ref x) const {
             return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
             }
-        
+
         bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
         bool ends_with(basic_string_ref x) const {
             return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
             }
 
         size_type find(basic_string_ref s) const {
-            const_iterator iter = std::search ( this->cbegin (), this->cend (), 
+            const_iterator iter = std::search ( this->cbegin (), this->cend (),
                                                 s.cbegin (), s.cend (), traits::eq );
             return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
-        
+
         size_type find(charT c) const {
-            const_iterator iter = std::find_if ( this->cbegin (), this->cend (), 
+            const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
                                     detail::string_ref_traits_eq ( c ));
             return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
-                        
+
         size_type rfind(basic_string_ref s) const {
-            const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (), 
+            const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
                                                 s.crbegin (), s.crend (), traits::eq );
             return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
             }
 
         size_type rfind(charT c) const {
-            const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (), 
+            const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
                                     detail::string_ref_traits_eq ( c ));
             return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
             }
-        
+
         size_type find_first_of(charT c) const { return  find (c); }
         size_type find_last_of (charT c) const { return rfind (c); }
-        
+
         size_type find_first_of(basic_string_ref s) const {
-            const_iterator iter = std::find_first_of 
+            const_iterator iter = std::find_first_of
                 ( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
             return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
-        
+
         size_type find_last_of(basic_string_ref s) const {
-            const_reverse_iterator iter = std::find_first_of 
+            const_reverse_iterator iter = std::find_first_of
                 ( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
             return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
             }
-        
+
         size_type find_first_not_of(basic_string_ref s) const {
-        	const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
+            const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
             return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
             }
-        
+
         size_type find_first_not_of(charT c) const {
             for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter )
                 if ( !traits::eq ( c, *iter ))
                     return std::distance ( this->cbegin (), iter );
             return npos;
             }
-        
+
         size_type find_last_not_of(basic_string_ref s) const {
-        	const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
+            const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
             return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
             }
-        
+
         size_type find_last_not_of(charT c) const {
             for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
                 if ( !traits::eq ( c, *iter ))
@@ -243,55 +241,75 @@ namespace boost {
         size_type reverse_distance ( r_iter first, r_iter last ) const {
             return len_ - 1 - std::distance ( first, last );
             }
-        
+
         template 
         Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
-			for ( ; first != last ; ++first )
-				if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
-					return first;
-			return last;
-			}
-		
-       		
-        
+            for ( ; first != last ; ++first )
+                if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
+                    return first;
+            return last;
+            }
+
+
+
         const charT *ptr_;
         std::size_t len_;
         };
-    
 
-//  Comparison operators (3 for each operation)
+
+//  Comparison operators
 //  Equality
     template
     bool operator==(basic_string_ref x, basic_string_ref y) {
         if ( x.size () != y.size ()) return false;
         return x.compare(y) == 0;
         }
-    template
-    bool operator==(basic_string_ref x, typename detail::__identity >::type y) {
-        if ( x.size () != y.size ()) return false;
-        return x.compare(y) == 0;
+
+    template
+    bool operator==(basic_string_ref x, const std::basic_string & y) {
+        return x == basic_string_ref(y);
         }
-    template
-    bool operator==(typename detail::__identity >::type x, basic_string_ref y) {
-        if ( x.size () != y.size ()) return false;
-        return x.compare(y) == 0;
+
+    template
+    bool operator==(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) == y;
         }
-    
+
+    template
+    bool operator==(basic_string_ref x, const charT * y) {
+        return x == basic_string_ref(y);
+        }
+
+    template
+    bool operator==(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) == y;
+        }
+
 //  Inequality
     template
     bool operator!=(basic_string_ref x, basic_string_ref y) {
         if ( x.size () != y.size ()) return true;
         return x.compare(y) != 0;
         }
-    template
-    bool operator!=(basic_string_ref x, typename detail::__identity >::type y) {
-        if ( x.size () != y.size ()) return true;
-        return x.compare(y) != 0;
+
+    template
+    bool operator!=(basic_string_ref x, const std::basic_string & y) {
+        return x != basic_string_ref(y);
         }
+
+    template
+    bool operator!=(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) != y;
+        }
+
     template
-    bool operator!=(typename detail::__identity >::type x, basic_string_ref y) {
-        if ( x.size () != y.size ()) return true;
-        return x.compare(y) != 0;
+    bool operator!=(basic_string_ref x, const charT * y) {
+        return x != basic_string_ref(y);
+        }
+
+    template
+    bool operator!=(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) != y;
         }
 
 //  Less than
@@ -299,13 +317,25 @@ namespace boost {
     bool operator<(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) < 0;
         }
-    template
-    bool operator<(basic_string_ref x, typename detail::__identity >::type y) {
-        return x.compare(y) < 0;
+
+    template
+    bool operator<(basic_string_ref x, const std::basic_string & y) {
+        return x < basic_string_ref(y);
         }
+
+    template
+    bool operator<(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) < y;
+        }
+
     template
-    bool operator<(typename detail::__identity >::type x, basic_string_ref y) {
-        return x.compare(y) < 0;
+    bool operator<(basic_string_ref x, const charT * y) {
+        return x < basic_string_ref(y);
+        }
+
+    template
+    bool operator<(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) < y;
         }
 
 //  Greater than
@@ -313,13 +343,25 @@ namespace boost {
     bool operator>(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) > 0;
         }
-    template
-    bool operator>(basic_string_ref x, typename detail::__identity >::type y) {
-        return x.compare(y) > 0;
+
+    template
+    bool operator>(basic_string_ref x, const std::basic_string & y) {
+        return x > basic_string_ref(y);
         }
+
+    template
+    bool operator>(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) > y;
+        }
+
     template
-    bool operator>(typename detail::__identity >::type x, basic_string_ref y) {
-        return x.compare(y) > 0;
+    bool operator>(basic_string_ref x, const charT * y) {
+        return x > basic_string_ref(y);
+        }
+
+    template
+    bool operator>(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) > y;
         }
 
 //  Less than or equal to
@@ -327,13 +369,25 @@ namespace boost {
     bool operator<=(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) <= 0;
         }
-    template
-    bool operator<=(basic_string_ref x, typename detail::__identity >::type y) {
-        return x.compare(y) <= 0;
+
+    template
+    bool operator<=(basic_string_ref x, const std::basic_string & y) {
+        return x <= basic_string_ref(y);
         }
+
+    template
+    bool operator<=(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) <= y;
+        }
+
     template
-    bool operator<=(typename detail::__identity >::type x, basic_string_ref y) {
-        return x.compare(y) <= 0;
+    bool operator<=(basic_string_ref x, const charT * y) {
+        return x <= basic_string_ref(y);
+        }
+
+    template
+    bool operator<=(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) <= y;
         }
 
 //  Greater than or equal to
@@ -341,17 +395,27 @@ namespace boost {
     bool operator>=(basic_string_ref x, basic_string_ref y) {
         return x.compare(y) >= 0;
         }
-    template
-    bool operator>=(basic_string_ref x, typename detail::__identity >::type y) {
-        return x.compare(y) >= 0;
-        }
-    template
-    bool operator>=(typename detail::__identity >::type x, basic_string_ref y) {
-        return x.compare(y) >= 0;
+
+    template
+    bool operator>=(basic_string_ref x, const std::basic_string & y) {
+        return x >= basic_string_ref(y);
         }
 
+    template
+    bool operator>=(const std::basic_string & x, basic_string_ref y) {
+        return basic_string_ref(x) >= y;
+        }
+
+    template
+    bool operator>=(basic_string_ref x, const charT * y) {
+        return x >= basic_string_ref(y);
+        }
+
+    template
+    bool operator>=(const charT * x, basic_string_ref y) {
+        return basic_string_ref(x) >= y;
+        }
 
-    
     // Inserter
     template
     std::basic_ostream&
@@ -365,7 +429,7 @@ namespace boost {
 #endif
         return os;
         }
-    
+
 #if 0
     // numeric conversions
     //
@@ -375,63 +439,63 @@ namespace boost {
     int stoi (string_ref str, size_t* idx=0, int base=10) {
         return std::stoi ( std::string(str), idx, base );
         }
-    
+
     long stol (string_ref str, size_t* idx=0, int base=10) {
         return std::stol ( std::string(str), idx, base );
         }
-        
+
     unsigned long stoul (string_ref str, size_t* idx=0, int base=10) {
         return std::stoul ( std::string(str), idx, base );
         }
-        
+
     long long stoll (string_ref str, size_t* idx=0, int base=10) {
         return std::stoll ( std::string(str), idx, base );
         }
-    
+
     unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) {
         return std::stoull ( std::string(str), idx, base );
         }
-    
+
     float stof (string_ref str, size_t* idx=0) {
         return std::stof ( std::string(str), idx );
         }
-        
+
     double stod (string_ref str, size_t* idx=0) {
         return std::stod ( std::string(str), idx );
         }
-        
+
     long double stold (string_ref str, size_t* idx=0)  {
         return std::stold ( std::string(str), idx );
         }
-    
+
     int  stoi (wstring_ref str, size_t* idx=0, int base=10) {
         return std::stoi ( std::wstring(str), idx, base );
         }
-        
+
     long stol (wstring_ref str, size_t* idx=0, int base=10) {
         return std::stol ( std::wstring(str), idx, base );
         }
-        
+
     unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) {
         return std::stoul ( std::wstring(str), idx, base );
         }
-        
+
     long long stoll (wstring_ref str, size_t* idx=0, int base=10) {
         return std::stoll ( std::wstring(str), idx, base );
         }
-        
+
     unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) {
         return std::stoull ( std::wstring(str), idx, base );
         }
-    
+
     float  stof (wstring_ref str, size_t* idx=0) {
         return std::stof ( std::wstring(str), idx );
         }
-        
+
     double stod (wstring_ref str, size_t* idx=0) {
         return std::stod ( std::wstring(str), idx );
         }
-        
+
     long double stold (wstring_ref str, size_t* idx=0) {
         return std::stold ( std::wstring(str), idx );
         }
diff --git a/test/string_ref_test1.cpp b/test/string_ref_test1.cpp
index 7524536..f1d4df2 100644
--- a/test/string_ref_test1.cpp
+++ b/test/string_ref_test1.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
    Copyright (c) Marshall Clow 2012-2012.
 
    Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -33,30 +33,30 @@ void null_tests ( const char *p ) {
     string_ref sr3 ( p, 0 );
     string_ref sr4 ( p );
     sr4.clear ();
-    
+
     BOOST_CHECK ( sr1 == sr2 );
     BOOST_CHECK ( sr1 == sr3 );
     BOOST_CHECK ( sr2 == sr3 );
-    BOOST_CHECK ( sr1 == sr4 );    
+    BOOST_CHECK ( sr1 == sr4 );
     }
 
 //  make sure that substrings work just like strings
 void test_substr ( const std::string &str ) {
     const size_t sz = str.size ();
     string_ref ref ( str );
-    
+
 //  Substrings at the end
     for ( size_t i = 0; i <= sz; ++ i )
         interop ( str.substr ( i ), ref.substr ( i ));
-        
+
 //  Substrings at the beginning
     for ( size_t i = 0; i <= sz; ++ i )
         interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
-        
+
 //  All possible substrings
     for ( size_t i = 0; i < sz; ++i )
         for ( size_t j = i; j < sz; ++j )
-            interop ( str.substr ( i, j ), ref.substr ( i, j ));    
+            interop ( str.substr ( i, j ), ref.substr ( i, j ));
     }
 
 //  make sure that removing prefixes and suffixes work just like strings
@@ -64,20 +64,20 @@ void test_remove ( const std::string &str ) {
     const size_t sz = str.size ();
     std::string work;
     string_ref ref;
-    
+
     for ( size_t i = 1; i <= sz; ++i ) {
       work = str;
-      ref  = str;     
+      ref  = str;
       while ( ref.size () >= i ) {
           interop ( work, ref );
           work.erase ( 0, i );
           ref.remove_prefix (i);
           }
       }
-    
+
     for ( size_t i = 1; i < sz; ++ i ) {
       work = str;
-      ref  = str;     
+      ref  = str;
       while ( ref.size () >= i ) {
           interop ( work, ref );
           work.erase ( work.size () - i, i );
@@ -93,7 +93,7 @@ const char *test_strings [] = {
     "0123456789",
     NULL
     };
-    
+
 BOOST_AUTO_TEST_CASE( test_main )
 {
     const char **p = &test_strings[0];
@@ -103,7 +103,7 @@ BOOST_AUTO_TEST_CASE( test_main )
         test_substr ( *p );
         test_remove ( *p );
         null_tests ( *p );
-    
+
         p++;
         }
 }
diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
index c4885a4..89e1cfc 100644
--- a/test/string_ref_test2.cpp
+++ b/test/string_ref_test2.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
    Copyright (c) Marshall Clow 2012-2012.
 
    Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -46,7 +46,7 @@ void ends_with ( const char *arg ) {
     BOOST_CHECK ( !sr2.ends_with ( ++ch ));
     BOOST_CHECK ( sr2.ends_with ( string_ref ()));
     }
-    
+
 void starts_with ( const char *arg ) {
     const size_t sz = strlen ( arg );
     string_ref sr  ( arg );
@@ -85,9 +85,9 @@ void reverse ( const char *arg ) {
 
 //	This helper function eliminates signed vs. unsigned warnings
 string_ref::size_type ptr_diff ( const char *res, const char *base ) {
-	BOOST_CHECK ( res >= base );
-	return static_cast ( res - base );
-	}
+    BOOST_CHECK ( res >= base );
+    return static_cast ( res - base );
+    }
 
 void find ( const char *arg ) {
     string_ref sr1;
@@ -102,7 +102,7 @@ void find ( const char *arg ) {
       BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg )));
       ++p;
       }
-  
+
 //  Look for each character in the string (searching from the end)
     p = arg;
     sr1 = arg;
@@ -115,13 +115,13 @@ void find ( const char *arg ) {
 //	Look for pairs on characters (searching from the start)
     sr1 = arg;
     p = arg;
-	while ( *p && *(p+1)) {
-		string_ref sr3 ( p, 2 );
-		string_ref::size_type pos = sr1.find ( sr3 );
-		BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast( p - arg ));
-		p++;
-		}
-		
+    while ( *p && *(p+1)) {
+        string_ref sr3 ( p, 2 );
+        string_ref::size_type pos = sr1.find ( sr3 );
+        BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast( p - arg ));
+        p++;
+        }
+
     sr1 = arg;
     p = arg;
 //  for all possible chars, see if we find them in the right place.
@@ -166,7 +166,7 @@ void find ( const char *arg ) {
         sr1.remove_suffix (1);
         --p;
         }
-        
+
 //  Find everything at the start
     sr1  = arg;
     p    = arg;
@@ -187,7 +187,7 @@ void find ( const char *arg ) {
         sr1.remove_suffix (1);
         --p;
         }
-        
+
 //  Basic sanity checking for "find_first_of / find_first_not_of"
     sr1 = arg;
     sr2 = arg;
@@ -212,7 +212,7 @@ void find ( const char *arg ) {
         BOOST_CHECK ( pos2 != pos1 );
         ++p;
         }
-        
+
 //  Basic sanity checking for "find_last_of / find_last_not_of"
     sr1 = arg;
     sr2 = arg;
@@ -234,7 +234,7 @@ void find ( const char *arg ) {
                 BOOST_CHECK ( sr1[i] == *p );
             BOOST_CHECK ( sr1 [ pos2 ] != *p );
             }
-         
+
         BOOST_CHECK ( pos2 != pos1 );
         ++p;
         }
@@ -244,50 +244,51 @@ void find ( const char *arg ) {
 
 void to_string ( const char *arg ) {
     string_ref sr1;
-	std::string str1;
-	std::string str2;
+    std::string str1;
+    std::string str2;
 
-	str1.assign ( arg );
-	sr1 = arg;
+    str1.assign ( arg );
+    sr1 = arg;
 //	str2 = sr1.to_string > ();
-	str2 = sr1.to_string ();
-	BOOST_CHECK ( str1 == str2 );
+    str2 = sr1.to_string ();
+    BOOST_CHECK ( str1 == str2 );
 
 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
-	std::string str3 = static_cast ( sr1 );
-	BOOST_CHECK ( str1 == str3 );
+    std::string str3 = static_cast ( sr1 );
+    BOOST_CHECK ( str1 == str3 );
 #endif
     }
 
 void compare ( const char *arg ) {
     string_ref sr1;
-	std::string str1;
-	std::string str2 = str1;
+    std::string str1;
+    std::string str2 = str1;
 
-	str1.assign ( arg );
-	sr1 = arg;
-	BOOST_CHECK ( sr1  == str1);	// compare string and string_ref
-	BOOST_CHECK ( str1 == sr1 );	// compare string_ref and string
-	BOOST_CHECK ( sr1  == arg );	// compare string_ref and pointer
-	BOOST_CHECK ( arg  == sr1 );	// compare pointer and string_ref
+    str1.assign ( arg );
+    sr1 = arg;
+    BOOST_CHECK ( sr1  == sr1);	    // compare string_ref and string_ref
+    BOOST_CHECK ( sr1  == str1);	// compare string and string_ref
+    BOOST_CHECK ( str1 == sr1 );	// compare string_ref and string
+    BOOST_CHECK ( sr1  == arg );	// compare string_ref and pointer
+    BOOST_CHECK ( arg  == sr1 );	// compare pointer and string_ref
 
-	if ( sr1.size () > 0 ) {
-		(*str1.rbegin())++;
-		BOOST_CHECK ( sr1  != str1 );
-		BOOST_CHECK ( str1 != sr1 );
-		BOOST_CHECK ( sr1 < str1 );
-		BOOST_CHECK ( sr1 <= str1 );
-		BOOST_CHECK ( str1 > sr1 );
-		BOOST_CHECK ( str1 >= sr1 );
+    if ( sr1.size () > 0 ) {
+        (*str1.rbegin())++;
+        BOOST_CHECK ( sr1  != str1 );
+        BOOST_CHECK ( str1 != sr1 );
+        BOOST_CHECK ( sr1 < str1 );
+        BOOST_CHECK ( sr1 <= str1 );
+        BOOST_CHECK ( str1 > sr1 );
+        BOOST_CHECK ( str1 >= sr1 );
 
-		(*str1.rbegin()) -= 2;
-		BOOST_CHECK ( sr1  != str1 );
-		BOOST_CHECK ( str1 != sr1 );
-		BOOST_CHECK ( sr1 > str1 );
-		BOOST_CHECK ( sr1 >= str1 );
-		BOOST_CHECK ( str1 < sr1 );
-		BOOST_CHECK ( str1 <= sr1 );
-		}
+        (*str1.rbegin()) -= 2;
+        BOOST_CHECK ( sr1  != str1 );
+        BOOST_CHECK ( str1 != sr1 );
+        BOOST_CHECK ( sr1 > str1 );
+        BOOST_CHECK ( sr1 >= str1 );
+        BOOST_CHECK ( str1 < sr1 );
+        BOOST_CHECK ( str1 <= sr1 );
+        }
     }
 
 const char *test_strings [] = {
@@ -299,19 +300,19 @@ const char *test_strings [] = {
     "abc\0asdfadsfasf",
     NULL
     };
-    
+
 BOOST_AUTO_TEST_CASE( test_main )
 {
     const char **p = &test_strings[0];
-    
+
     while ( *p != NULL ) {
         starts_with ( *p );
         ends_with ( *p );
         reverse ( *p );
         find ( *p );
         to_string ( *p );
-		compare ( *p );
-		
+        compare ( *p );
+
         p++;
         }
 }

From 1cdb78c30a6cbfc77ea813f69181cdc6be1d52db Mon Sep 17 00:00:00 2001
From: "Vicente J. Botet Escriba" 
Date: Thu, 14 Mar 2013 17:46:52 +0000
Subject: [PATCH 52/90] Assert: take care of #7028.

[SVN r83428]
---
 include/boost/assert.hpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp
index a233505..ed8294f 100644
--- a/include/boost/assert.hpp
+++ b/include/boost/assert.hpp
@@ -28,7 +28,7 @@
 
 #undef BOOST_ASSERT
 
-#if defined(BOOST_DISABLE_ASSERTS)
+#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
 
 # define BOOST_ASSERT(expr) ((void)0)
 
@@ -89,9 +89,9 @@ namespace boost
     #endif
 
     namespace boost
-    { 
-      namespace assertion 
-      { 
+    {
+      namespace assertion
+      {
         namespace detail
         {
           inline void assertion_failed_msg(char const * expr, char const * msg, char const * function,

From 98bb9e630083402963badeb64973ba0101e5c4dd Mon Sep 17 00:00:00 2001
From: "Vicente J. Botet Escriba" 
Date: Thu, 14 Mar 2013 17:48:06 +0000
Subject: [PATCH 53/90] Utility: address_of take care of #7079.

[SVN r83429]
---
 include/boost/utility/addressof.hpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/boost/utility/addressof.hpp b/include/boost/utility/addressof.hpp
index 95cd92f..ecb7776 100644
--- a/include/boost/utility/addressof.hpp
+++ b/include/boost/utility/addressof.hpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2002 Brad King (brad.king@kitware.com) 
+// Copyright (C) 2002 Brad King (brad.king@kitware.com)
 //                    Douglas Gregor (gregod@cs.rpi.edu)
 //
 // Copyright (C) 2002, 2008 Peter Dimov
@@ -50,7 +50,7 @@ template struct addressof_impl
 
 template T * addressof( T & v )
 {
-#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) )
+#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
 
     return boost::detail::addressof_impl::f( v, 0 );
 

From 2e4007413e108bc88beb4496797ad7534566aeae Mon Sep 17 00:00:00 2001
From: "Vicente J. Botet Escriba" 
Date: Thu, 14 Mar 2013 22:27:04 +0000
Subject: [PATCH 54/90] Assert: rollback [82428].

[SVN r83431]
---
 include/boost/assert.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp
index ed8294f..c42ea4c 100644
--- a/include/boost/assert.hpp
+++ b/include/boost/assert.hpp
@@ -28,7 +28,7 @@
 
 #undef BOOST_ASSERT
 
-#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
+#if defined(BOOST_DISABLE_ASSERTS)
 
 # define BOOST_ASSERT(expr) ((void)0)
 

From 9cb31aee6ee056fa30f9a6e64526ddb6c7fb9a60 Mon Sep 17 00:00:00 2001
From: Marshall Clow 
Date: Mon, 18 Mar 2013 20:46:53 +0000
Subject: [PATCH 55/90] Fix bug in test; thanks to AddressSanitizer for the
 heads-up

[SVN r83493]
---
 test/string_ref_test2.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/string_ref_test2.cpp b/test/string_ref_test2.cpp
index 89e1cfc..174405d 100644
--- a/test/string_ref_test2.cpp
+++ b/test/string_ref_test2.cpp
@@ -23,7 +23,7 @@ void ends_with ( const char *arg ) {
     string_ref sr2 ( arg );
     const char *p = arg;
 
-    while ( !*p ) {
+    while ( *p ) {
         BOOST_CHECK ( sr.ends_with ( p ));
         ++p;
         }

From 1057ff4d9e8a9b01dc237a6b870bab532e01abfb Mon Sep 17 00:00:00 2001
From: "Vicente J. Botet Escriba" 
Date: Wed, 10 Apr 2013 17:16:02 +0000
Subject: [PATCH 56/90] Utility/noncopyable: Make use of =delete #6578.

[SVN r83833]
---
 include/boost/noncopyable.hpp | 18 +++++++++++++++---
 utility.htm                   | 10 +++++++---
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/boost/noncopyable.hpp b/include/boost/noncopyable.hpp
index 7770bdb..eb8e2e7 100644
--- a/include/boost/noncopyable.hpp
+++ b/include/boost/noncopyable.hpp
@@ -9,6 +9,8 @@
 #ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
 #define BOOST_NONCOPYABLE_HPP_INCLUDED
 
+#include 
+
 namespace boost {
 
 //  Private copy constructor and copy assignment ensure classes derived from
@@ -21,11 +23,21 @@ namespace noncopyable_  // protection from unintended ADL
   class noncopyable
   {
    protected:
-      noncopyable() {}
+#ifndef BOOST_NO_DEFAULTED_FUNCTIONS
+    BOOST_CONSTEXPR noncopyable() = default;
+    ~noncopyable() = default;
+#else
+    noncopyable() {}
       ~noncopyable() {}
-   private:  // emphasize the following members are private
+#endif
+#ifndef BOOST_NO_DELETED_FUNCTIONS
+        noncopyable( const noncopyable& ) = delete;
+        noncopyable& operator=( const noncopyable& ) = delete;
+#else
+    private:  // emphasize the following members are private
       noncopyable( const noncopyable& );
-      const noncopyable& operator=( const noncopyable& );
+      noncopyable& operator=( const noncopyable& );
+#endif
   };
 }
 
diff --git a/utility.htm b/utility.htm
index 94920c3..974776e 100644
--- a/utility.htm
+++ b/utility.htm
@@ -84,8 +84,10 @@ const std::list<T>::iterator next = boost::next(prev, 2);
will prevent the otherwise implicitly-generated functions (which don't have the proper semantics) from becoming a trap for other programmers.

The traditional way to deal with these is to declare a private copy constructor - and copy assignment, and then document why this is done.  But deriving - from noncopyable is simpler and clearer, and doesn't require additional + and copy assignment, and then document why this is done.  A new alternative + was introduced in C++2011, declaring a copy constructor and a copy assignment + operator, but marking both as deleted.  Deriving + from noncopyable is simpler and clearer, and doesn't require additional documentation.

The program noncopyable_test.cpp can be used to verify class noncopyable works as expected. It has have been run @@ -106,7 +108,9 @@ class ResourceLadenFileSystem : boost::noncopyable { about the effect on compiler optimization of adding (even trivial inline) destructor declarations. He says "Probably this concern is misplaced, because noncopyable will be used mostly for classes which own resources and - thus have non-trivial destruction semantics."

+ thus have non-trivial destruction semantics."  With C++2011, using an + optimized and trivial constructor and similar destructor can be enforced by + declaring both and marking them default.

Function template addressof()

Function addressof() returns the address of an object.

From 91aab126e127ad8cf9d84c8d8d1df023a374cfeb Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 26 May 2013 15:36:25 +0000 Subject: [PATCH 57/90] 1. Extracted forward declarations to a separate header so that it can be included by other libraries (Boost.Log, for instance). 2. Added a default value for char traits template parameter. 3. Added missing headers and removed unused ones. 4. Added inline specifiers to operators. 5. Fixed operator<< behaving incorrectly when particular width is requested (std::setw, etc.). 6. Replaced all throw statements with BOOST_THROW_EXCEPTION. [SVN r84511] --- include/boost/utility/string_ref.hpp | 157 ++++++++++++----------- include/boost/utility/string_ref_fwd.hpp | 37 ++++++ 2 files changed, 118 insertions(+), 76 deletions(-) create mode 100644 include/boost/utility/string_ref_fwd.hpp diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index 6d5cace..1bab84c 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -17,10 +17,13 @@ #include #include +#include +#include +#include #include #include -#include +#include #include namespace boost { @@ -36,18 +39,6 @@ namespace boost { }; } - template class basic_string_ref; - typedef basic_string_ref > string_ref; - typedef basic_string_ref > wstring_ref; - -#ifndef BOOST_NO_CXX11_CHAR16_T - typedef basic_string_ref > u16string_ref; -#endif - -#ifndef BOOST_NO_CXX11_CHAR32_T - typedef basic_string_ref > u32string_ref; -#endif - template class basic_string_ref { public: @@ -61,7 +52,7 @@ namespace boost { typedef std::reverse_iterator const_reverse_iterator; typedef const_reverse_iterator reverse_iterator; typedef std::size_t size_type; - typedef ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); // construct/copy @@ -119,7 +110,7 @@ namespace boost { const charT& at(size_t pos) const { if ( pos >= len_ ) - throw std::out_of_range ( "boost::string_ref::at" ); + BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) ); return ptr_[pos]; } @@ -146,16 +137,13 @@ namespace boost { // basic_string_ref string operations BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const { -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600) // Looks like msvc 8 and 9 have a codegen bug when one branch of // a conditional operator is a throw expression. -EAN 2012/12/04 - if ( pos > size()) throw std::out_of_range ( "string_ref::substr" ); - if ( n == npos || pos + n > size()) n = size () - pos; + if ( pos > size()) + BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) ); + if ( n == npos || pos + n > size()) + n = size () - pos; return basic_string_ref ( data() + pos, n ); -#else - return pos > size() ? throw std::out_of_range ( "string_ref::substr" ) : - basic_string_ref ( data() + pos, n == npos || pos + n > size() ? size() - pos : n ); -#endif } int compare(basic_string_ref x) const { @@ -260,173 +248,190 @@ namespace boost { // Comparison operators // Equality template - bool operator==(basic_string_ref x, basic_string_ref y) { + inline bool operator==(basic_string_ref x, basic_string_ref y) { if ( x.size () != y.size ()) return false; return x.compare(y) == 0; } template - bool operator==(basic_string_ref x, const std::basic_string & y) { + inline bool operator==(basic_string_ref x, const std::basic_string & y) { return x == basic_string_ref(y); } template - bool operator==(const std::basic_string & x, basic_string_ref y) { + inline bool operator==(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) == y; } template - bool operator==(basic_string_ref x, const charT * y) { + inline bool operator==(basic_string_ref x, const charT * y) { return x == basic_string_ref(y); } template - bool operator==(const charT * x, basic_string_ref y) { + inline bool operator==(const charT * x, basic_string_ref y) { return basic_string_ref(x) == y; } // Inequality template - bool operator!=(basic_string_ref x, basic_string_ref y) { + inline bool operator!=(basic_string_ref x, basic_string_ref y) { if ( x.size () != y.size ()) return true; return x.compare(y) != 0; } template - bool operator!=(basic_string_ref x, const std::basic_string & y) { + inline bool operator!=(basic_string_ref x, const std::basic_string & y) { return x != basic_string_ref(y); } template - bool operator!=(const std::basic_string & x, basic_string_ref y) { + inline bool operator!=(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) != y; } template - bool operator!=(basic_string_ref x, const charT * y) { + inline bool operator!=(basic_string_ref x, const charT * y) { return x != basic_string_ref(y); } template - bool operator!=(const charT * x, basic_string_ref y) { + inline bool operator!=(const charT * x, basic_string_ref y) { return basic_string_ref(x) != y; } // Less than template - bool operator<(basic_string_ref x, basic_string_ref y) { + inline bool operator<(basic_string_ref x, basic_string_ref y) { return x.compare(y) < 0; } template - bool operator<(basic_string_ref x, const std::basic_string & y) { + inline bool operator<(basic_string_ref x, const std::basic_string & y) { return x < basic_string_ref(y); } template - bool operator<(const std::basic_string & x, basic_string_ref y) { + inline bool operator<(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) < y; } template - bool operator<(basic_string_ref x, const charT * y) { + inline bool operator<(basic_string_ref x, const charT * y) { return x < basic_string_ref(y); } template - bool operator<(const charT * x, basic_string_ref y) { + inline bool operator<(const charT * x, basic_string_ref y) { return basic_string_ref(x) < y; } // Greater than template - bool operator>(basic_string_ref x, basic_string_ref y) { + inline bool operator>(basic_string_ref x, basic_string_ref y) { return x.compare(y) > 0; } template - bool operator>(basic_string_ref x, const std::basic_string & y) { + inline bool operator>(basic_string_ref x, const std::basic_string & y) { return x > basic_string_ref(y); } template - bool operator>(const std::basic_string & x, basic_string_ref y) { + inline bool operator>(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) > y; } template - bool operator>(basic_string_ref x, const charT * y) { + inline bool operator>(basic_string_ref x, const charT * y) { return x > basic_string_ref(y); } template - bool operator>(const charT * x, basic_string_ref y) { + inline bool operator>(const charT * x, basic_string_ref y) { return basic_string_ref(x) > y; } // Less than or equal to template - bool operator<=(basic_string_ref x, basic_string_ref y) { + inline bool operator<=(basic_string_ref x, basic_string_ref y) { return x.compare(y) <= 0; } template - bool operator<=(basic_string_ref x, const std::basic_string & y) { + inline bool operator<=(basic_string_ref x, const std::basic_string & y) { return x <= basic_string_ref(y); } template - bool operator<=(const std::basic_string & x, basic_string_ref y) { + inline bool operator<=(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) <= y; } template - bool operator<=(basic_string_ref x, const charT * y) { + inline bool operator<=(basic_string_ref x, const charT * y) { return x <= basic_string_ref(y); } template - bool operator<=(const charT * x, basic_string_ref y) { + inline bool operator<=(const charT * x, basic_string_ref y) { return basic_string_ref(x) <= y; } // Greater than or equal to template - bool operator>=(basic_string_ref x, basic_string_ref y) { + inline bool operator>=(basic_string_ref x, basic_string_ref y) { return x.compare(y) >= 0; } template - bool operator>=(basic_string_ref x, const std::basic_string & y) { + inline bool operator>=(basic_string_ref x, const std::basic_string & y) { return x >= basic_string_ref(y); } template - bool operator>=(const std::basic_string & x, basic_string_ref y) { + inline bool operator>=(const std::basic_string & x, basic_string_ref y) { return basic_string_ref(x) >= y; } template - bool operator>=(basic_string_ref x, const charT * y) { + inline bool operator>=(basic_string_ref x, const charT * y) { return x >= basic_string_ref(y); } template - bool operator>=(const charT * x, basic_string_ref y) { + inline bool operator>=(const charT * x, basic_string_ref y) { return basic_string_ref(x) >= y; } // Inserter template - std::basic_ostream& + inline std::basic_ostream& operator<<(std::basic_ostream& os, const basic_string_ref& str) { -#ifdef BOOST_NO_CXX11_RANGE_BASED_FOR - for ( typename basic_string_ref::const_iterator iter = str.begin (); iter != str.end (); ++iter ) - os << *iter; -#else - for ( charT x : str ) - os << x; -#endif + typename std::basic_ostream::sentry guard(os); + if (guard) { + const std::size_t size = str.size(); + const std::size_t w = static_cast< std::size_t >(os.width()); + os.width(0); + if (w <= size) + os.write(str.data(), size); + else { + const bool align_left = (os.flags() & std::basic_ostream::adjustfield) == std::basic_ostream::left; + const std::size_t alignment_size = w - size; + if (!align_left) { + const charT fill_char = os.fill(); + for (std::size_t i = 0; i < alignment_size && os.good(); ++i) + os.put(fill_char); + } + if (os.good()) + os.write(str.data(), size); + if (align_left && os.good()) { + const charT fill_char = os.fill(); + for (std::size_t i = 0; i < alignment_size && os.good(); ++i) + os.put(fill_char); + } + } + } return os; } @@ -436,67 +441,67 @@ namespace boost { // These are short-term implementations. // In a production environment, I would rather avoid the copying. // - int stoi (string_ref str, size_t* idx=0, int base=10) { + inline int stoi (string_ref str, size_t* idx=0, int base=10) { return std::stoi ( std::string(str), idx, base ); } - long stol (string_ref str, size_t* idx=0, int base=10) { + inline long stol (string_ref str, size_t* idx=0, int base=10) { return std::stol ( std::string(str), idx, base ); } - unsigned long stoul (string_ref str, size_t* idx=0, int base=10) { + inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) { return std::stoul ( std::string(str), idx, base ); } - long long stoll (string_ref str, size_t* idx=0, int base=10) { + inline long long stoll (string_ref str, size_t* idx=0, int base=10) { return std::stoll ( std::string(str), idx, base ); } - unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) { + inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) { return std::stoull ( std::string(str), idx, base ); } - float stof (string_ref str, size_t* idx=0) { + inline float stof (string_ref str, size_t* idx=0) { return std::stof ( std::string(str), idx ); } - double stod (string_ref str, size_t* idx=0) { + inline double stod (string_ref str, size_t* idx=0) { return std::stod ( std::string(str), idx ); } - long double stold (string_ref str, size_t* idx=0) { + inline long double stold (string_ref str, size_t* idx=0) { return std::stold ( std::string(str), idx ); } - int stoi (wstring_ref str, size_t* idx=0, int base=10) { + inline int stoi (wstring_ref str, size_t* idx=0, int base=10) { return std::stoi ( std::wstring(str), idx, base ); } - long stol (wstring_ref str, size_t* idx=0, int base=10) { + inline long stol (wstring_ref str, size_t* idx=0, int base=10) { return std::stol ( std::wstring(str), idx, base ); } - unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) { + inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) { return std::stoul ( std::wstring(str), idx, base ); } - long long stoll (wstring_ref str, size_t* idx=0, int base=10) { + inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) { return std::stoll ( std::wstring(str), idx, base ); } - unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) { + inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) { return std::stoull ( std::wstring(str), idx, base ); } - float stof (wstring_ref str, size_t* idx=0) { + inline float stof (wstring_ref str, size_t* idx=0) { return std::stof ( std::wstring(str), idx ); } - double stod (wstring_ref str, size_t* idx=0) { + inline double stod (wstring_ref str, size_t* idx=0) { return std::stod ( std::wstring(str), idx ); } - long double stold (wstring_ref str, size_t* idx=0) { + inline long double stold (wstring_ref str, size_t* idx=0) { return std::stold ( std::wstring(str), idx ); } #endif diff --git a/include/boost/utility/string_ref_fwd.hpp b/include/boost/utility/string_ref_fwd.hpp new file mode 100644 index 0000000..f58b98c --- /dev/null +++ b/include/boost/utility/string_ref_fwd.hpp @@ -0,0 +1,37 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + +*/ + +#ifndef BOOST_STRING_REF_FWD_HPP +#define BOOST_STRING_REF_FWD_HPP + +#include +#include + +namespace boost { + + template > class basic_string_ref; + typedef basic_string_ref > string_ref; + typedef basic_string_ref > wstring_ref; + +#ifndef BOOST_NO_CXX11_CHAR16_T + typedef basic_string_ref > u16string_ref; +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + typedef basic_string_ref > u32string_ref; +#endif + +} + +#endif From 547c562464bda840da7fb23c74386f1f13215894 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 26 May 2013 15:52:16 +0000 Subject: [PATCH 58/90] Minor change (no need to create a sentry, it will be created by the stream methods). [SVN r84513] --- include/boost/utility/string_ref.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index 1bab84c..8e804c5 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -408,8 +408,7 @@ namespace boost { template inline std::basic_ostream& operator<<(std::basic_ostream& os, const basic_string_ref& str) { - typename std::basic_ostream::sentry guard(os); - if (guard) { + if (os.good()) { const std::size_t size = str.size(); const std::size_t w = static_cast< std::size_t >(os.width()); os.width(0); From 71b501a0b090728c72d27f80675faba36ce9625d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 26 May 2013 19:23:52 +0000 Subject: [PATCH 59/90] Removed constexpr from substr() as it doesn't work with BOOST_THROW_EXCEPTION. Added a test for streaming. [SVN r84518] --- include/boost/utility/string_ref.hpp | 4 +- test/Jamfile.v2 | 1 + test/string_ref_test_io.cpp | 172 +++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 test/string_ref_test_io.cpp diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index 8e804c5..6611dac 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace boost { @@ -135,10 +136,7 @@ namespace boost { // basic_string_ref string operations - BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const { - // Looks like msvc 8 and 9 have a codegen bug when one branch of - // a conditional operator is a throw expression. -EAN 2012/12/04 if ( pos > size()) BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) ); if ( n == npos || pos + n > size()) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d597cb8..cec9727 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,6 +38,7 @@ test-suite utility [ run ../shared_iterator_test.cpp ] [ run string_ref_test1.cpp unit_test_framework ] [ run string_ref_test2.cpp unit_test_framework ] + [ run string_ref_test_io.cpp unit_test_framework ] [ run ../value_init_test.cpp ] [ run ../value_init_workaround_test.cpp ] [ run ../initialized_test.cpp ] diff --git a/test/string_ref_test_io.cpp b/test/string_ref_test_io.cpp new file mode 100644 index 0000000..d4a288d --- /dev/null +++ b/test/string_ref_test_io.cpp @@ -0,0 +1,172 @@ +/* + * Copyright Andrey Semashev 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 string_ref_test_io.cpp + * \author Andrey Semashev + * \date 26.05.2013 + * + * \brief This header contains tests for stream operations of \c basic_string_ref. + */ + +#define BOOST_TEST_MODULE string_ref_test_io + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef boost::mpl::vector< + char +#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) + , wchar_t +#endif +/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available. +#if !defined(BOOST_NO_CXX11_CHAR16_T) + , char16_t +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) + , char32_t +#endif +*/ +>::type char_types; + +static const char* test_strings[] = +{ + "begin", + "abcd", + "end" +}; + +//! The context with test data for particular character type +template< typename CharT > +struct context +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + + string_type begin, abcd, end; + + context() + { + boost::string_ref str = test_strings[0]; + std::copy(str.begin(), str.end(), std::back_inserter(begin)); + + str = test_strings[1]; + std::copy(str.begin(), str.end(), std::back_inserter(abcd)); + + str = test_strings[2]; + std::copy(str.begin(), str.end(), std::back_inserter(end)); + } +}; + +// Test regular output +BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types) +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm; + strm << string_ref_type(ctx.abcd); + BOOST_CHECK(strm.str() == ctx.abcd); +} + +// Test support for padding +BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types) +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Test for padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); + } + + // Test that short width does not truncate the string + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); + } +} + +// Test support for padding fill +BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types) +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm_ref; + strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); +} + +// Test support for alignment +BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types) +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Left alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); + } + + // Right alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); + } +} From f3bb2a493cdd73dd9ce777280d980d509205372a Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 2 Jun 2013 18:15:53 +0000 Subject: [PATCH 60/90] Modifications according to the review. [SVN r84609] --- include/boost/utility/string_ref.hpp | 53 ++++++++++++++++++---------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index 6611dac..febdabe 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -402,6 +402,37 @@ namespace boost { return basic_string_ref(x) >= y; } + namespace detail { + + template + inline void insert_fill_chars(std::basic_ostream& os, std::size_t n) { + charT fill_chars[8]; + std::fill_n(fill_chars, 8, os.fill()); + for (std::size_t m = n / 8u; m > 0 && os.good(); --m) + os.write(fill_chars, 8); + n &= 7u; + if (n > 0 && os.good()) + os.write(fill_chars, static_cast< std::streamsize >(n)); + } + + template + void insert_aligned(std::basic_ostream& os, const basic_string_ref& str) { + const std::size_t size = str.size(); + const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size; + const bool align_left = (os.flags() & std::ios_base::adjustfield) == std::ios_base::left; + if (!align_left) { + detail::insert_fill_chars(os, alignment_size); + if (os.good()) + os.write(str.data(), static_cast< std::streamsize >(size)); + } + else { + os.write(str.data(), static_cast< std::streamsize >(size)); + detail::insert_fill_chars(os, alignment_size); + } + } + + } // namespace detail + // Inserter template inline std::basic_ostream& @@ -409,25 +440,11 @@ namespace boost { if (os.good()) { const std::size_t size = str.size(); const std::size_t w = static_cast< std::size_t >(os.width()); - os.width(0); if (w <= size) - os.write(str.data(), size); - else { - const bool align_left = (os.flags() & std::basic_ostream::adjustfield) == std::basic_ostream::left; - const std::size_t alignment_size = w - size; - if (!align_left) { - const charT fill_char = os.fill(); - for (std::size_t i = 0; i < alignment_size && os.good(); ++i) - os.put(fill_char); - } - if (os.good()) - os.write(str.data(), size); - if (align_left && os.good()) { - const charT fill_char = os.fill(); - for (std::size_t i = 0; i < alignment_size && os.good(); ++i) - os.put(fill_char); - } - } + os.write(str.data(), static_cast< std::streamsize >(size)); + else + detail::insert_aligned(os, str); + os.width(0); } return os; } From d09b37d3ef8e978d214abcc819937abd33d18059 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 2 Jun 2013 19:16:50 +0000 Subject: [PATCH 61/90] More modifications according to the review. [SVN r84611] --- include/boost/utility/string_ref.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index febdabe..235ac50 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -406,11 +406,11 @@ namespace boost { template inline void insert_fill_chars(std::basic_ostream& os, std::size_t n) { - charT fill_chars[8]; - std::fill_n(fill_chars, 8, os.fill()); - for (std::size_t m = n / 8u; m > 0 && os.good(); --m) - os.write(fill_chars, 8); - n &= 7u; + enum { chunk_size = 8 }; + charT fill_chars[chunk_size]; + std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill()); + for (; n >= chunk_size && os.good(); n -= chunk_size) + os.write(fill_chars, static_cast< std::streamsize >(chunk_size)); if (n > 0 && os.good()) os.write(fill_chars, static_cast< std::streamsize >(n)); } @@ -427,7 +427,8 @@ namespace boost { } else { os.write(str.data(), static_cast< std::streamsize >(size)); - detail::insert_fill_chars(os, alignment_size); + if (os.good()) + detail::insert_fill_chars(os, alignment_size); } } From 9092b9277bc31172cc326c6c27a39e6a7536ea3d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 2 Jun 2013 20:00:04 +0000 Subject: [PATCH 62/90] Added a test for long padding. [SVN r84613] --- test/string_ref_test_io.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/string_ref_test_io.cpp b/test/string_ref_test_io.cpp index d4a288d..376f695 100644 --- a/test/string_ref_test_io.cpp +++ b/test/string_ref_test_io.cpp @@ -107,6 +107,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types) BOOST_CHECK(strm_ref.str() == strm_correct.str()); } + // Test for long padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; + + BOOST_CHECK(strm_ref.str() == strm_correct.str()); + } + // Test that short width does not truncate the string { ostream_type strm_ref; From 6bb1ce9b7bcf1826f01c4e2218943f26bd162350 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 4 Jun 2013 18:41:39 +0000 Subject: [PATCH 63/90] Avoid using ios_base and streamsize, which are not defined in iosfwd. [SVN r84636] --- include/boost/utility/string_ref.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/utility/string_ref.hpp b/include/boost/utility/string_ref.hpp index 235ac50..9018513 100644 --- a/include/boost/utility/string_ref.hpp +++ b/include/boost/utility/string_ref.hpp @@ -410,23 +410,23 @@ namespace boost { charT fill_chars[chunk_size]; std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill()); for (; n >= chunk_size && os.good(); n -= chunk_size) - os.write(fill_chars, static_cast< std::streamsize >(chunk_size)); + os.write(fill_chars, static_cast< std::size_t >(chunk_size)); if (n > 0 && os.good()) - os.write(fill_chars, static_cast< std::streamsize >(n)); + os.write(fill_chars, n); } template void insert_aligned(std::basic_ostream& os, const basic_string_ref& str) { const std::size_t size = str.size(); const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size; - const bool align_left = (os.flags() & std::ios_base::adjustfield) == std::ios_base::left; + const bool align_left = (os.flags() & std::basic_ostream::adjustfield) == std::basic_ostream::left; if (!align_left) { detail::insert_fill_chars(os, alignment_size); if (os.good()) - os.write(str.data(), static_cast< std::streamsize >(size)); + os.write(str.data(), size); } else { - os.write(str.data(), static_cast< std::streamsize >(size)); + os.write(str.data(), size); if (os.good()) detail::insert_fill_chars(os, alignment_size); } @@ -442,7 +442,7 @@ namespace boost { const std::size_t size = str.size(); const std::size_t w = static_cast< std::size_t >(os.width()); if (w <= size) - os.write(str.data(), static_cast< std::streamsize >(size)); + os.write(str.data(), size); else detail::insert_aligned(os, str); os.width(0); From 9baf33dd167e5bc62040b7bd1e86b4a00f2501df Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 7 Jun 2013 20:21:24 +0000 Subject: [PATCH 64/90] Optimized BOOST_ASSERT_MSG so that it is more lightweight and doesn't prevent enclosing functions from inlining. Also added branching hints for the checked conditions. [SVN r84682] --- include/boost/assert.hpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index c42ea4c..ccc776a 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -34,6 +34,7 @@ #elif defined(BOOST_ENABLE_ASSERT_HANDLER) +#include #include namespace boost @@ -42,7 +43,7 @@ namespace boost char const * function, char const * file, long line); // user defined } // namespace boost -#define BOOST_ASSERT(expr) ((expr) \ +#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr)) \ ? ((void)0) \ : ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) @@ -63,6 +64,7 @@ namespace boost #elif defined(BOOST_ENABLE_ASSERT_HANDLER) + #include #include namespace boost @@ -71,7 +73,7 @@ namespace boost char const * function, char const * file, long line); // user defined } // namespace boost - #define BOOST_ASSERT_MSG(expr, msg) ((expr) \ + #define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \ ? ((void)0) \ : ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) @@ -80,6 +82,7 @@ namespace boost #define BOOST_ASSERT_HPP #include #include + #include #include // IDE's like Visual Studio perform better if output goes to std::cout or @@ -94,26 +97,28 @@ namespace boost { namespace detail { - inline void assertion_failed_msg(char const * expr, char const * msg, char const * function, + // Note: The template is needed to make the function non-inline and avoid linking errors + template< typename CharT > + BOOST_NOINLINE void assertion_failed_msg(CharT const * expr, char const * msg, char const * function, char const * file, long line) { BOOST_ASSERT_MSG_OSTREAM << "***** Internal Program Error - assertion (" << expr << ") failed in " << function << ":\n" << file << '(' << line << "): " << msg << std::endl; - #ifdef UNDER_CE - // The Windows CE CRT library does not have abort() so use exit(-1) instead. - std::exit(-1); - #else - std::abort(); - #endif +#ifdef UNDER_CE + // The Windows CE CRT library does not have abort() so use exit(-1) instead. + std::exit(-1); +#else + std::abort(); +#endif } } // detail } // assertion } // detail #endif - #define BOOST_ASSERT_MSG(expr, msg) ((expr) \ + #define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr)) \ ? ((void)0) \ : ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \ BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) From 15021632dc7866e51ab8abebf197e6a93d8aaf75 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Wed, 3 Jul 2013 22:14:27 +0000 Subject: [PATCH 65/90] added new result_of mode that uses TR1 with a decltype fallback as suggested by Nathan Crookston; fixes #7753 [SVN r84949] --- .../utility/detail/result_of_iterate.hpp | 25 +++++++++--- include/boost/utility/result_of.hpp | 29 ++++++++++---- test/result_of_test.cpp | 12 ++++-- utility.htm | 40 +++++++++++++++++++ 4 files changed, 89 insertions(+), 17 deletions(-) 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/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/test/result_of_test.cpp b/test/result_of_test.cpp index d06ec64..6c60f99 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,7 +307,7 @@ 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) 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 From eca8d9f1efe2f8a4b8e3e4fd6fa067cd41ae98f8 Mon Sep 17 00:00:00 2001 From: Robert Kawulak Date: Tue, 13 Aug 2013 21:39:57 +0000 Subject: [PATCH 66/90] [utility] Fixes to value_init docs. [SVN r85335] --- value_init.htm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/value_init.htm b/value_init.htm index 4ae9177..b82792f 100644 --- a/value_init.htm +++ b/value_init.htm @@ -295,7 +295,7 @@ so for those compilers that need to have such a workaround, based on the
operator T&() { return x ; }
T const &data() const { return x ; }
T& data() { return x ; } -
void swap( value_initialized<T>& ); +
void swap( value_initialized& );

private :
unspecified x ; @@ -313,6 +313,12 @@ so for those compilers that need to have such a workaround, based on the
return x.data() ;
}
+
template<class T> +
void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs ) +
{ +
lhs.swap(rhs) ; +
} +

} // namespace boost

@@ -385,7 +391,7 @@ the wrapped object is always performed with the get() idiom:


operator T&();
T const &data() const;
T& data(); -
void swap( value_initialized<T>& ); +
void swap( initialized& );

private :
unspecified x ; @@ -397,6 +403,9 @@ the wrapped object is always performed with the get() idiom:


template<class T>
T& get ( initialized<T>& x );
+
template<class T> +
void swap ( initialized<T>& lhs, initialized<T>& rhs ); +

} // namespace boost
From 7ae5e14681ed92b7465f94e3c64f2a45d61f1247 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 1 Sep 2013 16:31:16 +0000 Subject: [PATCH 67/90] Extracted BOOST_EXPLICIT_OPERATOR_BOOL macro from Boost.Log. [SVN r85543] --- doc/Jamfile.v2 | 23 +++- doc/explicit_operator_bool.qbk | 68 ++++++++++ .../boost/utility/explicit_operator_bool.hpp | 128 ++++++++++++++++++ index.html | 1 + 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 ++++++ 10 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 doc/explicit_operator_bool.qbk 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/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/explicit_operator_bool.hpp b/include/boost/utility/explicit_operator_bool.hpp new file mode 100644 index 0000000..8843e0c --- /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) + + 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 is too eager to convert pointer to function to void* even though it 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/index.html b/index.html index d5b4884..00ff8f8 100644 --- a/index.html +++ b/index.html @@ -36,6 +36,7 @@ utility
string_ref
value_init + BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL


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; +} From 8e4054467eb25e69eb18447013f7a2ac46ac7a27 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 5 Sep 2013 08:28:24 +0000 Subject: [PATCH 68/90] Attempt to work around explicit_operator_bool_compile_fail_conv_pvoid test failure for VACPP. [SVN r85570] --- include/boost/utility/explicit_operator_bool.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/utility/explicit_operator_bool.hpp b/include/boost/utility/explicit_operator_bool.hpp index 8843e0c..650caff 100644 --- a/include/boost/utility/explicit_operator_bool.hpp +++ b/include/boost/utility/explicit_operator_bool.hpp @@ -64,7 +64,7 @@ namespace boost { namespace detail { -#if !defined(_MSC_VER) +#if !defined(_MSC_VER) && !defined(__IBMCPP__) struct unspecified_bool { @@ -78,7 +78,7 @@ namespace detail { #else - // MSVC is too eager to convert pointer to function to void* even though it shouldn't + // 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 From 9df000eece85da97d5e118bc72c29727ed1c2143 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Thu, 5 Sep 2013 18:25:41 +0000 Subject: [PATCH 69/90] Extracted empty_deleter to Boost.Utility. [SVN r85577] --- include/boost/utility/empty_deleter.hpp | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 include/boost/utility/empty_deleter.hpp 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_ From 497198c62455cc4e16d2752d196ecc000ac9ac48 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 8 Sep 2013 18:45:41 +0000 Subject: [PATCH 70/90] Made indents similar. [SVN r85611] --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 00ff8f8..41c8c15 100644 --- a/index.html +++ b/index.html @@ -22,11 +22,11 @@ checked_delete
compressed_pair
current_function
- declval
- enable_if
+ declval
+ enable_if
in_place_factory
- iterator_adaptors
- generator iterator adaptors
+ iterator_adaptors
+ generator iterator adaptors
next/prior
noncopyable
operators
From 0f5ae0e73c4dab7c133bbc66318b226b9f062c8e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 9 Sep 2013 18:43:27 +0000 Subject: [PATCH 71/90] Corrected comment. [SVN r85624] --- test/result_of_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 6c60f99..9ea72f1 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -310,7 +310,7 @@ int main() #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; } From bcd50e9105e8747ae1bae699358afe7b92fb3380 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 25 Sep 2013 10:29:44 +0000 Subject: [PATCH 72/90] Remove use of obsolete BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE{,_SPEC} macro. [SVN r85896] --- include/boost/utility/in_place_factory.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/utility/in_place_factory.hpp b/include/boost/utility/in_place_factory.hpp index f84b003..1a62ace 100644 --- a/include/boost/utility/in_place_factory.hpp +++ b/include/boost/utility/in_place_factory.hpp @@ -48,15 +48,13 @@ public: {} template - void* apply(void* address - BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const + void* apply(void* address) const { return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) ); } template - void* apply(void* address, std::size_t n - BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const + void* apply(void* address, std::size_t n) const { for(char* next = address = this->BOOST_NESTED_TEMPLATE apply(address); !! --n;) From fc4bc227b52a3fbd4c5d972d3eaae252bda591e1 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Sep 2013 09:41:00 +0000 Subject: [PATCH 73/90] Utility: Remove obsolete MSVC version check [SVN r85932] --- include/boost/utility/value_init.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index 5de9585..2e43287 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -33,7 +33,6 @@ #ifdef BOOST_MSVC #pragma warning(push) -#if _MSC_VER >= 1310 // It is safe to ignore the following warning from MSVC 7.1 or higher: // "warning C4351: new behavior: elements of array will be default initialized" #pragma warning(disable: 4351) @@ -41,7 +40,6 @@ // a const type: "warning C4512: assignment operator could not be generated". #pragma warning(disable: 4512) #endif -#endif #ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED From 1fd5883b345a3c230daaad8ee93af5bc8f3209d5 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 26 Sep 2013 13:02:51 +0000 Subject: [PATCH 74/90] Remove obsolete MSVC check from pragma guard git grep -h -B1 "^#\s*pragma once" | grep -v pragma | sort | uniq is now clean. [SVN r85952] --- include/boost/checked_delete.hpp | 2 +- include/boost/current_function.hpp | 2 +- include/boost/ref.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/checked_delete.hpp b/include/boost/checked_delete.hpp index 9bb84e8..80f936a 100644 --- a/include/boost/checked_delete.hpp +++ b/include/boost/checked_delete.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp index cb36e35..2904789 100644 --- a/include/boost/current_function.hpp +++ b/include/boost/current_function.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp index 6058d69..90d033c 100644 --- a/include/boost/ref.hpp +++ b/include/boost/ref.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#if defined(_MSC_VER) # pragma once #endif From adf57817ec09cb8edd6032a30da6daec3edbe23f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 00:19:48 +0000 Subject: [PATCH 75/90] Ref: Remove obsolete MSVC version check. [SVN r86031] --- include/boost/ref.hpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp index 90d033c..cf68764 100644 --- a/include/boost/ref.hpp +++ b/include/boost/ref.hpp @@ -34,16 +34,8 @@ template class reference_wrapper public: typedef T type; -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - - explicit reference_wrapper(T& t): t_(&t) {} - -#else - explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} -#endif - operator T& () const { return *t_; } T& get() const { return *t_; } From 3d1646cf51d1b8c34981a2cdc397b942c478b2ad Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 00:21:39 +0000 Subject: [PATCH 76/90] Detail: Remove obsolete MSVC version checks. [SVN r86039] --- include/boost/detail/ob_compressed_pair.hpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp index 727acab..326e454 100644 --- a/include/boost/detail/ob_compressed_pair.hpp +++ b/include/boost/detail/ob_compressed_pair.hpp @@ -167,17 +167,6 @@ public: compressed_pair_1(const ::boost::compressed_pair& x) : T2(x.second()), _first(x.first()) {} -#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 - // Total weirdness. If the assignment to _first is moved after - // the call to the inherited operator=, then this breaks graph/test/graph.cpp - // by way of iterator_adaptor. - compressed_pair_1& operator=(const compressed_pair_1& x) { - _first = x._first; - T2::operator=(x); - return *this; - } -#endif - first_reference first() { return _first; } first_const_reference first() const { return _first; } From 4dc965909729ad0d7e1c669bbc4383d33ebe97c9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 30 Sep 2013 00:36:13 +0000 Subject: [PATCH 77/90] Remove check for obsolete DMC version. [SVN r86043] --- include/boost/current_function.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp index 2904789..7b0d918 100644 --- a/include/boost/current_function.hpp +++ b/include/boost/current_function.hpp @@ -28,11 +28,7 @@ namespace detail inline void current_function_helper() { -#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) - -# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ - -#elif defined(__DMC__) && (__DMC__ >= 0x810) +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) || defined(__DMC__) # define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ From 37c8f45edc124b7228172337fae0705003a4ec43 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 1 Oct 2013 08:47:11 +0000 Subject: [PATCH 78/90] Operators: Remove obsolete GCC version check. [SVN r86114] --- include/boost/operators.hpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index b524cee..ac3eaff 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -97,14 +97,7 @@ namespace boost { namespace detail { -template class empty_base { - -// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0 -#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0 - bool dummy; -#endif - -}; +template class empty_base {}; } // namespace detail } // namespace boost From b39e4e5aea333a541013be3327e89133232a4245 Mon Sep 17 00:00:00 2001 From: Joel Falcou Date: Tue, 1 Oct 2013 15:02:28 +0000 Subject: [PATCH 79/90] Fix #9169 - Add BOOST_FORCEINLINE on boost::ref for performance issue [SVN r86124] --- include/boost/ref.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp index cf68764..cd186f9 100644 --- a/include/boost/ref.hpp +++ b/include/boost/ref.hpp @@ -30,17 +30,17 @@ namespace boost { template class reference_wrapper -{ +{ public: typedef T type; - explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} + BOOST_FORCEINLINE explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} - operator T& () const { return *t_; } + BOOST_FORCEINLINE operator T& () const { return *t_; } - T& get() const { return *t_; } + BOOST_FORCEINLINE T& get() const { return *t_; } - T* get_pointer() const { return t_; } + BOOST_FORCEINLINE T* get_pointer() const { return t_; } private: @@ -53,12 +53,12 @@ private: # define BOOST_REF_CONST const # endif -template inline reference_wrapper BOOST_REF_CONST ref(T & t) -{ +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref(T & t) +{ return reference_wrapper(t); } -template inline reference_wrapper BOOST_REF_CONST cref(T const & t) +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref(T const & t) { return reference_wrapper(t); } @@ -117,7 +117,7 @@ namespace detail { typedef char (&yes_reference_wrapper_t)[1]; typedef char (&no_reference_wrapper_t)[2]; - + no_reference_wrapper_t is_reference_wrapper_test(...); template @@ -152,7 +152,7 @@ class is_reference_wrapper bool, value = ( sizeof(detail::is_reference_wrapper_test(type())) == sizeof(detail::yes_reference_wrapper_t))); - + typedef ::boost::mpl::bool_ type; }; @@ -165,13 +165,13 @@ class unwrap_reference # endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template inline typename unwrap_reference::type& +template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref(T& t) { return t; } -template inline T* get_pointer( reference_wrapper const & r ) +template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) { return r.get_pointer(); } From a90bc68a7f8b304a1eab357a76d2b24579f5c3fa Mon Sep 17 00:00:00 2001 From: Joel Falcou Date: Tue, 1 Oct 2013 15:05:39 +0000 Subject: [PATCH 80/90] Fix #9170 - Add BOOST_FORCEINLINE in address_of for performance issues [SVN r86125] --- include/boost/utility/addressof.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/boost/utility/addressof.hpp b/include/boost/utility/addressof.hpp index ecb7776..2b637df 100644 --- a/include/boost/utility/addressof.hpp +++ b/include/boost/utility/addressof.hpp @@ -25,8 +25,8 @@ template struct addr_impl_ref { T & v_; - inline addr_impl_ref( T & v ): v_( v ) {} - inline operator T& () const { return v_; } + BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {} + BOOST_FORCEINLINE operator T& () const { return v_; } private: addr_impl_ref & operator=(const addr_impl_ref &); @@ -34,13 +34,13 @@ private: template struct addressof_impl { - static inline T * f( T & v, long ) + static BOOST_FORCEINLINE T * f( T & v, long ) { return reinterpret_cast( &const_cast(reinterpret_cast(v))); } - static inline T * f( T * v, int ) + static BOOST_FORCEINLINE T * f( T * v, int ) { return v; } @@ -48,7 +48,9 @@ template struct addressof_impl } // namespace detail -template T * addressof( T & v ) +template +BOOST_FORCEINLINE +T * addressof( T & v ) { #if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC ) @@ -74,6 +76,7 @@ template struct addressof_addp } // namespace detail template< class T, std::size_t N > +BOOST_FORCEINLINE typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) { return &t; @@ -85,12 +88,14 @@ typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] ) // but these overloads work around the problem. #if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) template +BOOST_FORCEINLINE T (*addressof(T (&t)[N]))[N] { return reinterpret_cast(&t); } template +BOOST_FORCEINLINE const T (*addressof(const T (&t)[N]))[N] { return reinterpret_cast(&t); From e97577a0aef904f10ad39594e8f6c1c0dde6387f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:11:35 +0000 Subject: [PATCH 81/90] Remove obsolete files. [SVN r86242] --- include/boost/call_traits.hpp | 6 +- include/boost/compressed_pair.hpp | 6 +- include/boost/detail/ob_call_traits.hpp | 168 ------------------------ 3 files changed, 2 insertions(+), 178 deletions(-) delete mode 100644 include/boost/detail/ob_call_traits.hpp diff --git a/include/boost/call_traits.hpp b/include/boost/call_traits.hpp index 5253a6d..2c1328e 100644 --- a/include/boost/call_traits.hpp +++ b/include/boost/call_traits.hpp @@ -5,7 +5,7 @@ // // See http://www.boost.org/libs/utility for most recent version including documentation. -// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp +// See boost/detail/call_traits.hpp // for full copyright notices. #ifndef BOOST_CALL_TRAITS_HPP @@ -15,10 +15,6 @@ #include #endif -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else #include -#endif #endif // BOOST_CALL_TRAITS_HPP diff --git a/include/boost/compressed_pair.hpp b/include/boost/compressed_pair.hpp index e6cd6a0..a7be0f2 100644 --- a/include/boost/compressed_pair.hpp +++ b/include/boost/compressed_pair.hpp @@ -5,7 +5,7 @@ // // See http://www.boost.org/libs/utility for most recent version including documentation. -// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp +// See boost/detail/compressed_pair.hpp // for full copyright notices. #ifndef BOOST_COMPRESSED_PAIR_HPP @@ -15,10 +15,6 @@ #include #endif -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else #include -#endif #endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/include/boost/detail/ob_call_traits.hpp b/include/boost/detail/ob_call_traits.hpp deleted file mode 100644 index eb4df7a..0000000 --- a/include/boost/detail/ob_call_traits.hpp +++ /dev/null @@ -1,168 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). -// -// See http://www.boost.org/libs/utility for most recent version including documentation. -// -// Crippled version for crippled compilers: -// see libs/utility/call_traits.htm -// - -/* Release notes: - 01st October 2000: - Fixed call_traits on VC6, using "poor man's partial specialisation", - using ideas taken from "Generative programming" by Krzysztof Czarnecki - & Ulrich Eisenecker. -*/ - -#ifndef BOOST_OB_CALL_TRAITS_HPP -#define BOOST_OB_CALL_TRAITS_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP -#include -#endif - -namespace boost{ - -#ifdef BOOST_MSVC6_MEMBER_TEMPLATES -// -// use member templates to emulate -// partial specialisation: -// -namespace detail{ - -template -struct standard_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; -template -struct simple_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T param_type; -}; -template -struct reference_call_traits -{ - typedef T value_type; - typedef T reference; - typedef T const_reference; - typedef T param_type; -}; - -template -struct call_traits_chooser -{ - template - struct rebind - { - typedef standard_call_traits type; - }; -}; - -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef simple_call_traits type; - }; -}; - -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef reference_call_traits type; - }; -}; - -template -struct call_traits_sizeof_chooser2 -{ - template - struct small_rebind - { - typedef simple_call_traits small_type; - }; -}; - -template<> -struct call_traits_sizeof_chooser2 -{ - template - struct small_rebind - { - typedef standard_call_traits small_type; - }; -}; - -template <> -struct call_traits_chooser -{ - template - struct rebind - { - enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) }; - typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser; - typedef typename chooser::template small_rebind bound_type; - typedef typename bound_type::small_type type; - }; -}; - -} // namespace detail -template -struct call_traits -{ -private: - typedef detail::call_traits_chooser< - ::boost::is_pointer::value, - ::boost::is_arithmetic::value, - ::boost::is_reference::value - > chooser; - typedef typename chooser::template rebind bound_type; - typedef typename bound_type::type call_traits_type; -public: - typedef typename call_traits_type::value_type value_type; - typedef typename call_traits_type::reference reference; - typedef typename call_traits_type::const_reference const_reference; - typedef typename call_traits_type::param_type param_type; -}; - -#else -// -// sorry call_traits is completely non-functional -// blame your broken compiler: -// - -template -struct call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; - -#endif // member templates - -} - -#endif // BOOST_OB_CALL_TRAITS_HPP From 468fb2dd5f40581110f374f51d8ac46f4848d93b Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:17:48 +0000 Subject: [PATCH 82/90] Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION Process #ifndef...#else...#endif blocks. [SVN r86245] --- include/boost/operators.hpp | 23 -------------- include/boost/ref.hpp | 61 ------------------------------------- 2 files changed, 84 deletions(-) diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp index ac3eaff..82c374e 100644 --- a/include/boost/operators.hpp +++ b/include/boost/operators.hpp @@ -704,7 +704,6 @@ struct random_access_iteratable // the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as // necessary. // -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION // is_chained_base<> - a traits class used to distinguish whether an operator // template argument is being used for base class chaining, or is specifying a @@ -802,24 +801,6 @@ BOOST_OPERATOR_TEMPLATE2(template_name##2) \ BOOST_OPERATOR_TEMPLATE1(template_name##1) -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -# define BOOST_OPERATOR_TEMPLATE4(template_name4) \ - BOOST_IMPORT_TEMPLATE4(template_name4) -# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ - BOOST_IMPORT_TEMPLATE3(template_name3) -# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ - BOOST_IMPORT_TEMPLATE2(template_name2) -# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ - BOOST_IMPORT_TEMPLATE1(template_name1) - - // In this case we can only assume that template_name<> is equivalent to the - // more commonly needed template_name1<> form. -# define BOOST_OPERATOR_TEMPLATE(template_name) \ - template > \ - struct template_name : template_name##1 {}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION namespace boost { @@ -890,14 +871,10 @@ struct operators2 , bitwise2 > > {}; -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template struct operators : operators2 {}; template struct operators -#else -template struct operators -#endif : totally_ordered BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST # undef BOOST_REF_CONST -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template class is_reference_wrapper @@ -104,66 +103,6 @@ AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper const volatile) # undef AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF -# else // no partial specialization - -} // namespace boost - -#include - -namespace boost -{ - -namespace detail -{ - typedef char (&yes_reference_wrapper_t)[1]; - typedef char (&no_reference_wrapper_t)[2]; - - no_reference_wrapper_t is_reference_wrapper_test(...); - - template - yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper >); - - template - struct reference_unwrapper - { - template - struct apply - { - typedef T type; - }; - }; - - template<> - struct reference_unwrapper - { - template - struct apply - { - typedef typename T::type type; - }; - }; -} - -template -class is_reference_wrapper -{ - public: - BOOST_STATIC_CONSTANT( - bool, value = ( - sizeof(detail::is_reference_wrapper_test(type())) - == sizeof(detail::yes_reference_wrapper_t))); - - typedef ::boost::mpl::bool_ type; -}; - -template -class unwrap_reference - : public detail::reference_unwrapper< - is_reference_wrapper::value - >::template apply -{}; - -# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref(T& t) From 03047e3f00c77a1b22c86dec87773936bea109f1 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 11 Oct 2013 23:20:59 +0000 Subject: [PATCH 83/90] Simplify multi-component ifdefs containing BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION [SVN r86248] --- include/boost/utility/result_of.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index a530c3a..9ea151d 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -68,7 +68,7 @@ namespace boost { template struct result_of; template struct tr1_result_of; // a TR1-style implementation of result_of -#if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +#if !defined(BOOST_NO_SFINAE) namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) From 12d17bc26d0a949681ea5f65af6d08fb0078342f Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Fri, 25 Oct 2013 02:46:04 +0000 Subject: [PATCH 84/90] Fixed duplicate anchors [SVN r86423] --- enable_if.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/enable_if.html b/enable_if.html index 8ea33bb..9988f3a 100644 --- a/enable_if.html +++ b/enable_if.html @@ -201,7 +201,7 @@ extra template parameter. -

3.1  Enabling function templates in C++0x

+

3.1  Enabling function templates in C++0x

In a compiler which supports C++0x default arguments for function template parameters, you can enable and disable function templates by adding an additional template parameter. This approach @@ -416,7 +416,7 @@ subscript operators). -

4  Acknowledgements

+

4  Acknowledgements

We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard Smith whose findings have influenced the library.
From d5e86bb576f3db3e16dbcac82f4546d3315b0033 Mon Sep 17 00:00:00 2001 From: Michel Morin Date: Wed, 30 Oct 2013 12:51:24 +0000 Subject: [PATCH 85/90] Correct broken links to C++ standard papers. Refs #9212. [SVN r86524] --- utility.htm | 2 +- value_init.htm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/utility.htm b/utility.htm index 1101cc6..5635d48 100644 --- a/utility.htm +++ b/utility.htm @@ -313,7 +313,7 @@ typedef boost::result_of< Technical Report, N1836, or, for motivation and design rationale, - the result_of proposal.

+ the result_of proposal.

Usage guidelines for boost::result_of

diff --git a/value_init.htm b/value_init.htm index b82792f..3222f69 100644 --- a/value_init.htm +++ b/value_init.htm @@ -159,10 +159,10 @@ the object shall be value-initialized (but see below). However, if a declara

value-initialization

The first Technical + href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html">Technical Corrigendum for the C++ Standard (TC1), whose draft was released to the public in November 2001, introduced Core + href="http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core Issue 178 (among many other issues, of course).

That issue introduced the new concept of value-initialization From dfad2950eac8067cdcba34e595051f5c7fc2d5a9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 17 Nov 2013 17:13:08 +0000 Subject: [PATCH 86/90] Add BOOST_EXPLICIT_OPERATOR_BOOL documentation. [SVN r86739] --- doc/html/explicit_operator_bool.html | 115 +++++++++++++++++++++++++++ index.html | 4 +- 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 doc/html/explicit_operator_bool.html diff --git a/doc/html/explicit_operator_bool.html b/doc/html/explicit_operator_bool.html new file mode 100644 index 0000000..78a844f --- /dev/null +++ b/doc/html/explicit_operator_bool.html @@ -0,0 +1,115 @@ + + + +BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+


+
+
+
+
+

+BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL

+

+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) +

+
+
+
+
+
+

Table of Contents

+
+
Overview
+
Examples
+
History
+
+
+
+ +

+ 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 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. +

+
+
+ +

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

+ + boost + 1.55 +

+
  • + The macro was extracted from Boost.Log. +
+
+
+ + + +

Last revised: November 17, 2013 at 17:08:52 GMT

+
+
+ + diff --git a/index.html b/index.html index 41c8c15..98c82f1 100644 --- a/index.html +++ b/index.html @@ -35,8 +35,8 @@ throw_exception
utility
string_ref
- value_init - BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL
+ value_init
+ BOOST_EXPLICIT_OPERATOR_BOOL and BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL


From ad98ca9c3c5d7b39c1217f22064593d4ff7b1956 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sat, 23 Nov 2013 14:14:01 +0000 Subject: [PATCH 87/90] Rebuild some of the utility documentation. [SVN r86796] --- doc/html/declval.html | 52 +++++++++++++++++++++------------------- doc/html/string_ref.html | 24 +++++++++---------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/doc/html/declval.html b/doc/html/declval.html index 7791057..305cf36 100644 --- a/doc/html/declval.html +++ b/doc/html/declval.html @@ -3,7 +3,7 @@ Declval - + @@ -31,9 +31,10 @@
-
+
-

+

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)

@@ -43,13 +44,13 @@

Table of Contents

-
+
Overview
Reference
History
-
+
@@ -66,13 +67,13 @@ in a non-using context, e.g. given the declaration

template<class T>
-T&& declval(); // not used
-
+T&& declval(); // not used +

as part of the function template declaration

template<class To, class From>
-decltype(static_cast<To>(declval<From>())) convert(From&&);
+decltype(static_cast<To>(declval<From>())) convert(From&&);
 

or as part of a class template definition @@ -80,9 +81,9 @@

template<class> class result_of;
 
 template<class Fn, class... ArgTypes>
-struct result_of<Fn(ArgTypes...)> 
+struct result_of<Fn(ArgTypes...)>
 {
-  typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
+  typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
 };
 

@@ -94,8 +95,8 @@ to

template<class T>
-typename std::add_rvalue_reference<T>::type declval(); // not used
-
+typename std::add_rvalue_reference<T>::type declval(); // not used +

which ensures that we can also use cv void as template parameter. The careful reader might have noticed that declval() already exists under the name create() as @@ -109,7 +110,7 @@ is expected to be part of the daily tool-box of the C++0x programmer.

-
+
@@ -119,10 +120,10 @@
namespace boost {
 
     template <typename T>
-    typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
-
-}  // namespace boost
-
+ typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand + +} // namespace boost +

The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands. @@ -142,32 +143,33 @@ Example:

template <class To, class From>
-decltype(static_cast<To>(declval<From>())) convert(From&&);
+decltype(static_cast<To>(declval<From>())) convert(From&&);
 

Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.

-
+
-

- - boost 1.50 +

+ + boost + 1.50

- New Features: + Fixes:

-
  • +
    • #6570 Adding noexcept to boost::declval.
- +

Last revised: March 25, 2012 at 18:26:23 GMT

Last revised: November 23, 2013 at 14:11:12 GMT


diff --git a/doc/html/string_ref.html b/doc/html/string_ref.html index 0b8a9d1..3352614 100644 --- a/doc/html/string_ref.html +++ b/doc/html/string_ref.html @@ -3,7 +3,7 @@ String_Ref - + @@ -37,14 +37,14 @@

Table of Contents

-
+
Overview
Examples
Reference
History
-
+
@@ -115,7 +115,7 @@ string_ref does.

-
+
@@ -130,7 +130,7 @@ return bar.substr ( 2, 3 ); } -if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } +if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }

Let's figure out what happens in this (contrived) example. @@ -166,15 +166,15 @@ copied, but those are cheap operations.

-
+

The header file "string_ref.hpp" defines a template boost::basic_string_ref, and four specializations - for char - / wchar_t / char16_t - / char32_t . + / wchar_t / char16_t + / char32_t .

#include <boost/utility/string_ref.hpp> @@ -256,22 +256,22 @@ bool ends_with(basic_string_ref x) const ;

-
+

- boost + boost 1.53

-
  • +
    • Introduced
- +

Last revised: January 14, 2013 at 16:24:14 GMT

Last revised: November 23, 2013 at 14:12:56 GMT


From 244c343efef4c10ab02782616e8d29722c811bbc Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 11 Dec 2013 00:13:48 +0200 Subject: [PATCH 88/90] Revert "Remove obsolete MSVC check from pragma guard" This reverts commit 1fd5883b345a3c230daaad8ee93af5bc8f3209d5. --- include/boost/checked_delete.hpp | 2 +- include/boost/current_function.hpp | 2 +- include/boost/ref.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/checked_delete.hpp b/include/boost/checked_delete.hpp index 80f936a..9bb84e8 100644 --- a/include/boost/checked_delete.hpp +++ b/include/boost/checked_delete.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp index 7b0d918..a135881 100644 --- a/include/boost/current_function.hpp +++ b/include/boost/current_function.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp index eae86f8..e31b167 100644 --- a/include/boost/ref.hpp +++ b/include/boost/ref.hpp @@ -3,7 +3,7 @@ // MS compatible compilers support #pragma once -#if defined(_MSC_VER) +#if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif From f90812f1d928e8dbaffafb5a400e1e031f3556bd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 11 Dec 2013 00:18:49 +0200 Subject: [PATCH 89/90] Revert "Remove check for obsolete DMC version." This reverts commit 4dc965909729ad0d7e1c669bbc4383d33ebe97c9. --- include/boost/current_function.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp index a135881..cb36e35 100644 --- a/include/boost/current_function.hpp +++ b/include/boost/current_function.hpp @@ -28,7 +28,11 @@ namespace detail inline void current_function_helper() { -#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) || defined(__DMC__) +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__) + +# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ + +#elif defined(__DMC__) && (__DMC__ >= 0x810) # define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ From 79d9d9f5141ae77d20aaa963dd89839516ad4ffb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 11 Dec 2013 00:46:10 +0200 Subject: [PATCH 90/90] Revert "Ref: Remove obsolete MSVC version check." This reverts commit adf57817ec09cb8edd6032a30da6daec3edbe23f. Conflicts: include/boost/ref.hpp --- include/boost/ref.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp index e31b167..8169149 100644 --- a/include/boost/ref.hpp +++ b/include/boost/ref.hpp @@ -34,8 +34,16 @@ template class reference_wrapper public: typedef T type; +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) + + explicit reference_wrapper(T& t): t_(&t) {} + +#else + BOOST_FORCEINLINE explicit reference_wrapper(T& t): t_(boost::addressof(t)) {} +#endif + BOOST_FORCEINLINE operator T& () const { return *t_; } BOOST_FORCEINLINE T& get() const { return *t_; }