Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76687 - in sandbox/local_function/libs/utility/identity_type/doc: . html
From: lorcaminiti_at_[hidden]
Date: 2012-01-25 16:38:09


Author: lcaminiti
Date: 2012-01-25 16:38:05 EST (Wed, 25 Jan 2012)
New Revision: 76687
URL: http://svn.boost.org/trac/boost/changeset/76687

Log:
Docs.
Removed:
   sandbox/local_function/libs/utility/identity_type/doc/html/
Text files modified:
   sandbox/local_function/libs/utility/identity_type/doc/Jamfile.v2 | 37 +++++------
   sandbox/local_function/libs/utility/identity_type/doc/identity_type.qbk | 124 ++++++++++++++++++++++++++++++---------
   2 files changed, 113 insertions(+), 48 deletions(-)

Modified: sandbox/local_function/libs/utility/identity_type/doc/Jamfile.v2
==============================================================================
--- sandbox/local_function/libs/utility/identity_type/doc/Jamfile.v2 (original)
+++ sandbox/local_function/libs/utility/identity_type/doc/Jamfile.v2 2012-01-25 16:38:05 EST (Wed, 25 Jan 2012)
@@ -7,26 +7,23 @@
 import quickbook ;
 using boostbook ;
 
-doxygen reference :
- ../../../../boost/utility/identity_type.hpp
- :
- <reftitle>"Reference"
- <doxygen:param>PREDEFINED="DOXYGEN"
- <doxygen:param>QUIET=YES
- <doxygen:param>WARN_IF_UNDOCUMENTED=NO
- <doxygen:param>HIDE_UNDOC_MEMBERS=YES
- <doxygen:param>HIDE_UNDOC_CLASSES=YES
- <doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{1}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\1</link>\\endxmlonly\" RefSectId{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
-;
+doxygen reference : ../../../../boost/utility/identity_type.hpp
+ : <reftitle>"Reference"
+ <doxygen:param>PREDEFINED="DOXYGEN"
+ <doxygen:param>QUIET=YES
+ <doxygen:param>WARN_IF_UNDOCUMENTED=NO
+ <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+ <doxygen:param>HIDE_UNDOC_CLASSES=YES
+ <doxygen:param>ALIASES=" Params=\"<b>Parameters:</b> <table border="0">\" Param{2}=\"<tr><td><b><tt>\\1</tt></b></td><td>\\2</td></tr>\" EndParams=\"</table>\" Returns=\"<b>Returns:</b>\" Note=\"<b>Note:</b>\" Warning=\"<b>Warning:</b>\" See=\"<b>See:</b>\" RefSect{1}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\1</link>\\endxmlonly\" RefSectId{2}=\"\\xmlonly<link linkend='boost_utility_identitytype.\\1'>\\2</link>\\endxmlonly\" RefClass{1}=\"\\xmlonly<computeroutput><classname alt='\\1'>\\1</classname></computeroutput>\\endxmlonly\" RefFunc{1}=\"\\xmlonly<computeroutput><functionname alt='\\1'>\\1</functionname></computeroutput>\\endxmlonly\" RefMacro{1}=\"\\xmlonly<computeroutput><macroname alt='\\1'>\\1</macroname></computeroutput>\\endxmlonly\" "
+ ;
 
-xml doc : identity_type.qbk :
- <format>onehtml
- <dependency>reference
-;
+xml index : identity_type.qbk : <dependency>reference ;
 
-boostbook standalone : doc :
- <xsl:param>boost.root=../../../../..
- <xsl:param>boost.defaults=Boost
- <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/scope_exit/doc/html
-;
+boostbook standalone : index
+ : <location>html
+ <format>onehtml
+ <xsl:param>toc.section.depth=0
+ <xsl:param>html.stylesheet=../../../../../doc/src/boostbook.css
+ <xsl:param>boost.root=../../../../..
+ ;
 

Modified: sandbox/local_function/libs/utility/identity_type/doc/identity_type.qbk
==============================================================================
--- sandbox/local_function/libs/utility/identity_type/doc/identity_type.qbk (original)
+++ sandbox/local_function/libs/utility/identity_type/doc/identity_type.qbk 2012-01-25 16:38:05 EST (Wed, 25 Jan 2012)
@@ -5,26 +5,28 @@
     [copyright 2009-2012 Lorenzo Caminiti]
     [purpose wraps types with round parenthesis]
     [license
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or a copy at
+ 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])
     ]
     [authors [Caminiti <email>lorcaminiti_at_[hidden]</email>, Lorenzo]]
     [category Utilities]
 ]
 
-This library allows to wrap type expressions within round parenthesis so they can be passed as macro parameters even if they contain commas.
+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_ok.cpp]
+[import ../test/template.cpp]
+[import ../test/tmp_assert.cpp]
 
-[section Introduction]
+[section Motivation]
 
-Consider the following macro which declares a variable named `var_`/postfix/ with the specified /type/:
+Consider the following macro which declares a variable named `var`/n/ with the specified /type/ (see also [@../../test/var_err.cpp =var_err.cpp=]):
 
-[test_var_err]
+[var_err]
 
-The first macro invocation works correctly declaring a variable name `var_a` of type `int`.
+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:
 
 [pre
@@ -32,53 +34,119 @@
 ]
 
 That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`.
-The preprocessor interprets that unwrapped comma as separation between macro parameters concluding that a of three (and not two) parameters are passed to the macro in the following order:
+The preprocessor interprets that unwrapped comma as separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order:
 
-# `std::map<char`
-# `int>`
+# `std::map<int`
+# `char>`
 # `2`
 
 Note that, differently from the compiler, the preprocessor only recognizes round parameters `()`.
-Therefore angular `<>` or squared `[]` parenthesis are not detected by the preprocessor (as shown by the example above) when parsing the macro parameters.
+Angular `<>` or squared `[]` parenthesis are not used by the preprocessor in parsing the macro parameters.
 
-This library defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround this issue:
-
-[test_var_ok]
+[endsect]
 
-This macro works on any __CPP03__ compilers (it does not require __variadic_macro__ support)
+[section Solution]
 
-[endsect]
+In some cases, it might be possible to workaround the issue above 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_ok.cpp =var_ok.cpp=]):
 
-[section Tutorial]
+[var_typedef]
 
-The macro defined by this library allows to pass type expressions that contain unwrapped commas as a single macro parameter.
-For example (see also [@../../../test/var_ok.cpp =var_ok.cpp=]):
+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_ok.cpp =var_ok.cpp=]).
 
-[test_var_ok]
+[var_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 must be always wrapped by a set of extra round parenthesis `()` (for a total of two set of round parenthesis: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the parenthesis to wrap the type `BOOST_IDENTITY_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 set of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type within `BOOST_IDENTITY_TYPE((...))`.
 
-This macro works on any __CPP03__ compiler and it does not require __variadic_macro__ support.
-Using variadic macros, it would be possible to use a single set of parenthesis `()` instead of two `(())` but variadic macros are not part of the __CPP03__ (even if nowadays they are supported by most modern compilers and also part of __CPP11__).
+This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (because it does not require [@http://en.wikipedia.org/wiki/Variadic_macro variadic macro] support).
+[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).
+]
+
+[endsect]
 
 [section Templates]
 
-This macro must be prefixed by `typename` when used within 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=]):
+
+[template_f_decl]
+[template_f_call]
 
-[test_var_tpl]
+However, note that the template parameter type `char` must be explicitly specified when invoking the function `f<char>(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)`.
+(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:
+
+[template_g_decl]
+[template_g_call]
 
 [endsect]
 
 [section Abstract Types]
 
-On some compilers (e.g., GCC), using this macro on abstract types (classes with one or more pure virtual function) 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., 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.
+
+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 [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html Boost.MPL `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=]):
 
-[test_var_abstract]
+[tmp_assert_abstract]
 
 [endsect]
 
+[section Annex: Usages]
+
+The [macroref BOOST_IDENTITY_TYPE] macro can be used either in 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=]):
+
+[tmp_assert_alternative]
+
+However, note that the user will /always/ have to specify the extra parenthesis even when the macro parameter contains no comma:
+
+[tmp_assert_alternative_always]
+
+In some cases, using the macro internally might provide the best syntax to the user.
+For example, this is the case for `BOOST_MPL_ASSERT` because the large 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.
+ boost::mpl::and_<
+ boost::is_const<T>
+ , boost::is_reference<T>
+ >
+ ));
+
+However, in other cases it might be preferable to not require the extra parenthesis in normal 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:
+
+ 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.
+
+[endsect]
+
+[section Annex: Implementation]
+
+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.
+]
+
+ #include <boost/type_traits/function_traits.hpp>
+
+ #define BOOST_IDENTITY_TYPE(parenthesized_type) \
+ boost::function_traits<void parenthesized_type>::arg1_type
+
+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 (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).
+
 [endsect]
 
 [xinclude reference.xml]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk