From d6cb9a9176294bf42507cfe062ba97d799b11966 Mon Sep 17 00:00:00 2001
From: Lorenzo Caminiti
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
Consider the following macro which declares a variable named var
n 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)
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).
// In header: <boost/utility/identity_type.hpp>
-BOOST_IDENTITY_TYPE(parenthesized_type)
Parameters:
parenthesized_type | The 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)
Parameters:
parenthesized_type | The 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
- Consider the following macro which declares a variable named var
n with the specified
- type (see also var_error.cpp
):
+ Consider the following macro which declares a variable named var
n
+ 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 arg
n
- with the specified type (see also template.cpp
):
+ a function parameter named arg
n
+ 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 functionf<char>(a)
. In fact, + However, note that the template parameterchar
+ must be manually specified when invoking the functionf<char>(a)
. In fact, when theBOOST_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 inf(a)
. (This - limitation does not apply to class templates because class template parameters - must always be explicitly specified.) In other words, without using theBOOST_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 inf(a)
. [2] (This limitation does not apply to class templates because class + template parameters must always be explicitly specified.) In other words, without + using theBOOST_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 forBOOST_MPL_ASSERT
+ within the user macro definition might provide the best syntax for the user. + For example, this is the case forBOOST_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 usingBOOST_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).
Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas.
BOOST_IDENTITY_TYPE(parenthesized_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).
// In header: <boost/utility/identity_type.hpp>
-BOOST_IDENTITY_TYPE(parenthesized_type)
Parameters:
parenthesized_type | The 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)
Parameters:
parenthesized_type | The 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
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) -
Table of Contents
Table of Contents
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: +
-std=c++0x
) on
+ Cygwin.
+ + 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)
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).
// In header: <boost/utility/identity_type.hpp>
-BOOST_IDENTITY_TYPE(parenthesized_type)
Parameters:
parenthesized_type | The 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)
Parameters:
parenthesized_type | The 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
Copyright © 2008 Howard Hinnant
Copyright © 2008 Beman Dawes
Copyright © 2009, 2010 Vicente J. Botet Escriba
Copyright © 2009 -2012 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 @@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.
+ New Features: +
+Last revised: April 06, 2011 at 20:06:10 GMT |
+Last revised: March 25, 2012 at 18:26:23 GMT |
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) -
Table of Contents
Table of Contents
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: -
-std=c++0x
) on
- Cygwin.
- - 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)
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).
// In header: <boost/utility/identity_type.hpp>
-BOOST_IDENTITY_TYPE(parenthesized_type)
Parameters:
parenthesized_type | The 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)
Parameters:
parenthesized_type | The 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.