From 290103d629af3dedc19fabc234b4bf829fa6b746 Mon Sep 17 00:00:00 2001 From: Lorenzo Caminiti Date: Thu, 24 May 2012 01:35:04 +0000 Subject: [PATCH] Merged ScopeExit (improved), LocalFunction (new), Functional/OverloadedFunction (new), and Utility/IdentityType (new) from trunk into release branch. [SVN r78564] --- doc/Jamfile.v2 | 2 +- doc/acknowledgements.qbk | 10 +- doc/advanced_topics.qbk | 175 +++--- doc/alternatives.qbk | 92 ++-- doc/bibliography.qbk | 2 +- doc/examples.qbk | 83 +-- doc/getting_started.qbk | 35 +- doc/html/BOOST_LOCAL_FUNCTION.html | 16 +- ...BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.html | 2 +- .../BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.html | 8 +- ...CAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.html | 66 +++ doc/html/BOOST_LOCAL_FUNCTION_ID.html | 77 +++ doc/html/BOOST_LOCAL_FUNCTION_NAME.html | 37 +- doc/html/BOOST_LOCAL_FUNCTION_NAME_TPL.html | 65 +++ doc/html/BOOST_LOCAL_FUNCTION_TPL.html | 20 +- doc/html/BOOST_LOCAL_FUNCTION_TPL_ID.html | 77 +++ doc/html/BOOST_LOCAL_FUNCTION_TYPEOF.html | 12 +- .../boost_localfunction/Acknowledgments.html | 15 +- .../boost_localfunction/Advanced_Topics.html | 510 +++++++++++------- .../boost_localfunction/Alternatives.html | 186 ++++--- doc/html/boost_localfunction/Examples.html | 252 ++++++--- .../boost_localfunction/Getting_Started.html | 67 ++- .../boost_localfunction/Implementation.html | 66 +-- .../No_Variadic_Macros.html | 313 +++++------ .../boost_localfunction/Release_Notes.html | 21 +- doc/html/boost_localfunction/Tutorial.html | 138 +++-- doc/html/index.html | 62 ++- doc/html/reference.html | 16 +- doc/implementation.qbk | 20 +- doc/introduction.qbk | 24 +- doc/local_function.qbk | 57 +- doc/no_variadic_macros.qbk | 41 +- doc/release_notes.qbk | 15 +- doc/tutorial.qbk | 53 +- example/Jamfile.v2 | 21 +- .../add_cxx11_lambda.cpp | 21 +- example/add_global_functor.cpp | 9 +- example/add_local_functor.cpp | 10 +- example/add_phoenix.cpp | 11 +- example/chrono.py | 5 +- example/const_block.hpp | 15 +- ...st_block_err.cpp => const_block_error.cpp} | 0 example/const_block_error_cxx11_lambda.cpp | 28 + ...da.cpp => expensive_copy_cxx11_lambda.cpp} | 15 +- example/expensive_copy_local_function.cpp | 9 +- example/gcc_access.cpp | 12 +- ..._lambda_cpp11.cpp => gcc_cxx11_lambda.cpp} | 22 +- example/gcc_lambda.cpp | 20 +- example/gcc_lambda.hpp | 4 + example/gcc_square.cpp | 12 +- example/gcc_store.cpp | 12 +- example/impl_pp_keyword.cpp | 10 +- example/impl_tparam_tricks.cpp | 23 +- example/n2529_this.cpp | 17 +- example/n2550_find_if.cpp | 15 +- ...cpp => noncopyable_cxx11_lambda_error.cpp} | 17 +- example/noncopyable_local_function.cpp | 7 +- example/phoenix_factorial.cpp | 10 +- example/phoenix_factorial_local.cpp | 10 +- ...le_lambda.cpp => profile_cxx11_lambda.cpp} | 10 +- ..._debug.png => profile_gcc_cxx11_debug.png} | Bin ...ease.png => profile_gcc_cxx11_release.png} | Bin ...da.png => profile_legend_cxx11_lambda.png} | Bin example/scope_exit.cpp | 16 +- example/scope_exit.hpp | 4 + include/boost/local_function.hpp | 314 ++++++++--- include/boost/local_function/aux_/config.hpp | 35 -- .../boost/local_function/aux_/function.hpp | 37 +- .../local_function/aux_/macro/code_/bind.hpp | 50 +- .../local_function/aux_/macro/code_/end.hpp | 97 ---- .../aux_/macro/code_/functor.hpp | 77 +-- .../local_function/aux_/macro/code_/name.hpp | 103 ---- .../aux_/macro/code_/result.hpp | 104 ++-- .../boost/local_function/aux_/macro/name.hpp | 78 +-- include/boost/local_function/aux_/member.hpp | 22 +- include/boost/local_function/aux_/nobind.hpp | 10 +- include/boost/local_function/config.hpp | 63 ++- .../preprocessor/keyword/facility/add.hpp | 4 +- .../detail/preprocessor/void_list.hpp | 2 +- test/Jamfile.v2 | 70 +-- test/add.cpp | 16 +- test/add_classifiers.cpp | 20 +- test/add_classifiers_seq.cpp | 26 + test/add_classifiers_seq_nova.cpp | 10 + test/add_default.cpp | 20 +- test/add_default_seq.cpp | 19 + test/add_default_seq_nova.cpp | 10 + test/add_except.cpp | 19 +- test/add_except_seq.cpp | 25 + test/add_except_seq_nova.cpp | 10 + test/add_inline.cpp | 18 +- test/add_inline_seq.cpp | 28 + test/add_inline_seq_nova.cpp | 10 + test/{add_params.cpp => add_params_only.cpp} | 20 +- test/add_params_only_seq.cpp | 19 + test/add_params_only_seq_nova.cpp | 10 + test/add_seq.cpp | 17 +- test/add_seq_nova.cpp | 10 + test/add_template.cpp | 19 +- test/add_template_seq.cpp | 31 ++ test/add_template_seq_nova.cpp | 10 + test/add_this.cpp | 23 +- test/add_this_seq.cpp | 43 ++ test/add_this_seq_nova.cpp | 10 + test/add_typed.cpp | 20 +- test/add_typed_seq.cpp | 37 ++ test/add_typed_seq_nova.cpp | 10 + test/add_with_default.cpp | 16 +- test/add_with_default_seq.cpp | 21 + test/add_with_default_seq_nova.cpp | 10 + test/addable.hpp | 9 +- test/all_decl.cpp | 177 ++++++ test/{seq.cpp => all_decl_seq.cpp} | 10 +- test/all_decl_seq_nova.cpp | 10 + test/factorial.cpp | 24 +- test/factorial_seq.cpp | 48 ++ test/factorial_seq_nova.cpp | 10 + test/goto.cpp | 16 +- test/{goto_err.cpp => goto_error.cpp} | 21 +- test/goto_error_seq.cpp | 27 + test/goto_error_seq_nova.cpp | 10 + test/goto_seq.cpp | 25 + test/goto_seq_nova.cpp | 10 + test/macro_commas.cpp | 20 +- test/macro_commas_seq.cpp | 44 ++ test/macro_commas_seq_nova.cpp | 10 + test/nesting.cpp | 18 +- test/nesting_seq.cpp | 28 + test/nesting_seq_nova.cpp | 10 + test/nova.hpp | 21 + test/operator.cpp | 20 +- test/{operator_err.cpp => operator_error.cpp} | 24 +- test/operator_error_seq.cpp | 29 + test/operator_error_seq_nova.cpp | 10 + test/operator_seq.cpp | 29 + test/operator_seq_nova.cpp | 10 + test/overload.cpp | 29 +- test/overload_seq.cpp | 42 ++ test/overload_seq_nova.cpp | 10 + test/return_assign.cpp | 21 +- test/return_assign_seq.cpp | 40 ++ test/return_assign_seq_nova.cpp | 10 + test/return_derivative.cpp | 22 +- test/return_derivative_seq.cpp | 34 ++ test/return_derivative_seq_nova.cpp | 10 + test/return_inc.cpp | 21 +- test/return_inc_seq.cpp | 31 ++ test/return_inc_seq_nova.cpp | 10 + test/return_setget.cpp | 18 +- test/return_setget_seq.cpp | 39 ++ test/return_setget_seq_nova.cpp | 10 + test/return_this.cpp | 26 +- test/return_this_seq.cpp | 43 ++ test/return_this_seq_nova.cpp | 10 + test/same_line.cpp | 57 ++ test/same_line_seq.cpp | 48 ++ test/same_line_seq_nova.cpp | 10 + test/ten_void.cpp | 9 +- test/ten_void_nova.cpp | 10 + test/transform.cpp | 19 +- test/transform_seq.cpp | 39 ++ test/transform_seq_nova.cpp | 10 + test/typeof.cpp | 19 +- test/typeof_seq.cpp | 30 ++ test/typeof_seq_nova.cpp | 10 + test/typeof_template.cpp | 17 +- test/typeof_template_seq.cpp | 33 ++ test/typeof_template_seq_nova.cpp | 10 + 168 files changed, 4145 insertions(+), 1895 deletions(-) create mode 100644 doc/html/BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.html create mode 100644 doc/html/BOOST_LOCAL_FUNCTION_ID.html create mode 100644 doc/html/BOOST_LOCAL_FUNCTION_NAME_TPL.html create mode 100644 doc/html/BOOST_LOCAL_FUNCTION_TPL_ID.html rename test/add_lambda.cpp => example/add_cxx11_lambda.cpp (64%) rename example/{const_block_err.cpp => const_block_error.cpp} (100%) create mode 100644 example/const_block_error_cxx11_lambda.cpp rename example/{expensive_copy_lambda.cpp => expensive_copy_cxx11_lambda.cpp} (71%) rename example/{gcc_lambda_cpp11.cpp => gcc_cxx11_lambda.cpp} (60%) rename example/{noncopyable_lambda_err.cpp => noncopyable_cxx11_lambda_error.cpp} (64%) rename example/{profile_lambda.cpp => profile_cxx11_lambda.cpp} (90%) rename example/{profile_gcc_cpp11_debug.png => profile_gcc_cxx11_debug.png} (100%) rename example/{profile_gcc_cpp11_release.png => profile_gcc_cxx11_release.png} (100%) rename example/{profile_legend_lambda.png => profile_legend_cxx11_lambda.png} (100%) delete mode 100644 include/boost/local_function/aux_/config.hpp delete mode 100644 include/boost/local_function/aux_/macro/code_/end.hpp delete mode 100644 include/boost/local_function/aux_/macro/code_/name.hpp create mode 100644 test/add_classifiers_seq.cpp create mode 100644 test/add_classifiers_seq_nova.cpp create mode 100644 test/add_default_seq.cpp create mode 100644 test/add_default_seq_nova.cpp create mode 100644 test/add_except_seq.cpp create mode 100644 test/add_except_seq_nova.cpp create mode 100644 test/add_inline_seq.cpp create mode 100644 test/add_inline_seq_nova.cpp rename test/{add_params.cpp => add_params_only.cpp} (58%) create mode 100644 test/add_params_only_seq.cpp create mode 100644 test/add_params_only_seq_nova.cpp create mode 100644 test/add_seq_nova.cpp create mode 100644 test/add_template_seq.cpp create mode 100644 test/add_template_seq_nova.cpp create mode 100644 test/add_this_seq.cpp create mode 100644 test/add_this_seq_nova.cpp create mode 100644 test/add_typed_seq.cpp create mode 100644 test/add_typed_seq_nova.cpp create mode 100644 test/add_with_default_seq.cpp create mode 100644 test/add_with_default_seq_nova.cpp create mode 100644 test/all_decl.cpp rename test/{seq.cpp => all_decl_seq.cpp} (96%) create mode 100644 test/all_decl_seq_nova.cpp create mode 100644 test/factorial_seq.cpp create mode 100644 test/factorial_seq_nova.cpp rename test/{goto_err.cpp => goto_error.cpp} (67%) create mode 100644 test/goto_error_seq.cpp create mode 100644 test/goto_error_seq_nova.cpp create mode 100644 test/goto_seq.cpp create mode 100644 test/goto_seq_nova.cpp create mode 100644 test/macro_commas_seq.cpp create mode 100644 test/macro_commas_seq_nova.cpp create mode 100644 test/nesting_seq.cpp create mode 100644 test/nesting_seq_nova.cpp create mode 100644 test/nova.hpp rename test/{operator_err.cpp => operator_error.cpp} (56%) create mode 100644 test/operator_error_seq.cpp create mode 100644 test/operator_error_seq_nova.cpp create mode 100644 test/operator_seq.cpp create mode 100644 test/operator_seq_nova.cpp create mode 100644 test/overload_seq.cpp create mode 100644 test/overload_seq_nova.cpp create mode 100644 test/return_assign_seq.cpp create mode 100644 test/return_assign_seq_nova.cpp create mode 100644 test/return_derivative_seq.cpp create mode 100644 test/return_derivative_seq_nova.cpp create mode 100644 test/return_inc_seq.cpp create mode 100644 test/return_inc_seq_nova.cpp create mode 100644 test/return_setget_seq.cpp create mode 100644 test/return_setget_seq_nova.cpp create mode 100644 test/return_this_seq.cpp create mode 100644 test/return_this_seq_nova.cpp create mode 100644 test/same_line.cpp create mode 100644 test/same_line_seq.cpp create mode 100644 test/same_line_seq_nova.cpp create mode 100644 test/ten_void_nova.cpp create mode 100644 test/transform_seq.cpp create mode 100644 test/transform_seq_nova.cpp create mode 100644 test/typeof_seq.cpp create mode 100644 test/typeof_seq_nova.cpp create mode 100644 test/typeof_template_seq.cpp create mode 100644 test/typeof_template_seq_nova.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 0a30457..226e501 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -17,7 +17,7 @@ doxygen reference 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\" " ; xml qbk : local_function.qbk diff --git a/doc/acknowledgements.qbk b/doc/acknowledgements.qbk index 14fd7b3..5f1d571 100644 --- a/doc/acknowledgements.qbk +++ b/doc/acknowledgements.qbk @@ -5,11 +5,11 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Acknowledgments Acknowledgments] +[section Acknowledgments] This section aims to recognize the contributions of /all/ the different people that participated directly or indirectly to the design and development of this library. -Many thanks to Steven Watanabe and Vicente Botet for suggesting to me to use __Boost_ScopeExit__ binding to [@http://boost.2283326.n4.nabble.com/contract-diff-n1962-tt2671482.html#none emulate local functions]. +Many thanks to Steven Watanabe and Vicente Botet for suggesting to me to use __Boost_ScopeExit__ binding to [@http://lists.boost.org/Archives/boost/2010/04/165149.php emulate local functions]. Many thanks to Alexander Nasonov for clarifying how __Boost_ScopeExit__ binding could be used to implement local functions and for some [@http://thread.gmane.org/gmane.comp.lib.boost.devel/168612 early work] in this direction. Many thanks to Gregory Crosswhite for using an early version of this library in [@https://github.com/gcross/CodeSearch one of his projects]. @@ -25,9 +25,9 @@ Thanks to Vicente Botet for suggesting to provide a macro to expose the bound va Thanks to Steven Watanabe, Vicente Botet, Michael Caisse, Yechezkel Mett, Joel de Guzman, Thomas Heller, et al. for helping with the __Alternatives__ section and with the profiling of the different alternatives. -Many thanks to the library's [@http://lists.boost.org/boost-announce/2011/12/0340.php Boost review] manager: Jeffrey Lee Hellrung. -Thanks also to all the people that submitted a (positive and negative) review: Andrzej Krzemienski, Edward Diener, Gregory Crosswhite, John Bytheway, Hartmut Kaiser, Krzysztof Czainski, Nat Lindon, Pierre Morcello, Thomas Heller, and Vicente J. Botet. -Thanks to everyone else that commented (positively and negatively) on the library during its Boost review. +Many thanks to Jeffrey Lee Hellrung for managing the [@http://lists.boost.org/boost-announce/2011/12/0340.php Boost review] of this library. +Thanks also to all the people that submitted a Boost review: Andrzej Krzemienski, Edward Diener, Gregory Crosswhite, John Bytheway, Hartmut Kaiser, Krzysztof Czainski, Nat Lindon, Pierre Morcello, Thomas Heller, and Vicente J. Botet. +Thanks to everyone that commented on the library during its Boost review. Finally, many thanks to the entire __Boost__ community and [@http://lists.boost.org mailing list] for providing valuable comments about this library and great insights on the C++ programming language. diff --git a/doc/advanced_topics.qbk b/doc/advanced_topics.qbk index 6310a64..2998de6 100644 --- a/doc/advanced_topics.qbk +++ b/doc/advanced_topics.qbk @@ -5,19 +5,20 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Advanced_Topics Advanced Topics] +[section Advanced Topics] -This section illustrates advanced usages of this library (at the bottom there is also a list of known limitations of the library). +This section illustrates advanced usage of this library. +At the bottom there is also a list of known limitations of this library. [section Default Parameters] -This library also allows to specify default values for the local function parameters. +This library allows to specify default values for the local function parameters. However, the usual C++ syntax for default parameters that uses the assignment symbol `=` cannot be used. [footnote *Rationale.* The assignment symbol `=` cannot be used to specify default parameter values because default values are not part of the parameter type so they cannot be handled using template meta-programming. Default parameter values need to be separated from the rest of the parameter declaration using the preprocessor. -Specifically, this library needs to use preprocessor meta-programming to remove default values when constructing the local function type and then to count the number of default values to provide the correct set of call operators for the local functor. +Specifically, this library needs to use preprocessor meta-programming to remove default values when constructing the local function type and also to count the number of default values to provide the correct set of call operators for the local functor. Therefore, the symbol `=` cannot be used because it cannot be handled by preprocessor meta-programming (non-alphanumeric symbols cannot be detected by preprocessor meta-programming because they cannot be concatenated by the preprocessor). ] The keyword `default` is used instead: @@ -28,10 +29,10 @@ For example, let's program a local function `add(x, y)` where the second paramet [add_default] -Programmers can define a `WITH_DEFAULT` macro similar to the following if they think it improves readability over the syntax above (see also [@../../test/add_with_default.cpp =add_with_default.cpp=]): +Programmers can define a `WITH_DEFAULT` macro similar to the following if they think it improves readability over the above syntax (see also [@../../test/add_with_default.cpp =add_with_default.cpp=]): [footnote The authors do not personally find the use of the `WITH_DEFAULT` macro more readable and they prefer to use the `default` keyword directly. -Furthermore, `WITH_DEFAULT` needs to be defined differently for compilers without variadic macros `#define WITH_DEFAULT (default)` so it can only be defined by programmers based on the syntax they decide to use. +Furthermore, `WITH_DEFAULT` needs to be defined differently for compilers without variadic macros `#define WITH_DEFAULT (default)` so it can only be defined by programmers based on the syntax they decide to use (see the __No_Variadic_Macros__ section). ] [add_with_default_macro] @@ -42,7 +43,7 @@ Furthermore, `WITH_DEFAULT` needs to be defined differently for compilers withou [section Commas and Symbols in Macros] The C++ preprocessor does not allow commas `,` within macro parameters unless they are wrapped by round parenthesis `()` (see the __Boost_Utility_IdentityType__ documentation for details). -Therefore, using commas within the local function parameters and bindings will generate (cryptic) preprocessor errors unless they are wrapped with an extra set of round parenthesis `()` as explained here. +Therefore, using commas within local function parameters and bindings will generate (cryptic) preprocessor errors unless they are wrapped with an extra set of round parenthesis `()` as explained here. [note Also macro parameters with commas wrapped by angular parenthesis `<>` (templates, etc) or square parenthesis `[]` (multidimensional array access, etc) need to be wrapped by the extra round parenthesis `()` as explained here (this is because the preprocessor only recognizes the round parenthesis and it does not recognize angular, square, or any other type of parenthesis). @@ -74,7 +75,7 @@ This comma is not wrapped by any round parenthesis `()` thus it will cause a pre The preprocessor always interprets unwrapped commas as separating macro parameters. Thus in this case the comma will indicate to the preprocessor that the first macro parameter is `const std::map& m`, etc instead of passing `const std::map& m` as a single macro parameter. ] -The __Boost_Utility_IdentityType__ macro `BOOST_IDENTITY_TYPE(`[^['parenthesized-type]]`)` from the header =boost/utility/identity_type.hpp= can be used to wrap a type within extra parenthesis `()` so to overcome the problem: +The __Boost_Utility_IdentityType__ macro `BOOST_IDENTITY_TYPE((`[^['type-with-commas]]`))` defined in the =boost/utility/identity_type.hpp= header can be used to wrap a type within extra parenthesis `()` so to overcome this problem: #include @@ -85,7 +86,7 @@ The __Boost_Utility_IdentityType__ macro `BOOST_IDENTITY_TYPE(`[^['parenthesized ... } BOOST_LOCAL_FUNCTION_NAME(f) -This macro expands to an expression that evaluates (at compile-time) exactly to the specified type. +This macro expands to an expression that evaluates (at compile-time) exactly to the specified type (furthermore, this macro does not use variadic macros so it works on any __CXX03__ compiler). Note that a total of two set of parenthesis `()` are needed: The parenthesis to invoke the `BOOST_IDENTITY_TYPE(...)` macro plus the parenthesis to wrap the type expression (and therefore any comma `,` that it contains) passed as parameter to the `BOOST_IDENTITY_TYPE((...))` macro. Finally, the `BOOST_IDENTITY_TYPE` macro must be prefixed by the `typename` keyword `typename BOOST_IDENTITY_TYPE(`[^['parenthesized-type]]`)` when used together with the [macroref BOOST_LOCAL_FUNCTION_TPL] macro within templates. @@ -102,7 +103,7 @@ For example, in this case a `typedef` from the enclosing scope could have been u ) BOOST_LOCAL_FUNCTION_NAME(f) [*(2)] The parameter type `::sign_t` starts with the non-alphanumeric symbols `::` thus it will generate preprocessor errors if used as a local function parameter type. -The macros `BOOST_IDENTITY_TYPE` can also be used to overcome this issue: +The `BOOST_IDENTITY_TYPE` macro can also be used to overcome this issue: void BOOST_LOCAL_FUNCTION( ... @@ -128,7 +129,7 @@ For example, in this case the symbols `::` could have been simply dropped to obt [*(3)] The default parameter value `key_sizeof::value` contains a comma `,` after the first template parameter `std::string`. Again, this comma is not wrapped by any parenthesis `()` so it will cause a preprocessor error. -Because this is a value expression (and not a type expression), it can be simply wrapped within an extra set of round parenthesis `()`: +Because this is a value expression (and not a type expression), it can simply be wrapped within an extra set of round parenthesis `()`: void BOOST_LOCAL_FUNCTION( ... @@ -147,22 +148,21 @@ Consider the following complete example (see also [@../../test/macro_commas.cpp [endsect] -[section Assigning and Returning] +[section Assignments and Returns] -Local functions are function objects so it is possible to assign them to other functors like __Boost_Function__ `boost::function` in order to store the local function into a variable, pass it as a parameter to another function, or return it from the enclosing function. +Local functions are function objects so it is possible to assign them to other functors like __Boost_Function__'s `boost::function` in order to store the local function into a variable, pass it as a parameter to another function, or return it from the enclosing function. For example (see also [@../../test/return_assign.cpp =return_assign.cpp=]): [return_assign] -Note that: - -[important -As with __CPP11_lambda__ functions, programmers are responsible to ensure that bound references are valid in any scope where the local function object is called. -(This might be tricky to verify in a program when local functions are returned and called outside the local scope of their declaration.) +[warning +As with __CXX11_lambda_functions__, programmers are responsible to ensure that bound variables are valid in any scope where the local function object is called. +Returning and calling a local function outside its declaration scope will lead to undefined behaviour if any of the bound variable is no longer valid in the scope where the local function is called (see the __Examples__ section for more examples on the extra care needed when returning a local function as a closure). +It is always safe instead to call a local function within its enclosing scope. ] -In addition, a local function can bind and call another local function. +In addition, a local function can bind and call other local functions. Local functions should always be bound by constant reference `const bind&` to avoid unnecessary copies. For example, the following local function `inc_sum` binds the local function `inc` so `inc_sum` can call `inc` (see aslo [@../../test/transform.cpp =transform.cpp=]): @@ -181,7 +181,7 @@ For example (see also [@../../test/nesting.cpp =nesting.cpp=]): [section Accessing Types (concepts, etc)] -This library never requires to explicitly specify the type of bound variables. +This library never requires to explicitly specify the type of bound variables (e.g., this reduces maintenance because the local function declaration and definition do not have to change even if the bound variable types change as long as the semantics of the local function remain valid). From within local functions, programmers can access the type of a bound variable using the following macro: BOOST_LOCAL_FUNCTION_TYPEOF(``/bound-variable-name/``) @@ -198,10 +198,7 @@ Within templates, [macroref BOOST_LOCAL_FUNCTION_TYPEOF] should not be prefixed [typeof_template] -It is best to use the [macroref BOOST_LOCAL_FUNCTION_TYPEOF] macro instead of using __Boost_Typeof__ so to reduce the number of times that __Boost_Typeof__ is invoked: - -# Either the library already internally used __Boost_Typeof__ once, in which case using this macro will not use __Boost_Typeof__ again. -# Or, the bound variable type is explicitly specified by programmers (see below), in which case using this macro will not use __Boost_Typeof__ at all. +In this context, it is best to use the [macroref BOOST_LOCAL_FUNCTION_TYPEOF] macro instead of using __Boost_Typeof__ to reduce the number of times that __Boost_Typeof__ is invoked (either the library already internally used __Boost_Typeof__ once, in which case using this macro will not use __Boost_Typeof__ again, or the bound variable type is explicitly specified by programmers as shown be below, in which case using this macro will not use __Boost_Typeof__ at all). Furthermore, within the local function body it possible to access the result type using `result_type`, the type of the first parameter using `arg1_type`, the type of the second parameter using `arg2_type`, etc. [footnote @@ -211,9 +208,9 @@ The type names `result_type` and `arg`[^['N]]`_type` follow the __Boost_TypeTrai [endsect] -[section Specifying Types] +[section Specifying Types (no Boost.Typeof)] -While not required, it is possible to explicitly specify the type of a bound variable so the library will not internally use __Boost_Typeof__ to automatically deduce such a type. +While not required, it is possible to explicitly specify the type of bound variables so the library will not internally use __Boost_Typeof__ to automatically deduce the types. When specified, the bound variable type must follow the `bind` "keyword" and it must be wrapped within round parenthesis `()`: bind(``/variable-type/``) ``/variable-name/`` // Bind by value with explicit type. @@ -231,29 +228,28 @@ Thus it is also possible to specify the local function result type as one of the BOOST_LOCAL_FUNCTION_TYPE(return ``[^/result-type/]``, ...) Note that the result type must be specified only once either before the macro (without the `return` prefix) or as one of the macro parameters (with the `return` prefix). -As usual, the result type can always be `void` to declare a function returning nothing (so `return void` is allowed when the result type is specified as one of the macro parameters). +As always, the result type can be `void` to declare a function that returns nothing (so `return void` is allowed when the result type is specified as one of the macro parameters). The following example specifies all bound variables and result types (see also [@../../test/add_typed.cpp =add_typed.cpp=]): [footnote -In the examples of this documentation, we specify bound variables, function parameters, and result type in this order because this is the order used by __CPP11_lambda__ functions. +In the examples of this documentation, bound variables, function parameters, and the result type are specified in this order because this is the order used by __CXX11_lambda_functions__. However, the library accepts bound variables, function parameters, and the result type in any order. ] [add_typed] Unless necessary, it is recommended to not specify the bound variable and result types. -Let the library deduce these types so the local function syntax will be more concise and the local function declaration will not have to change if a bound variable type changes (facilitating maintenance). +Let the library deduce these types so the local function syntax will be more concise and the local function declaration will not have to change if a bound variable type changes (reducing maintenance). [note -Unfortunately, even when all bound variables and result types are explicitly specified, the currently library implementation still has to use __Boost_Typeof__ once (to deduce the local function object type, see the __Implementation__ section). +When all bound variable and result types are explicitly specified, the library implementation will not use __Boost_Typeof__. ] - [endsect] [section Inlining] -Local functions can be declared inline to increase the chances that the compiler will be able to reduce the run-time of the local function call by inlining the generated assembly code. +Local functions can be declared [@http://en.wikipedia.org/wiki/Inline_function inline] to increase the chances that the compiler will be able to reduce the run-time of the local function call by inlining the generated assembly code. A local function is declared inline by prefixing its name with the keyword `inline`: ``/result-type/`` BOOST_LOCAL_FUNCTION(``/parameters/``) { @@ -262,20 +258,20 @@ A local function is declared inline by prefixing its name with the keyword `inli When inlining a local function, note the following: -* On __CPP03__ compliant compilers, inlined local functions always have a run-time comparable to their equivalent implementation that uses local functors (see the __Alternatives__ section). -However, inlined local functions have the important limitation that they cannot be assigned to other functors (like `boost::function`) and they cannot be passed as template parameters. -* On __CPP11__ compilers, `inline` has no effect because this library will automatically generate code that uses __CPP11__ specific features to inline the local function calls whenever possible even if the local function is not declared inline. -Furthermore, non __CPP11__ local functions can always be passes as template parameters even when they are declared inline. +* On __CXX03__ compliant compilers, inline local functions always have a run-time comparable to their equivalent implementation that uses local functors (see the __Alternatives__ section). +However, inline local functions have the important limitation that they cannot be assigned to other functors (like `boost::function`) and they cannot be passed as template parameters. +* On __CXX11__ compilers, `inline` has no effect because this library will automatically generate code that uses __CXX11__ specific features to inline the local function calls whenever possible even if the local function is not declared inline. +Furthermore, non __CXX11__ local functions can always be passes as template parameters even when they are declared inline. [footnote *Rationale.* This library uses an indirect function call via a function pointer in order to pass the local function as a template parameter (see the __Implementation__ section). No compiler has yet been observed to be able to inline function calls when they use such indirect function pointer calls. -Therefore, inlined local functions do not use such indirect function pointer call (so they are more likely to be optimized) but because of that they cannot be passed as template parameters. -The indirect function pointer call is needed on __CPP03__ but it is not needed on __CPP11__ (see __N2657__) thus this library automatically generates local function calls that can be inlined on __CPP11__ compilers (even when the local function is not declared inline). +Therefore, inline local functions do not use such indirect function pointer call (so they are more likely to be optimized) but because of that they cannot be passed as template parameters. +The indirect function pointer call is needed on __CXX03__ but it is not needed on __CXX11__ (see __N2657__ and __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`) thus this library automatically generates local function calls that can be inline on __CXX11__ compilers (even when the local function is not declared inline). ] [important -It is recommended to not declare a local function inline unless it is strictly necessary for optimizing pure __CPP03__ compliant code (because in all other cases this library will automatically take advantage of __CPP11__ features to optimize the local function calls while always allowing to pass the local function as a template parameter). +It is recommended to not declare a local function inline unless it is strictly necessary for optimizing pure __CXX03__ compliant code (because in all other cases this library will automatically take advantage of __CXX11__ features to optimize the local function calls while always allowing to pass the local function as a template parameter). ] For example, the following local function is declared inline (thus a for-loop needs to be used for portability instead of passing the local function as a template parameter to the `std::for_each` algorithm, see also [@../../test/add_inline.cpp =add_inline.cpp=]): @@ -287,7 +283,7 @@ For example, the following local function is declared inline (thus a for-loop ne [section Recursion] Local functions can be declared [@http://en.wikipedia.org/wiki/Recursion_(computer_science)#Recursive_procedures recursive] so a local function can recursively call itself from its body (as usual with C++ functions). -A local function is declared recursive by prefixing its name with the "keyword" `recursive` (thus `recursive` cannot be used as a local function name): +A local function is declared recursive by prefixing its name with the `recursive` "keyword" (thus `recursive` cannot be used as a local function name): ``/result-type/`` BOOST_LOCAL_FUNCTION(``/parameters/``) { ... // Body. @@ -297,27 +293,32 @@ For example, the following local function is used to recursively calculate the f [factorial] -Compilers have not been observed to be able to inline recursive local function calls (not even when the recursive local function is also declared inline as in `BOOST_LOCAL_FUNCTION_NAME(inline recursive factorial)`). +Compilers have not been observed to be able to inline recursive local function calls not even when the recursive local function is also declared inline: + + ... BOOST_LOCAL_FUNCTION_NAME(inline recursive factorial) -[warning Recursive local functions should never be called outside their declaration scope. -If a local function is returned from the enclosing function and called in a different scope, the behaviour is undefined (and it will likely result in a run-time error). [footnote *Rationale.* This limitation comes from the fact that the global functor used to pass the local function as a template parameter (and eventually returned outside the declarations scope) does not know the local function name so the local function name used for recursive call cannot be set in the global functor. This limitation together with preventing the possibility for inlining are the reasons why local functions are not recursive unless programmers explicitly declare them `recursive`. ] -This is not a limitation with respect to __CPP11_lambda__ functions because lambdas can never call themselves recursively (in other words, there is no recursive lambda function that can successfully be called outside its declaration scope because there is no recursive lambda function at all). + +[warning +If a local function is returned from the enclosing function and called in a different scope, the behaviour is undefined (and it will likely result in a run-time error). ] +This is not a limitation with respect to __CXX11_lambda_functions__ because lambdas can never call themselves recursively (in other words, there is no recursive lambda function that can successfully be called outside its declaration scope because there is no recursive lambda function at all). + [endsect] [section Overloading] -It is possible to overload local functions using the `boost::overloaded_function` functor of __Boost_Functional_OverloadedFunction__ from the header =boost/functional/overloaded_function.hpp= (see the __Boost_Functional_OverloadedFunction__ documentation for details). +Because local functions are functors, it is possible to overload them using the `boost::overloaded_function` functor of __Boost_Functional_OverloadedFunction__ from the =boost/functional/overloaded_function.hpp= header (see the __Boost_Functional_OverloadedFunction__ documentation for details). In the following example, the overloaded function object `add` can be called with signatures from either the local function `add_s`, or the local function `add_d`, or the local function `add_d` with its extra default parameter, or the function pointer `add_i` (see also [@../../test/overload.cpp =overload.cpp=]): +[overload_decl] [overload] [endsect] @@ -337,14 +338,14 @@ For example (see also [@../../test/add_except.cpp =add_except.cpp=]): [endsect] -[section Storage Classifiers (`auto` and `register`)] +[section Storage Classifiers] -Local function parameters support the storage classifiers as usual in __CPP03__. +Local function parameters support the storage classifiers as usual in __CXX03__. The `auto` storage classifier is specified as: [footnote -The `auto` storage classifier is part of the __CPP03__ standard and therefore supported by this library. -However, the meaning and usage of the `auto` keyword changed in __CPP11__. -Therefore, use the `auto` storage classifier with the usual care in order to avoid writing __CPP03__ code that might not work on __CPP11__. +The `auto` storage classifier is part of the __CXX03__ standard and therefore supported by this library. +However, the meaning and usage of the `auto` keyword changed in __CXX11__. +Therefore, use the `auto` storage classifier with the usual care in order to avoid writing __CXX03__ code that might not work on __CXX11__. ] auto ``/parameter-type parameter-name/`` @@ -359,6 +360,32 @@ For example (see also [@../../test/add_classifiers.cpp =add_classifiers.cpp=]): [endsect] +[section Same Line Expansions] + +In general, it is not possible to expand the [macroref BOOST_LOCAL_FUNCTION], [macroref BOOST_LOCAL_FUNCTION_TPL] macros multiple times on the same line. +[footnote +*Rationale.* +The [macroref BOOST_LOCAL_FUNCTION] and [macroref BOOST_LOCAL_FUNCTION_TPL] macros internally use `__LINE__` to generate unique identifiers. +Therefore, if these macros are expanded more than on time on the same line, the generated identifiers will no longer be unique and the code will not compile. +(This restriction does not apply to MSVC and other compilers that provide the non-standard `__COUNTER__` macro.) +Note that the [macroref BOOST_LOCAL_FUNCTION_NAME] macro can always be expanded multiple times on the same line because the unique local function name (and not `__LINE__`) is used by this macro to generate unique identifiers (so there is no need for a `BOOST_LOCAL_FUNCTION_NAME_ID` macro). +] + +Therefore, this library provides additional macros [macroref BOOST_LOCAL_FUNCTION_ID] and [macroref BOOST_LOCAL_FUNCTION_ID_TPL] which can be expanded multiple times on the same line as long as programmers specify unique identifiers as the macros' first parameters. +The unique identifier can be any token (not just numeric) that can be successfully concatenated by the preprocessor (e.g., `local_function_number_1_at_line_123`). +[footnote +Because there are restrictions on the set of tokens that the preprocessor can concatenate and because not all compilers correctly implement these restrictions, it is in general recommended to specify unique identifiers as a combination of alphanumeric tokens. +] + +The [macroref BOOST_LOCAL_FUNCTION_ID] and [macroref BOOST_LOCAL_FUNCTION_ID_TPL] macros accept local function parameter declaration lists using the exact same syntax as [macroref BOOST_LOCAL_FUNCTION]. +For example (see also [@../../test/same_line.cpp =same_line.cpp=]): + +[same_line] + +As shown by the example above, the [macroref BOOST_LOCAL_FUNCTION_ID] and [macroref BOOST_LOCAL_FUNCTION_ID_TPL] macros are especially useful when it is necessary to invoke them multiple times within a user-defined macro (because the preprocessor expands all nested macros on the same line). + +[endsect] + [section Limitations (operators, etc)] The following table summarizes all C++ function features indicating those features that are not supported by this library for local functions. @@ -371,73 +398,73 @@ The following table summarizes all C++ function features indicating those featur ] [ [ `export` ] - [ No ] + [ No. ] [ This is not supported because local functions cannot be templates (plus most C++ compilers do not implement `export` at all). ] ] [ [ `template<`[^['template-parameter-list]]`>` ] - [ No ] - [ This is not supported because local functions are implemented using local classes and __CPP03__ local classes cannot be templates. ] + [ No. ] + [ This is not supported because local functions are implemented using local classes and __CXX03__ local classes cannot be templates. ] ] [ [ `explicit` ] - [ No ] + [ No. ] [ This is not supported because local functions are not constructors. ] ] [ [ `inline` ] - [ Yes ] - [ Local functions can be specified `inline` to improve the chances that __CPP03__ standard compilers can optimize the local function call run-time (but `inline` local functions cannot be passed as template parameters on __CPP03__ standard compilers, see the __Advanced_Topics__ section). ] + [ Yes. ] + [ Local functions can be specified `inline` to improve the chances that __CXX03__ compilers can optimize the local function call run-time (but `inline` local functions cannot be passed as template parameters on __CXX03__ compilers, see the __Advanced_Topics__ section). ] ] [ [ `extern` ] - [ No ] + [ No. ] [ This is not supported because local functions are always defined locally within the enclosing scope and together with their declarations. ] ] [ [ `static` ] - [ No ] + [ No. ] [ This is not supported because local functions are not member functions. ] ] [ [ `virtual` ] - [ No ] + [ No. ] [ This is not supported because local functions are not member functions. [footnote *Rationale.* It would be possible to make a local function class inherit from another local function class. -However, this "inheritance" feature is not implemented because it seemed of [@http://lists.boost.org/Archives/boost/2010/09/170895.php no use] given that local functions can be bound to one another thus they can simply call each other directly without recurring to dynamic binding or base function call. +However, this "inheritance" feature is not implemented because it seemed of [@http://lists.boost.org/Archives/boost/2010/09/170895.php no use] given that local functions can be bound to one another thus they can simply call each other directly without recurring to dynamic binding or base function calls. ] ] ] [ [ [^/result-type/] ] - [ Yes ] + [ Yes. ] [ This is supported (see the __Tutorial__ section). ] ] [ [ [^/function-name/] ] - [ Yes ] + [ Yes. ] [ Local functions are named and they can call themselves recursively but they cannot be operators (see the __Tutorial__ and __Advanced_Topics__ sections). ] ] [ [ [^/parameter-list/] ] - [ Yes ] + [ Yes. ] [ This is supported and it also supports the `auto` and `register` storage classifiers, default parameters, and binding of variables in scope (see the __Tutorial__ and __Advanced_Topics__ sections). ] ] [ [ Trailing `const` qualifier ] - [ No ] + [ No. ] [ This is not supported because local functions are not member functions. ] ] [ [ Trailing `volatile` qualifier ] - [ No ] + [ No. ] [ This is not supported because local functions are not member functions. ] ] ] -[h5 Operators] +[heading Operators] Local functions cannot be operators. Naming a local function `operator...` will generate a compile-time error. @@ -446,17 +473,21 @@ Naming a local function `operator...` will generate a compile-time error. This is the because a local function name must be a valid local variable name (the local variable used to hold the local functor) and operators cannot be used as local variable names. ] -For example, the following code will not compile: +For example, the following code does not compile (see also [@../../test/operator_error.cpp =operator_error.cpp=]): -[operator_err] +[operator_error] -[h5 Goto] +[heading Goto] -It is not possible to jump with a `goto` from within a local function to a label defined in the enclosing scope. +It is possible to jump with a `goto` within the local function body. +For example, the following compiles (see also [@../../test/goto.cpp =goto.cpp=]): -For example, the following will not compile: +[goto] -[goto_err] +However, it is not possible to jump with a `goto` from within the local function body to to a label defined in the enclosing scope. +For example, the following does not compile (see also [@../../test/goto_error.cpp =goto_error.cpp=]): + +[goto_error] [endsect] diff --git a/doc/alternatives.qbk b/doc/alternatives.qbk index 984f938..bf7f00c 100644 --- a/doc/alternatives.qbk +++ b/doc/alternatives.qbk @@ -5,11 +5,11 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Alternatives Annex: Alternatives] +[section:alternatives Annex: Alternatives] This section compares the features offered by this library with similar features offered by C++ and by other libraries. -[h5 Features] +[heading Features] The following table compares local function features. @@ -34,13 +34,13 @@ Therefore this not really an alternative implementation of local functions but i [ [ ['Can be defined using C++ statement syntax] ] [ Yes. -Plus eventual compiler errors and debugging follow the usual format of C++ statement errors. ] +Plus eventual compiler errors and debugging retain their usual meaning and format. ] [ Yes. -Plus eventual compiler errors and debugging follow the usual format of C++ statement errors. ] +Plus eventual compiler errors and debugging retain their usual meaning and format. ] [ Yes. -Plus eventual compiler errors and debugging follow the usual format of C++ statement errors. ] +Plus eventual compiler errors and debugging retain their usual meaning and format. ] [ Yes. -Plus eventual compiler errors and debugging follow the usual format of C++ statement errors. ] +Plus eventual compiler errors and debugging retain their usual meaning and format. ] [ No (it uses C++ __expression_template__ syntax). ] ] [ @@ -54,19 +54,19 @@ Plus eventual compiler errors and debugging follow the usual format of C++ state [ [ ['Can be passed as template parameter (e.g., to STL algorithms)] ] [ Yes. -The __CPP03__ standard does not allow to pass local types as template parameters (see __N2657__) but this library implements a "trick" to get around this limitation (see the __Implementation__ section). ] +The __CXX03__ standard does not allow to pass local types as template parameters (see __N2657__) but this library implements a "trick" to get around this limitation (see the __Implementation__ section). ] [ Yes. ] - [ No on __CPP03__ compilers (but yes on __CPP11__ compilers and some compilers like MSVC 8.0, see __N2657__). ] + [ No on __CXX03__ compilers (but yes on __CXX11__ compilers and some compilers like MSVC 8.0, see __N2657__). ] [ Yes. ] [ Yes. ] ] [ [ ['Access variables in scope] ] [ Yes. -The variable names are repeated in the function declaration so they can be bound by value, by constant value, by reference, and by constant reference (the object `this` can also be bound). ] +The variable names are repeated in the function declaration so they can be bound by value, by constant value, by reference, and by constant reference (the object `this` can also be bound using `this_`). ] [ Yes. The variable names are repeated in the function declaration (plus there is a short-hand syntax to bind all variables in scope at once) so they can be bound by constant value and by reference (the object `this` can also be bound). -However, variables cannot be bound by constant references and non-constant value (see below). ] +However, variables cannot be bound by constant references (see below). ] [ No. Programmers must manually program functor data members and explicitly specify their types to access variables in scope. ] [ No. @@ -75,9 +75,9 @@ Programmers must manually program functor data members and explicitly specify th Variables in scope are accessible as usual within expressions (plus `boost::phoenix::let` can be used to bind variables by constant reference). ] ] [ - [ ['[@http://en.wikipedia.org/wiki/Type_polymorphism#Parametric_polymorphism Polymorphic] in the unbound parameter types] ] + [ ['[@http://en.wikipedia.org/wiki/Type_polymorphism#Parametric_polymorphism Polymorphic] in the function parameter type] ] [ No (local functions cannot be function templates). ] - [ No (__CPP11__ lambdas cannot be function templates). ] + [ No (__CXX11__ lambdas cannot be function templates). ] [ No (local classes cannot have member function templates). ] [ Yes. ] [ Yes. ] @@ -86,32 +86,32 @@ Variables in scope are accessible as usual within expressions (plus `boost::phoe [*C++11 Lambda Function] -__CPP11_lambda__ functions have most of the features of this library (see also the example in the __Introduction__ section): +__CXX11_lambda_functions__ have most of the features of this library plus some additional feature (see also the example in the __Introduction__ section): -* __CPP11_lambda__ functions can be defined within expressions while this library local functions can only be defined at declaration scope. -* __CPP11_lambda__ functions are only supported by the __CPP11__ standard so they are not supported by all C++ compilers. -This library local functions can be programmed also on __CPP03__ compilers (and they have performances comparable to __CPP11_lambda__ functions on __CPP11__ compilers). -* __CPP11_lambda__ functions do not allow to bind variables in scope by constant reference or by non-constant value. -Because a variable cannot be bound by constant reference, __CPP11_lambda__ functions can bind a variable by constant only if the variable is `CopyConstructible` and the binding requires a (potentially expensive) extra copy operation. -Both constant reference and non-constant value binding are instead supported by this library. -However, __CPP11_lambda__ functions provide a short-hand syntax to bind all variables in scope at once (`&` or `=`). +* __CXX11_lambda_functions__ can be defined within expressions while this library local functions can only be defined at declaration scope. +* __CXX11_lambda_functions__ are only supported by the __CXX11__ standard so they are not supported by all C++ compilers. +This library local functions can be programmed also on __CXX03__ compilers (and they have performances comparable to __CXX11_lambda_functions__ on __CXX11__ compilers). +* __CXX11_lambda_functions__ do not allow to bind variables in scope by constant reference. +Because a variable cannot be bound by constant reference, __CXX11_lambda_functions__ can bind a variable by constant only if the variable is `CopyConstructible` and the binding requires a (potentially expensive) extra copy operation. +Constant reference binding is instead supported by this library. +* __CXX11_lambda_functions__ do not allow to bind data members selectively without binding also the object `this` while this library local functions can bind either selected data members or the entire object `this` (using `this_`). +* __CXX11_lambda_functions__ provide a short-hand syntax to bind all variables in scope at once (`&` or `=`) while this library local function always require to bind variables naming them one-by-one. -For example, for non-copyable objects (see also [@../../example/noncopyable_lambda_err.cpp =noncopyable_lambda_err.cpp=] and [@../../example/noncopyable_local_function.cpp =noncopyable_local_function.cpp=]): +For example, for non-copyable objects (see also [@../../example/noncopyable_cxx11_lambda_error.cpp =noncopyable_cxx11_lambda_error.cpp=] and [@../../example/noncopyable_local_function.cpp =noncopyable_local_function.cpp=]): [table - [ [C++11 Lambda] [Boost.LocalFunction] ] - [ [[noncopyable_lambda_err]] [[noncopyable_local_function]] ] + [ [C++11 Lambda Function] [Boost.LocalFunction] ] + [ [[noncopyable_cxx11_lambda_error]] [[noncopyable_local_function]] ] ] -Or, for objects with expensive copy operations (see also [@../../example/expensive_copy_lambda.cpp =expensive_copy_lambda.cpp=] and [@../../example/expensive_copy_local_function.cpp =expensive_copy_local_function.cpp=]): +Or, for objects with expensive copy operations (see also [@../../example/expensive_copy_cxx11_lambda.cpp =expensive_copy_cxx11_lambda.cpp=] and [@../../example/expensive_copy_local_function.cpp =expensive_copy_local_function.cpp=]): [table - [ [C++11 Lambda] [Boost.LocalFunction] ] - [ [[expensive_copy_lambda]] [[expensive_copy_local_function]] ] + [ [C++11 Lambda Function] [Boost.LocalFunction] ] + [ [[expensive_copy_cxx11_lambda]] [[expensive_copy_local_function]] ] ] -When constant binding functionality is needed for __CPP11_lambda__ functions, the best alternative might be to bind an extra local variable declared constant and initialized to the original variable (for example, `const n& const_x = x` and then bind `const_x` instead of `x` to the lambda function). -In many cases the use of the extra constant variable `const_x` can be acceptable but in other cases (e.g., /constant blocks/ presented in the __Examples__ section) it might be preferable to maintain the same variable name `x` within the function body. +When constant binding functionality is needed for __CXX11_lambda_functions__, the best alternative might be to bind an extra local variable declared constant and initialized to the original variable (for example, see /constant blocks/ implemented with __CXX11_lambda_functions__ in the __Examples__ section). [*Local Functor] @@ -145,29 +145,29 @@ The following example compares local functions with __Boost_Phoenix__ (see also The comparison in this section does not include the __Boost_Lambda__ library because that library is obsolete and it was replaced by __Boost_Phoenix__. The __Boost_Phoenix__ library version 3.0 is used for this comparison. -[h5 Performances] +[heading Performances] -The following tables compare run-times, compile-times, and binary sizes for the different alternatives presented here for local functions. +The following tables compare run-times, compile-times, and binary sizes for the different alternatives to local functions presented in this section. Overall, this library has compile-times and generates binary sizes similar to the ones of the other approaches. -This library run-times on __CPP03__ compilers were measured to be larger than other approaches when compiler optimization is enabled (using `bjam release ...`). -However, on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with __CPP11__ features enabled [^-std=c++0x], see also __N2657__) this library automatically generates optimized code that runs as fast as the fastest of the other approaches (see the "Boost.LocalFunction" approach below). +This library run-times on __CXX03__ compilers were measured to be larger than other approaches when compiler optimization is enabled (using `bjam release ...`). +However, on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with __CXX11__ features enabled [^-std=c++0x], see also __N2657__ and __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`) this library automatically generates optimized code that runs as fast as the fastest of the other approaches (see the "Boost.LocalFunction" approach below). When this library local function is specified `inline` (see the "Boost.LocalFunction Inline" approach below and the __Advanced_Topics__ section) its run-times are always comparable to both the "Local Functor" and "Global Functor" approaches. -However, in these cases the local function cannot be portably passed as template parameter (see __N2657__) so `std::for_each` is replaced by a for-loop (on MSVC the for-loop, and not the local function in fact the same applies to local functors, was measured to have worst performances than using `std::for_each`). +However, in these cases the local function cannot be portably passed as template parameter (see __N2657__ and __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`) so `std::for_each` is replaced by a for-loop (on MSVC the for-loop, and not the local function in fact the same applies to local functors, was measured to have worst performances than using `std::for_each`). Finally, this library run-times are always among the fastest when no compiler optimization is enabled (using `bjam debug ...`). [note -The run-time performances of this library local functions are explained because on __CPP03__ compliant compilers (e.g., GCC 4.5.3 without [^-std=c++0x]) this library needs to use a function pointer in order to pass the local function class as a template parameter (see __N2657__ and the __Implementation__ section). +The run-time performances of this library local functions are explained because on __CXX03__ compliant compilers (e.g., GCC 4.5.3 without [^-std=c++0x]) this library needs to use a function pointer in order to portably pass the local function class as a template parameter (see __N2657__ and the __Implementation__ section). For all tested compilers, this function pointer prevents the compiler optimization algorithms from inlining the local function calls. Instead, the functors used by other approaches (e.g., __Boost_Phoenix__) have been observed to allow all tested compilers to inline all the function calls for optimization. -This run-time performance cost is not present on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with __CPP11__ features enabled [^-std=c++0x]) because this library does not have to use the extra function pointer to implement the local function call (it directly passes the local class type as template parameter). +This run-time performance cost is not present on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with __CXX11__ features enabled [^-std=c++0x], see __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`) because this library does not have to use the extra function pointer to implement the local function call (it directly passes the local class type as template parameter). ] -This run-time performance cost on __CPP03__ compilers might or might not be an issue depending on the performance requirements of specific applications. +This run-time performance cost on __CXX03__ compilers might or might not be an issue depending on the performance requirements of specific applications. For example, an application might already be using a number of indirect function calls (function pointers, virtual functions, etc) for which the overhead added by using the one extra function pointer required by the local function call might not be noticeable within the overall program run-time. Finally, note that only a very simple local function body with just a single instruction was used for the anaylsis presented here (see the source files below). -The authors have not studied how this library and the other approaches will perform with respect to each other when a more complex set of instructions is programmed for the local function body (e.g., /if/ a more complex set of instructions in the local function body were to inhibit some compilers from inlining functor objects also other approaches like __Boost_Phoenix__ /could/ start to show higher run-times even when optimization is enabled). +The authors have not studied how this library and the other approaches will perform with respect to each other when a more complex set of instructions is programmed for the local function body (e.g., /if/ a more complex set of instructions in the local function body were to inhibit some compiler from inlining function objects also other approaches like __CXX11_lambda_functions__ and __Boost_Phoenix__ /could/ start to show higher run-times even when optimization is enabled). The following commands were executed from the library example directory to measure compile-time, binary size, and run-time respectively: @@ -197,13 +197,13 @@ The local function was called =1e8= times to add together all the elements of a [[@../../example/profile_local_function_inline.cpp =profile_local_function_inline.cpp=]] ] [ - [[$../../example/profile_legend_lambda.png]] - [__CPP11__ Lambda Function + [[$../../example/profile_legend_cxx11_lambda.png]] + [__CXX11__ Lambda Function [footnote -Measurements available only for __CPP11__ compilers. +Measurements available only for __CXX11__ compilers. ] ] - [[@../../example/profile_lambda.cpp =profile_lambda.cpp=]] + [[@../../example/profile_cxx11_lambda.cpp =profile_cxx11_lambda.cpp=]] ] [ [[$../../example/profile_legend_local_functor.png]] @@ -223,19 +223,19 @@ Measurements available only for __CPP11__ compilers. ] [table - [ [GCC 4.5.3 With C++11 Lambdas and "Local Types as Template Parameters" ([^bjam cxxflags=-std=c++0x ...])] ] + [ [GCC 4.5.3 With C++11 Lambda Functions and "Local Classes as Template Parameters" ([^bjam cxxflags=-std=c++0x ...])] ] [ [ [*Compiled with =bjam release ...= for maximum optimization (=-O3 -finline-functions=)] - [$../../example/profile_gcc_cpp11_release.png [width 13in] [height 10in]] + [$../../example/profile_gcc_cxx11_release.png [width 13in] [height 10in]] ] ] [ [ [*Compiled with =bjam debug ...= for no optimization (=-O0 -fno-inline=)] - [$../../example/profile_gcc_cpp11_debug.png [width 13in] [height 10in]] + [$../../example/profile_gcc_cxx11_debug.png [width 13in] [height 10in]] ] ] ] [table - [ [MSVC 8.0 With "Local Types as Template Parameters" (Without __CPP11__ Lambdas)] ] + [ [MSVC 8.0 With "Local Classes as Template Parameters" (Without C++11 Lambda Functions)] ] [ [ [*Compiled with =bjam release ...= for maximum optimization (=/O2 /Ob2=)] [$../../example/profile_msvc_release.png [width 13in] [height 10in]] @@ -247,7 +247,7 @@ Measurements available only for __CPP11__ compilers. ] [table - [ [GCC 4.3.4 With __CPP03__ Only (Without __CPP11__ Lambdas and Without "Local Types as Template Parameters")] ] + [ [GCC 4.3.4 With __CXX03__ Only (Without __CXX11__ Lambda Functions and Without "Local Classes as Template Parameters")] ] [ [ [*Compiled with =bjam release ...= for maximum optimization (=-O3 -finline-functions=)] [$../../example/profile_gcc_release.png [width 13in] [height 10in]] diff --git a/doc/bibliography.qbk b/doc/bibliography.qbk index 3b11a6f..1db2d99 100644 --- a/doc/bibliography.qbk +++ b/doc/bibliography.qbk @@ -5,7 +5,7 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Bibliography Bibliography] +[section Bibliography] This section lists all the bibliographic references cited by this documentation. diff --git a/doc/examples.qbk b/doc/examples.qbk index 51888ad..db33d93 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -5,32 +5,36 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Examples Examples] +[section Examples] This section lists some examples that use this library. -[section GCC Lambdas (Without C++11)] +[section GCC Lambdas (without C++11)] -Combing local functions with the [@http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html statement expression] extension of GCC compilers, it is possible to implement lambda functions for GCC compilers even without __CPP11__ support. +Combing local functions with the non-standard [@http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html statement expression] extension of the GCC compiler, it is possible to implement lambda functions for GCC compilers even without __CXX11__ support. [warning -This code only works on compilers that support the statement expression GCC extension or that support __CPP11_lambda__ functions. +This code only works on compilers that support GCC statement expression extension or that support __CXX11_lambda_functions__. ] -For example (see also [@../../example/gcc_lambda.cpp =gcc_lambda.cpp=] and [@../../example/gcc_lambda_cpp11.cpp =gcc_lambda_cpp11.cpp=]): +For example (see also [@../../example/gcc_lambda.cpp =gcc_lambda.cpp=] and [@../../example/gcc_cxx11_lambda.cpp =gcc_cxx11_lambda.cpp=]): [table [ [With Local Functions (GCC only)] [C++11 Lambdas] ] - [ [[gcc_lambda]] [[gcc_lambda_cpp11]] ] + [ [[gcc_lambda]] [[gcc_cxx11_lambda]] ] ] -Where the macros are defined in [@../../example/gcc_lambda.hpp =gcc_lambda.hpp=]. +The GCC lambda function macros are implemented using local functions (see also [@../../example/gcc_lambda.hpp =gcc_lambda.hpp=]): + +[gcc_lambda_macro] +[gcc_lambda_end_macro] This is possible because GCC statement expressions allow to use declaration statements within expressions and therefore to declare a local function within an expression. -The macros automatically detect if the compiler supports __CPP11_lambda__ functions in which case the implementation uses native lambdas instead of local functions in statement expressions. -However, __CPP11_lambda__ functions do not support constant binding so it is best to only use `const bind variable` (same as __CPP11_lambda__ `=variable`) and `bind& variable` (same as __CPP11_lambda__ `&variable`) because these have the exact same semantic between the local function and native lambda implementation. -Unfortunately, the __CPP11_lambda__ short-hand binds `&` and `=` (which automatically bind all variables in scope either by reference or value) are not supported by the macros because they are not supported by the local function implementation. -Finally, the result type `return `[^['result-type]] is optional and it is assumed `void` when it is not specified (same as with __CPP11_lambda__ functions). +The macros automatically detect if the compiler supports __CXX11_lambda_functions__ in which case the implementation uses native lambdas instead of local functions in GCC statement expressions. +However, __CXX11_lambda_functions__ do not support constant binding so it is best to only use `const bind variable` (same as `=variable` for __CXX11_lambda_functions__) and `bind& variable` (same as `&variable` for __CXX11_lambda_functions__') because these have the exact same semantic between the local function and the native lambda implementations. +Furthermore, local functions allow to bind data members directly while __CXX11_lambda_functions__ require to access data members via binding the object `this`. +Unfortunately, the short-hand binds `&` and `=` of __CXX11_lambda_functions__ (which automatically bind all variables in scope either by reference or value) are not supported by these GCC lambda function macros because they are not supported by local functions. +Finally, the result type `return `[^['result-type]] is optional and it is assumed `void` when it is not specified (same as with __CXX11_lambda_functions__). [endsect] @@ -45,8 +49,8 @@ For example, consider the following assertion where by mistake we programmed `op assert(x = y); // Mistakenly `=` instead of `==`. Ideally this code will not compile instead this example not only compiles but the assertion even passes the run-time check and no error is generated at all. -The __N1613__ paper introduces the idea of a /const-block/ which could be used to wrap the assertion above and catch the programming error at compile-time. -Similarly, the following code will generate a compile-time error when `operator=` is mistakenly used instead of `operator==` because both `x` and `y` are made constants (using local functions) within the block of code performing the assertion (see also [@../../example/const_block_err.cpp =const_block_err.cpp=]): +The __N1613__ paper introduces the concept of a /const-block/ which could be used to wrap the assertion above and catch the programming error at compile-time. +Similarly, the following code will generate a compile-time error when `operator=` is mistakenly used instead of `operator==` because both `x` and `y` are made constants (using local functions) within the block of code performing the assertion (see also [@../../example/const_block_error.cpp =const_block_error.cpp=]): [table [ [With Local Functions] [N1613 Const-Blocks] ] @@ -58,17 +62,25 @@ Similarly, the following code will generate a compile-time error when `operator= ``] ] ] -Where the macros are defined in [@../../example/const_block.hpp =const_block.hpp=]. +The constant block macros are implemented using local functions (see also [@../../example/const_block.hpp =const_block.hpp=]): + +[const_block_macro] +[const_block_end_macro] The constant block macros are implemented using a local function which binds by constant reference `const bind&` all the specified variables (so the variables are constant within the code block but they do not need to be `CopyConstructible` and no extra copy is performed). -The local function executes the `assert` instruction in its body which is called immediately after it is defined. +The local function executes the `assert` instruction in its body and it is called immediately after it is defined. More in general, constant blocks can be used to evaluate any instruction (not just assertions) within a block were all specified variables are constant. -Unfortunately, constant blocks cannot be implemented with __CPP11_lambda__ functions because these do not support constant binding (of course it is always possible to introduce extra constant variables `const int& const_x = x`, etc and use these variables in the assertion). -Variables bound by value using __CPP11_lambda__ functions (`variable`, `=variable`, and `=`) are constant but they are required to be `CopyConstructible` and they introduce potentially expensive copy operations. +Unfortunately, constant blocks cannot be implemented with __CXX11_lambda_functions__ because these do not support constant binding. +Variables bound by value using __CXX11_lambda_functions__ (`variable`, `=variable`, and `=`) are constant but they are required to be `CopyConstructible` and they introduce potentially expensive copy operations. [footnote -Ideally, __CPP11_lambda__ functions would allow to bind variables also using `const& variable` (constant reference) and `const&` (all variables by constant reference). +Ideally, __CXX11_lambda_functions__ would allow to bind variables also using `const& variable` (constant reference) and `const&` (all variables by constant reference). ] +Of course it is always possible to introduce extra constant variables and bind these variables to the __CXX11_lambda_functions__ but the constant block code will then have to manage the declaration and initialization of these extra variables plus it will have to use the extra variable names instead of the original variable names: + +[const_block_cxx11_lambda] + +In many cases the use of an extra constant variable `const_x` can be acceptable but in other cases it might be preferable to maintain the same variable name `x` within the function body. [endsect] @@ -79,29 +91,30 @@ Scope exits allow to execute arbitrary code at the exit of the enclosing scope a For curiosity, here we show how to re-implement scope exits using local functions. One small advantage of scope exits that use local functions is that they support constant binding. __Boost_ScopeExit__ does not directly support constant binding (however, it is always possible to introduce an extra `const` local variable, assign it to the value to bind, and then bind the `const` variable so to effectively have constant binding with __Boost_ScopeExit__ as well). -In general, the authors recommend to use __Boost_ScopeExit__ instead of the code listed here whenever possible. + +[note +In general, the authors recommend to use __Boost_ScopeExit__ instead of the code listed by this example whenever possible (because __Boost_ScopeExit__ is a library deliberately designed to support the scope exit construct). +] The following example binds `p` by constant reference so this variable cannot be modified within the scope exit body but it is not copied and it will present the value it has at the exit of the enclosing scope and not at the scope exit declaration (see also [@../../example/scope_exit.cpp =scope_exit.cpp=]): [table [ [With Local Functions] [Boost.ScopeExit] ] - [ [[scope_exit]] [ -[pre + [ [[scope_exit]] [`` person& p = persons_.back(); person::evolution_t checkpoint = p.evolution_; BOOST_SCOPE_EXIT(checkpoint, &p, this_) { // Or extra variable `const_p`. if (checkpoint == p.evolution_) this_->persons_.pop_back(); } BOOST_SCOPE_EXIT_END -] - ] ] + ``] ] ] -Where the macros are defined in [@../../example/scope_exit.hpp =scope_exit.hpp=]. - -The scope exit macros are implemented by passing a local function when constructing an object of the following class: +The scope exit macros are implemented by passing a local function when constructing an object of the following class (see also [@../../example/scope_exit.hpp =scope_exit.hpp=]): [scope_exit_class] +[scope_exit_macro] +[scope_exit_end_macro] A local variable within the enclosing scope is used to hold the object so the destructor will be invoked at the exit of the enclosing scope and it will in turn call the local function executing the scope exit instructions. The scope exit local function has no parameter and `void` result type but it supports binding and constant binding. @@ -121,15 +134,15 @@ For example (see also [@../../example/phoenix_factorial_local.cpp =phoenix_facto This is presented here mainly as a curiosity because __Boost_Phoenix__ functions created from local functions have the important limitation that they cannot be polymorphic. [footnote *Rationale.* -Local functions can only be monomorphic because they are implemented using local classes and local classes cannot be templates in C++ (not even in __CPP11__). +Local functions can only be monomorphic because they are implemented using local classes and local classes cannot be templates in C++ (not even in __CXX11__). ] -Therefore, in many cases creating the __Boost_Phoenix__ function from global functors (possibly with the help of __Boost_Phoenix__ adaptor macros) might be a more valuable option. +Therefore, in many cases creating the __Boost_Phoenix__ function from global functors (possibly with the help of __Boost_Phoenix__ adaptor macros) might be a more useful. [endsect] [section Closures] -The following are examples of [@http://en.wikipedia.org/wiki/Closure_(computer_science) closures] that illustrate how to return local functions to the calling scope (and the relative precautions to take). +The following are examples of [@http://en.wikipedia.org/wiki/Closure_(computer_science) closures] that illustrate how to return local functions to the calling scope (note how extra care is taken in order to ensure that all bound variables remain valid at the calling scope): [table [ [Files] ] @@ -143,10 +156,10 @@ The following are examples of [@http://en.wikipedia.org/wiki/Closure_(computer_s [section GCC Nested Functions] -The GCC C compiler supports local functions under the name of [@http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html nested functions]. -Nested functions are exclusively a C extension of the GCC compiler (they are not supported for C++ not even by the GCC compiler, and they are not part of any C or C++ standard, nor they are supported by other compilers like MSVC). +The GCC C compiler supports local functions as a non-standard extension under the name of [@http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html nested functions]. +Note that nested functions are exclusively a C extension of the GCC compiler (they are not supported for C++ not even by the GCC compiler, and they are not part of any C or C++ standard, nor they are supported by other compilers like MSVC). -The following examples are taken form the GCC nested function documentation and programmed using this library: +The following examples are taken form the GCC nested function documentation and programmed using local functions: [table [ [Files] ] @@ -159,15 +172,15 @@ The following examples are taken form the GCC nested function documentation and [section N-Papers] -The following examples are taken from a number of N-papers and programmed using this library. +The following examples are taken from different C++ "N-papers" and programmed using local functions: [table [ [Files] [Notes] ] [ [[@../../example/n2550_find_if.cpp =n2550_find_if.cpp=]] [ -This example is adapted from __N2550__ (__CPP11_lambda__ functions): It passes a local function to the STL algorithm `std::find_if`. +This example is adapted from __N2550__ (__CXX11_lambda_functions__): It passes a local function to the STL algorithm `std::find_if`. ] ] [ [[@../../example/n2529_this.cpp =n2529_this.cpp=]] [ -This example is adapted from __N2529__ (__CPP11_lambda__ functions): It binds the object in scope `this` to a local function. +This example is adapted from __N2529__ (__CXX11_lambda_functions__): It binds the object in scope `this` to a local function. ] ] ] diff --git a/doc/getting_started.qbk b/doc/getting_started.qbk index 65a5269..cdc1628 100644 --- a/doc/getting_started.qbk +++ b/doc/getting_started.qbk @@ -5,9 +5,9 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Getting_Started Getting Started] +[section Getting Started] -This section explains how programmers can setup their system to use this library. +This section explains how to setup a system to use this library. [section This Documentation] @@ -18,25 +18,25 @@ All the other sections of this documentation can be considered optional. Some footnotes are marked by the word "*Rationale*". They explain reasons behind decisions made during the design and implementation of this library. -In some of the examples presented in this documentation, the __Boost_Test__ macro `BOOST_CHECK` is used equivalently to `assert` and the __Boost_Test__ macro `BOOST_AUTO_TEST_CASE` is used equivalently to `main`. +In most of the examples presented in this documentation, the Boost.Detail/LightweightTest (=boost/detail/lightweight_test.hpp=) macro `BOOST_TEST` is used to check correctness conditions. +The `BOOST_TEST` macro is conceptually similar to `assert` but a failure of the checked condition does not abort the program, instead it makes `boost::report_errors` return a non-zero program exit code. [footnote *Rationale.* -Using __Boost_Test__ allows to add the documentation examples to the library regression tests so to make sure that the listed examples always compile and run correctly. +Using Boost.Detail/LightweightTest allows to add the examples to the library regression tests so to make sure that they always compile and run correctly. ] [endsect] [section Compilers and Platforms] -The implementation of this library uses preprocessor and template meta-programming (as supported by __Boost_Preprocessor__ and __Boost_MPL__), templates with partial specializations and function pointers (similarly to __Boost_Function__). -As a consequence, this library is fairly demanding on compilers' compliance with the __CPP03__ standard. -At present, this library has been successfully compiled and tested on the following compilers and platforms: +The implementation of this library uses preprocessor and template meta-programming (as supported by __Boost_Preprocessor__ and __Boost_MPL__), templates with partial specializations and function pointers (similarly to __Boost_Function__), and automatic type deduction (as supported by __Boost_Typeof__). +The authors originally developed and tested the library on: -# GNU Compiler Collection (GCC) 4.5.1 on Ubuntu Linux 10. -# GCC 4.3.4 and 4.5.3 (with and without __CPP11__ features enabled `-std=c++0x`) on Cygwin. -# Miscrosoft Visual Studio Compiler (MSVC) 8.0 on Windows XP and Windows 7. +# GNU Compiler Collection (GCC) C++ 4.5.1 on Ubuntu Linux 10. +# GCC 4.3.4 and 4.5.3 (with and without __CXX11__ features enabled `-std=c++0x`) on Cygwin. +# Miscrosoft Visual C++ (MSVC) 8.0 on Windows XP and Windows 7. -This library has not yet been tested on any other compiler and platform. +See the library [@http://www.boost.org/development/tests/release/developer/local_function.html regressions test results] for detailed information on supported compilers and platforms. [endsect] @@ -46,15 +46,15 @@ This library is composed of header files only. Therefore there is no pre-compiled object file which needs to be installed or linked. Programmers can simply instruct the C++ compiler where to find the library header files (`-I` option for GCC, `/I` option for MSVC, etc) and they can start compiling code using this library. -This library implementation uses a number of __Boost__ libraries among which: __Boost_Preprocessor__, __Boost_ScopeExit__, __Boost_Typeof__, __Boost_TypeTraits__, and __Boost_MPL__. -These __Boost__ libraries must be properly installed on your system in order for this library to work. +The library implementation uses __Boost_Typeof__ to automatically deduce the types of bound variables (see the __Tutorial__ section). +In order to compile code in type-of emulation mode, all types should be properly registered using `BOOST_TYPEOF_REGISTER_TYPE` and `BOOST_TYPEOF_REGISTER_TEMPLATE`, or appropriate __Boost_Typeof__ headers should be included (see the source code of most examples presented in this documentation). The followings are part of the library private API, they are not documented, and they should not be directly used by programmers: [footnote *Rationale.* -This library concatenates symbols specified by the programmers (e.g., the local function name) with other symbols (e.g., special prefixes or preprocessor line numbers) to make internal symbols with unique names to avoid name clashes. +This library concatenates symbols specified by the programmers (e.g., the local function name) with other symbols (e.g., special prefixes or file line numbers) to make internal symbols with unique names to avoid name clashes. These symbols are separated by the letter "`X`" when they are concatenated so they read more easily during debugging (the underscore character "`_`" could not be used instead of the letter "`X`" because if the original symbols already contained a leading or trailing underscore, the concatenation could result in a symbol with double underscores "`__`" which is reserved by the C++ standard). -The "aux" symbols are private to this library while the "detail" symbols can be used within Boost by other libraries but they are still not part of this library public API. +The "aux" symbols are private to this library while the "detail" symbols may be used within Boost by other libraries but they are still not part of this library public API. ] * Any symbol defined by files within the =boost/local_function/aux_/= or =boost/local_function/detail/= directory (these header files should not be directly included by programmers). @@ -62,13 +62,8 @@ The "aux" symbols are private to this library while the "detail" symbols can be * Any symbol prefixed by `boost_local_function_aux_...` or `boost_local_function_detail_...` (regardless of its namespace). * Any symbol prefixed by `BOOST_LOCAL_FUNCTION_AUX_...` or `BOOST_LOCAL_FUNCTION_DETAIL_...` (regardless of its namespace). -[endsect] - -[section Configuration] - Some of the library behaviour can be changed at compile-time by defining special /configuration macros/. If a configuration macro is left undefined, the library will use an appropriate default value for it. - All configuration macros are defined in the header file [headerref boost/local_function/config.hpp]. It is strongly recommended not to change the library configuration macro definitions unless strictly necessary. diff --git a/doc/html/BOOST_LOCAL_FUNCTION.html b/doc/html/BOOST_LOCAL_FUNCTION.html index f6a170e..c09c14e 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION.html +++ b/doc/html/BOOST_LOCAL_FUNCTION.html @@ -33,18 +33,18 @@ BOOST_LOCAL_FUNCTION(declarations)
-

Description

+

Description

This macro must be used within a declarative context, it must follow the local function result type, it must be followed by the local function body code, and then by the BOOST_LOCAL_FUNCTION_NAME macro (see the Tutorial and Advanced Topics sections):

{ // Some declarative context.
     ...
     result_type BOOST_LOCAL_FUNCTION(declarations) {
         ... // Body code.
-    } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name)
+    } BOOST_LOCAL_FUNCTION_NAME(qualified_name)
     ...
 }
 

As usual, exceptions specifications can be optionally programmed just after the macro and before the body code block { ... } (but the exception specifications will only apply to the body code and not to the library code automatically generated by the macro expansion, see the Advanced Topics section).

-

Within templates, the special macro BOOST_LOCAL_FUNCTION_TPL must be used instead of BOOST_LOCAL_FUNCTION.

+

Within templates, the special macros BOOST_LOCAL_FUNCTION_TPL and BOOST_LOCAL_FUNCTION_NAME_TPL must be used.

Parameters:

@@ -71,19 +71,19 @@ returnfunction_result_type On compilers that do not support variadic macros, declaration_tuple cannot be used:
    declarations:
             void | declaration_sequence
-
Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; {expression} means the token resulting from the expression. +(Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; {expression} means the token resulting from the expression.)

-

Note that on compilers that support variadic macros, commas can be used to separate the declarations resembling more closely the usual C++ function declaration syntax. This is the preferred syntax. However, for portability, on all C++ compilers (with and without variadic macros) the same library macros also accept parameter declarations specified as a Boost.Preprocessor sequence separated by round parenthesis ().

+

Note that on compilers that support variadic macros, commas can be used to separate the declarations resembling more closely the usual C++ function declaration syntax (this is the preferred syntax). However, for portability, on all C++ compilers (with and without variadic macros) the same library macros also accept parameter declarations specified as a Boost.Preprocessor sequence separated by round parenthesis ().

When binding the object this, the special symbol this_ needs to be used instead of this as the name of the variable to bind and also within the local function body to access the object. (Mistakenly using this instead of this_ might not always result in a compiler error and will in general result in undefined behaviour.)

The result type must either be specified just before the macro or within the macro declarations prefixed by return (but not in both places).

Within the local function body it possible to access the result type using result_type, the type of the first parameter using arg1_type, the type of the second parameter using arg2_type, etc. The bound variable types can be accessed using BOOST_LOCAL_FUNCTION_TYPEOF.

-

The maximum number of local function parameters (excluding bound variables) is specified by the configuration macro BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX. The maximum number of bound variables is specified by the configuration macro BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.

+

This macro cannot be portably expanded multiple times on the same line. In these cases, use the BOOST_LOCAL_FUNCTION_ID macro instead.

+

The maximum number of local function parameters (excluding bound variables) is specified by the configuration macro BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX. The maximum number of bound variables is specified by the configuration macro BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX. The configuration macro BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS can be used to force optimizations that reduce the local function call run-time overhead.

Note: Local functions are functors so they can be assigned to other functors like boost::function (see Boost.Function).

-

Note: This macro cannot be portably used multiple times on the same line (because on GCC and other compilers, it internally uses the line number __LINE__ to generate unique identifiers).

-

See: Tutorial section, Advanced Topics section, BOOST_LOCAL_FUNCTION_TPL, BOOST_LOCAL_FUNCTION_NAME, BOOST_LOCAL_FUNCTION_TYPEOF, BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX, BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.

+

See: Tutorial section, Advanced Topics section, BOOST_LOCAL_FUNCTION_NAME, BOOST_LOCAL_FUNCTION_TPL, BOOST_LOCAL_FUNCTION_NAME_TPL, BOOST_LOCAL_FUNCTION_TYPEOF, BOOST_LOCAL_FUNCTION_ID, BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX, BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.

diff --git a/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.html b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.html index f3df67d..f15cf20 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.html +++ b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.html @@ -33,7 +33,7 @@ BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX
-

Description

+

Description

If programmers leave this configuration macro undefined, its default value is 5 (increasing this number might increase compilation time). When defined by programmers, this macro must be a non-negative integer number.

Note: This macro specifies the maximum number of local function parameters excluding bound variables (which are instead specified by BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX).

See: Tutorial section, Getting Started section, BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.

diff --git a/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.html b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.html index d984deb..ef43ca2 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.html +++ b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX.html @@ -7,7 +7,7 @@ - +
@@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext
@@ -33,7 +33,7 @@ BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX
-

Description

+

Description

If programmers leave this configuration macro undefined, its default value is 10 (increasing this number might increase compilation time). When defined by programmers, this macro must be a non-negative integer number.

Note: This macro specifies the maximum number of bound variables excluding local function parameters (which are instead specified by BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX).

See: Tutorial section, Getting Started section, BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX.

@@ -50,7 +50,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.html b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.html new file mode 100644 index 0000000..b5fde9a --- /dev/null +++ b/doc/html/BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.html @@ -0,0 +1,66 @@ + + + +Macro BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+
+
+

Macro BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS

+

BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS — Specify when local functions can be passed as template parameters without introducing any run-time overhead.

+
+

Synopsis

+
// In header: <boost/local_function/config.hpp>
+
+BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
+
+

Description

+

If this macro is defined to 1, this library will assume that the compiler allows to pass local classes as template parameters:

+
    template<typename T> void f(void) {}
+
+    int main(void) {
+        struct local_class {};
+        f<local_class>();
+        return 0;
+    }
+
+

This is the case for C++11 compilers and some C++03 compilers (e.g., MSVC), but it is not the case in general for most C++03 compilers (including GCC). This will allow the library to pass local functions as template parameters without introducing any run-time overhead (specifically without preventing the compiler from optimizing local function calls by inlining their assembly code).

+

If this macro is defined to 0 instead, this library will introduce a run-time overhead associated to resolving a function pointer call in order to still allow to pass the local functions as template parameters.

+

It is recommended to leave this macro undefined. In this case, the library will automatically define this macro to 0 if the Boost.Config macro BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS is defined for the specific compiler, and to 1 otherwise.

+

See: Getting Started section, Advanced Topics section, BOOST_LOCAL_FUNCTION_NAME.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/BOOST_LOCAL_FUNCTION_ID.html b/doc/html/BOOST_LOCAL_FUNCTION_ID.html new file mode 100644 index 0000000..c859f96 --- /dev/null +++ b/doc/html/BOOST_LOCAL_FUNCTION_ID.html @@ -0,0 +1,77 @@ + + + +Macro BOOST_LOCAL_FUNCTION_ID + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+
+
+

Macro BOOST_LOCAL_FUNCTION_ID

+

BOOST_LOCAL_FUNCTION_ID — This macro allows to declare multiple local functions on the same line.

+
+

Synopsis

+
// In header: <boost/local_function.hpp>
+
+BOOST_LOCAL_FUNCTION_ID(id, declarations)
+
+

Description

+

This macro is equivalent to BOOST_LOCAL_FUNCTION but it can be expanded multiple times on the same line if different identifiers id are provided for each expansion (see the Advanced Topics section).

+

Parameters:

+
++++ + + + + + + + + + + +
idA unique identifier token which can be concatenated by the preprocessor (__LINE__, local_function_number_1_on_line_123, etc).
declarationsSame as the declarations parameter of the BOOST_LOCAL_FUNCTION macro.
+

+

+

The BOOST_LOCAL_FUNCTION_NAME macro should be used to end each one of the multiple local function declarations as usual (and it will specify a unique name for each local function).

+

Within templates, the special macros BOOST_LOCAL_FUNCTION_TPL_ID must be used.

+

Note: This macro can be useful when the local function macros are expanded within user-defined macros (because macros all expand on the same line). On some compilers (e.g., MSVC which supports the non-standard __COUNTER__ macro) it might not be necessary to use this macro but the use of this macro when expanding multiple local function macros on the same line is always necessary to ensure portability (this is because this library can only portably use __LINE__ to internally generate unique identifiers).

+

See: Advanced Topics section, BOOST_LOCAL_FUNCTION, BOOST_LOCAL_FUNCTION_NAME, BOOST_LOCAL_FUNCTION_TPL_ID.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/BOOST_LOCAL_FUNCTION_NAME.html b/doc/html/BOOST_LOCAL_FUNCTION_NAME.html index 0e656f3..4e843ba 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION_NAME.html +++ b/doc/html/BOOST_LOCAL_FUNCTION_NAME.html @@ -6,8 +6,8 @@ - - + + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext
@@ -31,18 +31,19 @@

Synopsis

// In header: <boost/local_function.hpp>
 
-BOOST_LOCAL_FUNCTION_NAME(qualified_function_name)
+BOOST_LOCAL_FUNCTION_NAME(qualified_name)
-

Description

+

Description

This macro must follow the local function body code block { ... }:

{ // Some declarative context.
     ...
     result_type BOOST_LOCAL_FUNCTION(declarations) {
         ... // Body code.
-    } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name)
+    } BOOST_LOCAL_FUNCTION_NAME(qualified_name)
     ...
 }
 
+

Within templates, the special macros BOOST_LOCAL_FUNCTION_TPL and BOOST_LOCAL_FUNCTION_NAME_TPL must be used.

Parameters:

@@ -50,18 +51,26 @@ - - + +
qualified_function_nameThe name of the local function optionally qualified as follow:
qualified_function_name:
-        [inline] [recursive] name
-
Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; {expression} means the token resulting from the expression.
qualified_nameThe name of the local function optionally qualified as follow:
    name:
+            [inline] [recursive] local_function_name
+
(Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; {expression} means the token resulting from the expression.)

-

The local function name can be qualified by prefixing it with the keyword inline (see the Advanced Topics section): BOOST_LOCAL_FUNCTION_NAME(inline name). This increases the chances that the compiler will be able to inline the local function calls (thus reducing run-time). However, inlined local functions cannot be passed as template parameters (e.g., to std::for_each) or assigned to other functors (e.g., to boost::function). That is true on C++03 compilers but inlined local functions can instead be passed as template parameters on C++11 compilers. On C++11 compilers, there is no need to declare a local function lined because this library will automatically use C++11 specific features to inline the local function while always allowing to pass it as a template parameter.

-

The local function name can also be qualified by prefixing it with the "keyword" recursive (see the Advanced Topics section): BOOST_LOCAL_FUNCTION_NAME(recursive name). This allows the local function to recursively call itself from its body (as usual in C++). However, compilers have not been observed to be able to inline recursive local function calls (not even when the recursive local function is also declared inline: BOOST_LOCAL_FUNCTION(inline recursive name)). Furthermore, recursive local functions should only be called within their declaration scope (otherwise the result is undefined behaviour).

+

The local function name can be qualified by prefixing it with the keyword inline (see the Advanced Topics section):

+
    BOOST_LOCAL_FUNCTION_NAME(inline local_function_name)
+
+

This increases the chances that the compiler will be able to inline the local function calls (thus reducing run-time). However, inline local functions cannot be passed as template parameters (e.g., to std::for_each) or assigned to other functors (e.g., to boost::function). That is true on C++03 compilers but inline local functions can instead be passed as template parameters on C++11 compilers. On C++11 compilers, there is no need to declare a local function lined because this library will automatically use C++11 specific features to inline the local function while always allowing to pass it as a template parameter. This optimization is automatically enabled when the Boost.Config macro BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS is not defined but it also be forced using BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS.

+

The local function name can also be qualified by prefixing it with the "keyword" recursive (see the Advanced Topics section):

+
    BOOST_LOCAL_FUNCTION_NAME(recursive local_function_name)
+
+

This allows the local function to recursively call itself from its body (as usual in C++). However, recursive local functions should only be called within their declaration scope (otherwise the result is undefined behaviour). Finally, compilers have not been observed to be able to inline recursive local function calls, not even when the recursive local function is also declared inline:

+
    BOOST_LOCAL_FUNCTION(inline recursive local_function_name)
+

Note: The local function name cannot be the name of an operator operator... and it cannot be the same name of another local function declared within the same enclosing scope (but boost::overloaded_function can be used to overload local functions, see Boost.Functional/OverloadedFunction and the Advanced Topics section).

-

See: Tutorial section, Advanced Topics section, BOOST_LOCAL_FUNCTION.

+

See: Tutorial section, Advanced Topics section, BOOST_LOCAL_FUNCTION, BOOST_LOCAL_FUNCTION_NAME_TPL.

@@ -75,7 +84,7 @@

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/BOOST_LOCAL_FUNCTION_NAME_TPL.html b/doc/html/BOOST_LOCAL_FUNCTION_NAME_TPL.html new file mode 100644 index 0000000..8440f1f --- /dev/null +++ b/doc/html/BOOST_LOCAL_FUNCTION_NAME_TPL.html @@ -0,0 +1,65 @@ + + + +Macro BOOST_LOCAL_FUNCTION_NAME_TPL + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+
+
+

Macro BOOST_LOCAL_FUNCTION_NAME_TPL

+

BOOST_LOCAL_FUNCTION_NAME_TPL — This macro is used to end a local function declaration specifying its name within templates.

+
+

Synopsis

+
// In header: <boost/local_function.hpp>
+
+BOOST_LOCAL_FUNCTION_NAME_TPL(name)
+
+

Description

+

This macro must be used instead of BOOST_LOCAL_FUNCTION_NAME when declaring a local function within a template. A part from that, this macro has the exact same syntax a BOOST_LOCAL_FUNCTION_NAME (see BOOST_LOCAL_FUNCTION_NAME for more information):

+
{ // Some declarative context within a template.
+    ...
+    result_type BOOST_LOCAL_FUNCTION_TPL(declarations) {
+        ... // Body code.
+    } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name)
+    ...
+}
+
+

Note that BOOST_LOCAL_FUNCTION_TPL must be used with this macro instead of BOOST_LOCAL_FUNCTION.

+

Note: C++03 does not allow to use typename outside templates. This library internally manipulates types, these operations require typename but only within templates. This macro is used to indicate to the library when the enclosing scope is a template so the library can correctly use typename.

+

See: Tutorial section, BOOST_LOCAL_FUNCTION_NAME, BOOST_LOCAL_FUNCTION_TPL.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/BOOST_LOCAL_FUNCTION_TPL.html b/doc/html/BOOST_LOCAL_FUNCTION_TPL.html index 5365341..be7e794 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION_TPL.html +++ b/doc/html/BOOST_LOCAL_FUNCTION_TPL.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext
@@ -33,18 +33,20 @@ BOOST_LOCAL_FUNCTION_TPL(declarations)
-

Description

-

This macro must be used instead of BOOST_LOCAL_FUNCTION when declaring a local function within a template. A part from that, this macro has the exact same syntax as BOOST_LOCAL_FUNCTION (see BOOST_LOCAL_FUNCTION for more information):

-
{ // Some declarative context with a template.
+

Description

+

This macro must be used instead of BOOST_LOCAL_FUNCTION when declaring a local function within a template. A part from that, this macro has the exact same syntax a BOOST_LOCAL_FUNCTION (see BOOST_LOCAL_FUNCTION for more information):

+
{ // Some declarative context within a template.
     ...
     result_type BOOST_LOCAL_FUNCTION_TPL(declarations) {
         ... // Body code.
-    } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name)
+    } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name)
     ...
 }
 
-

Note: C++03 does not allow to use typename outside templates. This library internally manipulates types, these operations require typename but only within templates so this macro is used to indicate to the library when the enclosing scope is a template.

-

See: Tutorial section, BOOST_LOCAL_FUNCTION, BOOST_LOCAL_FUNCTION_NAME.

+

Note that BOOST_LOCAL_FUNCTION_NAME_TPL must be used with this macro instead of BOOST_LOCAL_FUNCTION_NAME.

+

This macro cannot be portably expanded multiple times on the same line. In these cases, use the BOOST_LOCAL_FUNCTION_TPL_ID macro instead.

+

Note: C++03 does not allow to use typename outside templates. This library internally manipulates types, these operations require typename but only within templates. This macro is used to indicate to the library when the enclosing scope is a template so the library can correctly use typename.

+

See: Tutorial section, BOOST_LOCAL_FUNCTION, BOOST_LOCAL_FUNCTION_TPL_ID, BOOST_LOCAL_FUNCTION_NAME_TPL.

@@ -58,7 +60,7 @@

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/BOOST_LOCAL_FUNCTION_TPL_ID.html b/doc/html/BOOST_LOCAL_FUNCTION_TPL_ID.html new file mode 100644 index 0000000..9030137 --- /dev/null +++ b/doc/html/BOOST_LOCAL_FUNCTION_TPL_ID.html @@ -0,0 +1,77 @@ + + + +Macro BOOST_LOCAL_FUNCTION_TPL_ID + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+
+
+

Macro BOOST_LOCAL_FUNCTION_TPL_ID

+

BOOST_LOCAL_FUNCTION_TPL_ID — This macro allows to declare multiple local functions on the same line within templates.

+
+

Synopsis

+
// In header: <boost/local_function.hpp>
+
+BOOST_LOCAL_FUNCTION_TPL_ID(id, declarations)
+
+

Description

+

This macro must be used instead of BOOST_LOCAL_FUNCTION_TPL when declaring multiple local functions on the same line within a template. A part from that, this macro has the exact same syntax as BOOST_LOCAL_FUNCTION_TPL (see BOOST_LOCAL_FUNCTION_TPL for more information).

+

Parameters:

+
++++ + + + + + + + + + + +
idA unique identifier token which can be concatenated by the preprocessor (__LINE__, local_function_number_1_on_line_123, etc).
declarationsSame as the declarations parameter of the BOOST_LOCAL_FUNCTION_TPL macro.
+

+

+

The BOOST_LOCAL_FUNCTION_NAME macro should be used to end each one of the multiple local function declarations as usual (and it will specify a unique name for each local function).

+

Outside template, the macro BOOST_LOCAL_FUNCTION_ID should be used to declare multiple local functions on the same line.

+

Note: This macro can be useful when the local function macros are expanded within user-defined macros (because macros all expand on the same line). On some compilers (e.g., MSVC which supports the non-standard __COUNTER__ macro) it might not be necessary to use this macro but the use of this macro when expanding multiple local function macros on the same line is always necessary to ensure portability (this is because this library can only portably use __LINE__ to internally generate unique identifiers).

+

See: Advanced Topics section, BOOST_LOCAL_FUNCTION_TPL, BOOST_LOCAL_FUNCTION_NAME, BOOST_LOCAL_FUNCTION_ID.

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/BOOST_LOCAL_FUNCTION_TYPEOF.html b/doc/html/BOOST_LOCAL_FUNCTION_TYPEOF.html index feb7339..4138aa4 100644 --- a/doc/html/BOOST_LOCAL_FUNCTION_TYPEOF.html +++ b/doc/html/BOOST_LOCAL_FUNCTION_TYPEOF.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
-PrevUpHomeNext +PrevUpHomeNext
@@ -33,7 +33,7 @@ BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name)
-

Description

+

Description

This macro can be used within the local functions body to refer to the bound variable types so to declare local variables, check concepts (using Boost.ConceptCheck), etc (see the Advanced Topics section). This way the local function can be programmed entirely without explicitly specifying the bound variable types thus facilitating maintenance (e.g., if the type of a bound variable changes in the enclosing scope, the local function code does not have to change).

Parameters:

@@ -56,8 +56,8 @@
  • Bound by constant reference using const bind& t then BOOST_LOCAL_FUNCTION_TYPEOF(t) is const T&.

  • -This macro must be prefixed by typename when used in a type dependant context.

    -

    It is best to use this macro instead of Boost.Typeof so to reduce the number of times Boost.Typeof is used to deduce types (see the Advanced Topics section).

    +This macro must be prefixed by typename when used within templates.

    +

    Note: It is best to use this macro instead of Boost.Typeof so to reduce the number of times Boost.Typeof is used to deduce types (see the Advanced Topics section).

    See: Advanced Topics section, BOOST_LOCAL_FUNCTION.

    @@ -72,7 +72,7 @@ This macro must be prefixed by typename when

    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_localfunction/Acknowledgments.html b/doc/html/boost_localfunction/Acknowledgments.html index c7d3217..f9ef40d 100644 --- a/doc/html/boost_localfunction/Acknowledgments.html +++ b/doc/html/boost_localfunction/Acknowledgments.html @@ -33,7 +33,7 @@

    Many thanks to Steven Watanabe and Vicente Botet for suggesting to me to use Boost.ScopeExit binding - to emulate + to emulate local functions. Many thanks to Alexander Nasonov for clarifying how Boost.ScopeExit binding could be used to implement local functions and for some early @@ -71,13 +71,12 @@ section and with the profiling of the different alternatives.

    - Many thanks to the library's Boost - review manager: Jeffrey Lee Hellrung. Thanks also to all the people - that submitted a (positive and negative) review: Andrzej Krzemienski, Edward - Diener, Gregory Crosswhite, John Bytheway, Hartmut Kaiser, Krzysztof Czainski, - Nat Lindon, Pierre Morcello, Thomas Heller, and Vicente J. Botet. Thanks to - everyone else that commented (positively and negatively) on the library during - its Boost review. + Many thanks to Jeffrey Lee Hellrung for managing the Boost + review of this library. Thanks also to all the people that submitted + a Boost review: Andrzej Krzemienski, Edward Diener, Gregory Crosswhite, John + Bytheway, Hartmut Kaiser, Krzysztof Czainski, Nat Lindon, Pierre Morcello, + Thomas Heller, and Vicente J. Botet. Thanks to everyone that commented on the + library during its Boost review.

    Finally, many thanks to the entire Boost diff --git a/doc/html/boost_localfunction/Advanced_Topics.html b/doc/html/boost_localfunction/Advanced_Topics.html index 8f411cd..d0afe18 100644 --- a/doc/html/boost_localfunction/Advanced_Topics.html +++ b/doc/html/boost_localfunction/Advanced_Topics.html @@ -31,26 +31,28 @@ Parameters

    Commas and Symbols in Macros
    -
    Assigning - and Returning
    +
    Assignments + and Returns
    Nesting
    Accessing Types (concepts, etc)
    -
    Specifying - Types
    +
    Specifying + Types (no Boost.Typeof)
    Inlining
    Recursion
    Overloading
    Exception Specifications
    -
    Storage - Classifiers (auto and register)
    +
    Storage + Classifiers
    +
    Same + Line Expansions
    Limitations (operators, etc)

    - This section illustrates advanced usages of this library (at the bottom there - is also a list of known limitations of the library). + This section illustrates advanced usage of this library. At the bottom there + is also a list of known limitations of this library.

    @@ -58,10 +60,9 @@ Parameters

    - This library also allows to specify default values for the local function - parameters. However, the usual C++ syntax for default parameters that uses - the assignment symbol = cannot - be used. [17] The keyword default + This library allows to specify default values for the local function parameters. + However, the usual C++ syntax for default parameters that uses the assignment + symbol = cannot be used. [17] The keyword default is used instead:

    parameter-type parameter-name, default parameter-default-value, ...
    @@ -75,18 +76,18 @@
           

    -
    int BOOST_LOCAL_FUNCTION(int x, int y, default 2) { // Default.
    +
    int BOOST_LOCAL_FUNCTION(int x, int y, default 2) { // Default parameter.
         return x + y;
     } BOOST_LOCAL_FUNCTION_NAME(add)
     
    -BOOST_CHECK( add(1) == 3 );
    +BOOST_TEST(add(1) == 3);
     

    Programmers can define a WITH_DEFAULT macro similar to the following if they think it improves readability over - the syntax above (see also add_with_default.cpp): + the above syntax (see also add_with_default.cpp): [18]

    @@ -101,7 +102,7 @@ return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) -BOOST_CHECK( add(1) == 3 ); +BOOST_TEST(add(1) == 3);

    @@ -114,7 +115,7 @@

    The C++ preprocessor does not allow commas , within macro parameters unless they are wrapped by round parenthesis () (see the Boost.Utility/IdentityType - documentation for details). Therefore, using commas within the local function + documentation for details). Therefore, using commas within local function parameters and bindings will generate (cryptic) preprocessor errors unless they are wrapped with an extra set of round parenthesis () as explained here. @@ -159,9 +160,8 @@ after the first template parameter std::string. This comma is not wrapped by any round parenthesis () thus it will cause a preprocessor error. [20] The Boost.Utility/IdentityType - macro BOOST_IDENTITY_TYPE(parenthesized-type) from the header boost/utility/identity_type.hpp - can be used to wrap a type within extra parenthesis () - so to overcome the problem: + macro BOOST_IDENTITY_TYPE((type-with-commas)) defined in the boost/utility/identity_type.hpp + header can be used to wrap a type within extra parenthesis () so to overcome this problem:

    #include <boost/utility/identity_type.hpp>
     
    @@ -174,11 +174,12 @@
     

    This macro expands to an expression that evaluates (at compile-time) exactly - to the specified type. Note that a total of two set of parenthesis () are needed: The parenthesis to invoke the - BOOST_IDENTITY_TYPE(...) - macro plus the parenthesis to wrap the type expression (and therefore any - comma , that it contains) passed - as parameter to the BOOST_IDENTITY_TYPE((...)) macro. Finally, the BOOST_IDENTITY_TYPE macro must be prefixed + to the specified type (furthermore, this macro does not use variadic macros + so it works on any C++03 + compiler). Note that a total of two set of parenthesis () + are needed: The parenthesis to invoke the BOOST_IDENTITY_TYPE(...) macro plus the parenthesis to wrap the + type expression (and therefore any comma , + that it contains) passed as parameter to the BOOST_IDENTITY_TYPE((...)) macro. Finally, the BOOST_IDENTITY_TYPE macro must be prefixed by the typename keyword typename BOOST_IDENTITY_TYPE(parenthesized-type) when used together with the BOOST_LOCAL_FUNCTION_TPL macro within templates.

    @@ -207,9 +208,8 @@

    (2) The parameter type ::sign_t starts with the non-alphanumeric symbols :: thus it will generate - preprocessor errors if used as a local function parameter type. The macros - BOOST_IDENTITY_TYPE can also - be used to overcome this issue: + preprocessor errors if used as a local function parameter type. The BOOST_IDENTITY_TYPE macro can also be used + to overcome this issue:

    void BOOST_LOCAL_FUNCTION(
         ...
    @@ -249,7 +249,7 @@
             first template parameter std::string.
             Again, this comma is not wrapped by any parenthesis ()
             so it will cause a preprocessor error. Because this is a value expression
    -        (and not a type expression), it can be simply wrapped within an extra set
    +        (and not a type expression), it can simply be wrapped within an extra set
             of round parenthesis ():
           

    void BOOST_LOCAL_FUNCTION(
    @@ -285,14 +285,14 @@
     

    -
    +

    Local functions are function objects so it is possible to assign them to - other functors like Boost.Function + other functors like Boost.Function's boost::function in order to store the local function into a variable, pass it as a parameter to another function, or return it from the enclosing function. @@ -302,8 +302,8 @@

    -
    void call1(boost::function<int (int) > f) { BOOST_CHECK( f(1) == 5 ); }
    -void call0(boost::function<int (void)> f) { BOOST_CHECK( f() == 5 ); }
    +
    void call1(boost::function<int (int) > f) { BOOST_TEST(f(1) == 5); }
    +void call0(boost::function<int (void)> f) { BOOST_TEST(f() == 5); }
     
     boost::function<int (int, int)> linear(const int& slope) {
         int BOOST_LOCAL_FUNCTION(const bind& slope,
    @@ -312,7 +312,7 @@
         } BOOST_LOCAL_FUNCTION_NAME(lin)
     
         boost::function<int (int, int)> f = lin; // Assign to local variable.
    -    BOOST_CHECK( f(1, 2) == 5 );
    +    BOOST_TEST(f(1, 2) == 5);
     
         call1(lin); // Pass to other functions.
         call0(lin);
    @@ -322,29 +322,30 @@
     
     void call(void) {
         boost::function<int (int, int)> f = linear(2);
    -    BOOST_CHECK( f(1, 2) == 5 );
    +    BOOST_TEST(f(1, 2) == 5);
     }
     

    -

    - Note that: -

    -
    +
    - - + +
    [Important]Important[Warning]Warning

    As with C++11 - lambda functions, programmers are responsible to ensure that bound - references are valid in any scope where the local function object is called. - (This might be tricky to verify in a program when local functions are returned - and called outside the local scope of their declaration.) + lambda functions, programmers are responsible to ensure that bound + variables are valid in any scope where the local function object is called. + Returning and calling a local function outside its declaration scope will + lead to undefined behaviour if any of the bound variable is no longer valid + in the scope where the local function is called (see the Examples + section for more examples on the extra care needed when returning a local + function as a closure). It is always safe instead to call a local function + within its enclosing scope.

    - In addition, a local function can bind and call another local function. Local + In addition, a local function can bind and call other local functions. Local functions should always be bound by constant reference const bind& to avoid unnecessary copies. For example, the following local function inc_sum binds the local function inc so inc_sum @@ -357,7 +358,7 @@ std::vector<int> w; for(int i = 1; i <= 2; ++i) v.push_back(i * 10); -BOOST_CHECK( v[0] == 10 ); BOOST_CHECK( v[1] == 20 ); +BOOST_TEST(v[0] == 10); BOOST_TEST(v[1] == 20); w.resize(v.size()); int BOOST_LOCAL_FUNCTION(const bind& offset, int i) { @@ -365,7 +366,7 @@ } BOOST_LOCAL_FUNCTION_NAME(inc) std::transform(v.begin(), v.end(), w.begin(), inc); -BOOST_CHECK( w[0] == 16 ); BOOST_CHECK( w[1] == 26 ); +BOOST_TEST(w[0] == 16); BOOST_TEST(w[1] == 26); int BOOST_LOCAL_FUNCTION(bind& inc, int i, int j) { return inc(i + j); // Call the other bound local function. @@ -373,7 +374,7 @@ offset = 0; std::transform(v.begin(), v.end(), w.begin(), v.begin(), inc_sum); -BOOST_CHECK( v[0] == 27 ); BOOST_CHECK( v[1] == 47 ); +BOOST_TEST(v[0] == 27); BOOST_TEST(v[1] == 47);

    @@ -410,9 +411,12 @@ Types (concepts, etc)

    - This library never requires to explicitly specify the type of bound variables. - From within local functions, programmers can access the type of a bound variable - using the following macro: + This library never requires to explicitly specify the type of bound variables + (e.g., this reduces maintenance because the local function declaration and + definition do not have to change even if the bound variable types change + as long as the semantics of the local function remain valid). From within + local functions, programmers can access the type of a bound variable using + the following macro:

    BOOST_LOCAL_FUNCTION_TYPEOF(bound-variable-name)
     
    @@ -440,10 +444,10 @@
    int sum = 0, factor = 10;
     
     void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    -    // Typeof for concept checking.
    +    // Type-of for concept checking.
         BOOST_CONCEPT_ASSERT((Addable<boost::remove_reference<
                 BOOST_LOCAL_FUNCTION_TYPEOF(sum)>::type>));
    -    // Typeof for declarations.
    +    // Type-of for declarations.
         boost::remove_reference<BOOST_LOCAL_FUNCTION_TYPEOF(
                 factor)>::type mult = factor * num;
         sum += mult;
    @@ -471,7 +475,7 @@
             BOOST_CONCEPT_ASSERT((Addable<typename boost::remove_reference<
                     BOOST_LOCAL_FUNCTION_TYPEOF(sum)>::type>));
             sum += factor * num;
    -    } BOOST_LOCAL_FUNCTION_NAME(add)
    +    } BOOST_LOCAL_FUNCTION_NAME_TPL(add)
     
         add(6);
         return sum;
    @@ -480,23 +484,15 @@
     

    - It is best to use the BOOST_LOCAL_FUNCTION_TYPEOF + In this context, it is best to use the BOOST_LOCAL_FUNCTION_TYPEOF macro instead of using Boost.Typeof - so to reduce the number of times that Boost.Typeof - is invoked: + to reduce the number of times that Boost.Typeof + is invoked (either the library already internally used Boost.Typeof + once, in which case using this macro will not use Boost.Typeof + again, or the bound variable type is explicitly specified by programmers + as shown be below, in which case using this macro will not use Boost.Typeof + at all).

    -
      -
    1. - Either the library already internally used Boost.Typeof - once, in which case using this macro will not use Boost.Typeof - again. -
    2. -
    3. - Or, the bound variable type is explicitly specified by programmers (see - below), in which case using this macro will not use Boost.Typeof - at all. -
    4. -

    Furthermore, within the local function body it possible to access the result type using result_type, the @@ -505,15 +501,15 @@ etc. [21]

    -
    +

    - While not required, it is possible to explicitly specify the type of a bound - variable so the library will not internally use Boost.Typeof - to automatically deduce such a type. When specified, the bound variable type + While not required, it is possible to explicitly specify the type of bound + variables so the library will not internally use Boost.Typeof + to automatically deduce the types. When specified, the bound variable type must follow the bind "keyword" and it must be wrapped within round parenthesis ():

    @@ -546,23 +542,23 @@ Note that the result type must be specified only once either before the macro (without the return prefix) or as one of the macro parameters (with the return - prefix). As usual, the result type can always be void - to declare a function returning nothing (so return + prefix). As always, the result type can be void + to declare a function that returns nothing (so return void is allowed when the result type is specified as one of the macro parameters).

    The following example specifies all bound variables and result types (see also add_typed.cpp): - [22] + [22]

    struct adder {
    -    adder(): sum_(0) {}
    +    adder(void) : sum_(0) {}
     
         int sum(const std::vector<int>& nums, const int& factor = 10) {
    -        // Explicitly specify bound variable and result types.
    +        // Explicitly specify bound variable and return types (no type-of).
             BOOST_LOCAL_FUNCTION(const bind(const int&) factor,
                     bind(adder*) this_, int num, return int) {
                 return this_->sum_ += factor * num;
    @@ -571,6 +567,7 @@
             std::for_each(nums.begin(), nums.end(), add);
             return sum_;
         }
    +
     private:
         int sum_;
     };
    @@ -581,7 +578,7 @@
             Unless necessary, it is recommended to not specify the bound variable and
             result types. Let the library deduce these types so the local function syntax
             will be more concise and the local function declaration will not have to
    -        change if a bound variable type changes (facilitating maintenance).
    +        change if a bound variable type changes (reducing maintenance).
           

    @@ -589,10 +586,8 @@
    Note

    - Unfortunately, even when all bound variables and result types are explicitly - specified, the currently library implementation still has to use Boost.Typeof once (to deduce - the local function object type, see the Implementation - section). + When all bound variable and result types are explicitly specified, the + library implementation will not use Boost.Typeof.

    @@ -601,10 +596,10 @@ Inlining

    - Local functions can be declared inline to increase the chances that the compiler - will be able to reduce the run-time of the local function call by inlining - the generated assembly code. A local function is declared inline by prefixing - its name with the keyword inline: + Local functions can be declared inline + to increase the chances that the compiler will be able to reduce the run-time + of the local function call by inlining the generated assembly code. A local + function is declared inline by prefixing its name with the keyword inline:

    result-type BOOST_LOCAL_FUNCTION(parameters) {
         ... // Body.
    @@ -616,10 +611,10 @@
     
    • On C++03 - compliant compilers, inlined local functions always have a run-time comparable + compliant compilers, inline local functions always have a run-time comparable to their equivalent implementation that uses local functors (see the Alternatives - section). However, inlined local functions have the important limitation + section). However, inline local functions have the important limitation that they cannot be assigned to other functors (like boost::function) and they cannot be passed as template parameters.
    • @@ -660,7 +655,7 @@ void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { sum += factor * num; -} BOOST_LOCAL_FUNCTION_NAME(inline add) // Inlined. +} BOOST_LOCAL_FUNCTION_NAME(inline add) // Inlining. std::vector<int> v(100); std::fill(v.begin(), v.end(), 1); @@ -678,7 +673,7 @@ Local functions can be declared recursive so a local function can recursively call itself from its body (as usual with C++ functions). A local function is declared recursive by prefixing its name - with the "keyword" recursive + with the recursive "keyword" (thus recursive cannot be used as a local function name):

      @@ -715,9 +710,13 @@

      Compilers have not been observed to be able to inline recursive local function - calls (not even when the recursive local function is also declared inline - as in BOOST_LOCAL_FUNCTION_NAME(inline recursive - factorial)). + calls not even when the recursive local function is also declared inline: +

      +
      ... BOOST_LOCAL_FUNCTION_NAME(inline recursive factorial)
      +
      +

      + Recursive local functions should never be called outside their declaration + scope. [24]

      @@ -725,25 +724,27 @@
      Warning

      - Recursive local functions should never be called outside their declaration - scope. If a local function is returned from the enclosing function and - called in a different scope, the behaviour is undefined (and it will likely - result in a run-time error). [24] This is not a limitation with respect to C++11 - lambda functions because lambdas can never call themselves recursively - (in other words, there is no recursive lambda function that can successfully - be called outside its declaration scope because there is no recursive lambda - function at all). + If a local function is returned from the enclosing function and called + in a different scope, the behaviour is undefined (and it will likely result + in a run-time error).

      +

      + This is not a limitation with respect to C++11 + lambda functions because lambdas can never call themselves recursively + (in other words, there is no recursive lambda function that can successfully + be called outside its declaration scope because there is no recursive lambda + function at all). +

    - It is possible to overload local functions using the boost::overloaded_function - functor of Boost.Functional/OverloadedFunction - from the header boost/functional/overloaded_function.hpp + Because local functions are functors, it is possible to overload them using + the boost::overloaded_function functor of Boost.Functional/OverloadedFunction + from the boost/functional/overloaded_function.hpp header (see the Boost.Functional/OverloadedFunction documentation for details).

    @@ -756,31 +757,33 @@

    int add_i(int x, int y) { return x + y; }
    +
    +

    +

    +

    +

    +
    std::string s = "abc";
    +std::string BOOST_LOCAL_FUNCTION(
    +        const bind& s, const std::string& x) {
    +    return s + x;
    +} BOOST_LOCAL_FUNCTION_NAME(add_s)
     
    -BOOST_AUTO_TEST_CASE( test_overload ) {
    -    std::string s = "abc";
    -    std::string BOOST_LOCAL_FUNCTION(
    -            const bind& s, const std::string& x) {
    -        return s + x;
    -    } BOOST_LOCAL_FUNCTION_NAME(add_s)
    +double d = 1.23;
    +double BOOST_LOCAL_FUNCTION(const bind d, double x, double y, default 0) {
    +    return d + x + y;
    +} BOOST_LOCAL_FUNCTION_NAME(add_d)
     
    -    double d = 1.23;
    -    double BOOST_LOCAL_FUNCTION(const bind d, double x, double y, default 0) {
    -        return d + x + y;
    -    } BOOST_LOCAL_FUNCTION_NAME(add_d)
    +boost::overloaded_function<
    +      std::string (const std::string&)
    +    , double (double)
    +    , double (double, double) // Overload giving default param.
    +    , int (int, int)
    +> add(add_s, add_d, add_d, add_i); // Overloaded function object.
     
    -    boost::overloaded_function<
    -          std::string (const std::string&)
    -        , double (double)
    -        , double (double, double) // Overload giving default param.
    -        , int (int, int)
    -    > add(add_s, add_d, add_d, add_i); // Overloaded function object.
    -
    -    BOOST_CHECK( add("xyz") == "abcxyz" ); // Call `add_s`.
    -    BOOST_CHECK( fabs(add(3.21) - 4.44) < 0.001 ); // Call `add_d` (no default).
    -    BOOST_CHECK( fabs(add(3.21, 40.0) - 44.44) < 0.001); // Call `add_d`.
    -    BOOST_CHECK( add(1, 2) == 3 ); // Call `add_i`.
    -}
    +BOOST_TEST(add("xyz") == "abcxyz"); // Call `add_s`.
    +BOOST_TEST(fabs(add(3.21) - 4.44) < 0.001); // Call `add_d` (no default).
    +BOOST_TEST(fabs(add(3.21, 40.0) - 44.44) < 0.001); // Call `add_d`.
    +BOOST_TEST(add(1, 2) == 3); // Call `add_i`.
     

    @@ -828,15 +831,15 @@

    -
    +

    Local function parameters support the storage classifiers as usual in C++03. The auto storage classifier - is specified as: [25] + is specified as: [25]

    auto parameter-type parameter-name
     
    @@ -858,6 +861,86 @@

    +
    + +

    + In general, it is not possible to expand the BOOST_LOCAL_FUNCTION, + BOOST_LOCAL_FUNCTION_TPL + macros multiple times on the same line. [26] +

    +

    + Therefore, this library provides additional macros BOOST_LOCAL_FUNCTION_ID + and BOOST_LOCAL_FUNCTION_TPL_ID + which can be expanded multiple times on the same line as long as programmers + specify unique identifiers as the macros' first parameters. The unique identifier + can be any token (not just numeric) that can be successfully concatenated + by the preprocessor (e.g., local_function_number_1_at_line_123). + [27] +

    +

    + The BOOST_LOCAL_FUNCTION_ID + and BOOST_LOCAL_FUNCTION_TPL_ID + macros accept local function parameter declaration lists using the exact + same syntax as BOOST_LOCAL_FUNCTION. + For example (see also same_line.cpp): +

    +

    +

    +
    #define LOCAL_INC_DEC(offset) \
    +    int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(inc, __LINE__), /* unique ID */ \
    +            const bind offset, const int x) { \
    +        return x + offset; \
    +    } BOOST_LOCAL_FUNCTION_NAME(inc) \
    +    \
    +    int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(dec, __LINE__), \
    +            const bind offset, const int x) { \
    +        return x - offset; \
    +    } BOOST_LOCAL_FUNCTION_NAME(dec)
    +
    +#define LOCAL_INC_DEC_TPL(offset) \
    +    int BOOST_LOCAL_FUNCTION_TPL_ID(BOOST_PP_CAT(inc, __LINE__), \
    +            const bind offset, const int x) { \
    +        return x + offset; \
    +    } BOOST_LOCAL_FUNCTION_NAME(inc) \
    +    \
    +    int BOOST_LOCAL_FUNCTION_TPL_ID(BOOST_PP_CAT(dec, __LINE__), \
    +            const bind offset, const int x) { \
    +        return x - offset; \
    +    } BOOST_LOCAL_FUNCTION_NAME(dec)
    +
    +template<typename T>
    +void f(int delta) {
    +    LOCAL_INC_DEC_TPL(delta) // Multiple local functions on same line.
    +    /** @todo back to BOOST_TEST(dec(inc(123)) == 123)) and doc that on vacpp compiler composition doesn't work */
    +    BOOST_TEST(inc(123) == 123 + delta);
    +    BOOST_TEST(dec(123) == 123 - delta);
    +}
    +
    +int main(void) {
    +    int delta = 10;
    +
    +    LOCAL_INC_DEC(delta) // Multiple local functions on same line.
    +    /** @todo back to BOOST_TEST(dec(inc(123)) == 123)) and doc that on vacpp compiler composition doesn't work */
    +    BOOST_TEST(inc(123) == 123 + delta);
    +    BOOST_TEST(dec(123) == 123 - delta);
    +
    +    f(delta);
    +    return boost::report_errors();
    +}
    +
    +

    +

    +

    + As shown by the example above, the BOOST_LOCAL_FUNCTION_ID + and BOOST_LOCAL_FUNCTION_TPL_ID + macros are especially useful when it is necessary to invoke them multiple + times within a user-defined macro (because the preprocessor expands all nested + macros on the same line). +

    +

    Limitations @@ -899,7 +982,7 @@

    - No + No.

    @@ -918,7 +1001,7 @@

    - No + No.

    @@ -937,7 +1020,7 @@

    - No + No.

    @@ -954,17 +1037,16 @@

    - Yes + Yes.

    Local functions can be specified inline to improve the chances that C++03 - standard compilers can optimize the local function call run-time - (but inline local - functions cannot be passed as template parameters on C++03 - standard compilers, see the Advanced + compilers can optimize the local function call run-time (but inline local functions cannot be + passed as template parameters on C++03 + compilers, see the Advanced Topics section).

    @@ -977,7 +1059,7 @@

    - No + No.

    @@ -995,7 +1077,7 @@

    - No + No.

    @@ -1012,7 +1094,7 @@

    - No + No.

    @@ -1030,7 +1112,7 @@

    - Yes + Yes.

    @@ -1048,7 +1130,7 @@

    - Yes + Yes.

    @@ -1068,7 +1150,7 @@

    - Yes + Yes.

    @@ -1090,7 +1172,7 @@

    - No + No.

    @@ -1108,7 +1190,7 @@

    - No + No.

    @@ -1125,7 +1207,7 @@ because it seemed of no use given that local functions can be bound to one another thus they can simply call each other directly without recurring - to dynamic binding or base function call. + to dynamic binding or base function calls.

    @@ -1134,27 +1216,16 @@

    Local functions cannot be operators. Naming a local function operator... - will generate a compile-time error. [26] + will generate a compile-time error. [28]

    - For example, the following code will not compile: + For example, the following code does not compile (see also operator_error.cpp):

    -
    struct point {
    -    int x;
    -    int y;
    -};
    -
    -BOOST_AUTO_TEST_CASE( test_operator_err ) {
    -    bool BOOST_LOCAL_FUNCTION(const point& p, const point& q) {
    -        return p.x == q.x && p.y == q.y;
    -    } BOOST_LOCAL_FUNCTION_NAME(operator==) // Error: Cannot use `operator...`.
    -
    -    point a; a.x = 1; a.y = 2;
    -    point b = a;
    -    BOOST_CHECK( a == b );
    -}
    +
    bool BOOST_LOCAL_FUNCTION(const point& p, const point& q) {
    +    return p.x == q.x && p.y == q.y;
    +} BOOST_LOCAL_FUNCTION_NAME(operator==) // Error: Cannot use `operator...`.
     

    @@ -1163,25 +1234,42 @@ Goto

    - It is not possible to jump with a goto - from within a local function to a label defined in the enclosing scope. -

    -

    - For example, the following will not compile: + It is possible to jump with a goto + within the local function body. For example, the following compiles (see + also goto.cpp):

    int error(int x, int y) {
    -    int BOOST_LOCAL_FUNCTION(int x) {
    -        if(x <= 0) goto failure;    // Error: Cannot jump to enclosing scope.
    -        else goto success;          // OK: Can jump within local function.
    -
    +    int BOOST_LOCAL_FUNCTION(int z) {
    +        if(z > 0) goto success; // OK: Can jump within local function.
    +        return -1;
         success:
             return 0;
         } BOOST_LOCAL_FUNCTION_NAME(validate)
     
         return validate(x + y);
    -faliure:
    +}
    +
    +

    +

    +

    + However, it is not possible to jump with a goto + from within the local function body to to a label defined in the enclosing + scope. For example, the following does not compile (see also goto_error.cpp): +

    +

    +

    +
    int error(int x, int y) {
    +    int BOOST_LOCAL_FUNCTION(int z) {
    +        if(z <= 0) goto failure;    // Error: Cannot jump to enclosing scope.
    +        else goto success;          // OK: Can jump within local function.
    +    success:
    +        return 0;
    +    } BOOST_LOCAL_FUNCTION_NAME(validate)
    +
    +    return validate(x + y);
    +failure:
         return -1;
     }
     
    @@ -1197,7 +1285,7 @@ need to be separated from the rest of the parameter declaration using the preprocessor. Specifically, this library needs to use preprocessor meta-programming to remove default values when constructing the local function type and - then to count the number of default values to provide the correct set of + also to count the number of default values to provide the correct set of call operators for the local functor. Therefore, the symbol = cannot be used because it cannot be handled by preprocessor meta-programming (non-alphanumeric symbols cannot be detected by preprocessor meta-programming because they cannot be concatenated by @@ -1210,7 +1298,8 @@ needs to be defined differently for compilers without variadic macros #define WITH_DEFAULT (default) so it can only be defined by programmers - based on the syntax they decide to use. + based on the syntax they decide to use (see the No + Variadic Macros section).

    [19] Rationale. This limitation is because @@ -1232,11 +1321,11 @@ Rationale. The type names result_type and argN_type follow the Boost.TypeTraits naming conventions for function traits.

    -

    [22] - In the examples of this documentation, we specify bound variables, function - parameters, and result type in this order because this is the order used - by C++11 - lambda functions. However, the library accepts bound variables, +

    [22] + In the examples of this documentation, bound variables, function parameters, + and the result type are specified in this order because this is the order + used by C++11 + lambda functions. However, the library accepts bound variables, function parameters, and the result type in any order.

    [23] @@ -1245,27 +1334,28 @@ as a template parameter (see the Implementation section). No compiler has yet been observed to be able to inline function calls when they use such indirect function pointer calls. Therefore, - inlined local functions do not use such indirect function pointer call + inline local functions do not use such indirect function pointer call (so they are more likely to be optimized) but because of that they cannot be passed as template parameters. The indirect function pointer call is needed on C++03 but it is not needed on C++11 - (see [N2657]) + (see [N2657] + and Boost.Config's + BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) thus this library automatically generates local function calls that - can be inlined on C++11 + can be inline on C++11 compilers (even when the local function is not declared inline).

    [24] - Rationale. This limitation comes from - the fact that the global functor used to pass the local function as a - template parameter (and eventually returned outside the declarations - scope) does not know the local function name so the local function name - used for recursive call cannot be set in the global functor. This limitation - together with preventing the possibility for inlining are the reasons - why local functions are not recursive unless programmers explicitly declare - them recursive. -

    -

    [25] + Rationale. This limitation comes from + the fact that the global functor used to pass the local function as a template + parameter (and eventually returned outside the declarations scope) does + not know the local function name so the local function name used for recursive + call cannot be set in the global functor. This limitation together with + preventing the possibility for inlining are the reasons why local functions + are not recursive unless programmers explicitly declare them recursive. +

    +

    [25] The auto storage classifier is part of the C++03 standard and therefore supported by this library. However, the meaning @@ -1275,7 +1365,27 @@ classifier with the usual care in order to avoid writing C++03 code that might not work on C++11.

    -

    [26] +

    [26] + Rationale. The BOOST_LOCAL_FUNCTION + and BOOST_LOCAL_FUNCTION_TPL + macros internally use __LINE__ + to generate unique identifiers. Therefore, if these macros are expanded + more than on time on the same line, the generated identifiers will no longer + be unique and the code will not compile. (This restriction does not apply + to MSVC and other compilers that provide the non-standard __COUNTER__ macro.) Note that the BOOST_LOCAL_FUNCTION_NAME macro + can always be expanded multiple times on the same line because the unique + local function name (and not __LINE__) + is used by this macro to generate unique identifiers (so there is no need + for a BOOST_LOCAL_FUNCTION_NAME_ID + macro). +

    +

    [27] + Because there are restrictions on the set of tokens that the preprocessor + can concatenate and because not all compilers correctly implement these + restrictions, it is in general recommended to specify unique identifiers + as a combination of alphanumeric tokens. +

    +

    [28] Rationale. This is the because a local function name must be a valid local variable name (the local variable used to hold the local functor) and operators cannot be used as local variable diff --git a/doc/html/boost_localfunction/Alternatives.html b/doc/html/boost_localfunction/Alternatives.html index b8d9ee6..6b7a8e0 100644 --- a/doc/html/boost_localfunction/Alternatives.html +++ b/doc/html/boost_localfunction/Alternatives.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@


    -PrevUpHomeNext +PrevUpHomeNext

    @@ -120,26 +120,26 @@

    - Yes. Plus eventual compiler errors and debugging follow the usual - format of C++ statement errors. + Yes. Plus eventual compiler errors and debugging retain their usual + meaning and format.

    - Yes. Plus eventual compiler errors and debugging follow the usual - format of C++ statement errors. + Yes. Plus eventual compiler errors and debugging retain their usual + meaning and format.

    - Yes. Plus eventual compiler errors and debugging follow the usual - format of C++ statement errors. + Yes. Plus eventual compiler errors and debugging retain their usual + meaning and format.

    - Yes. Plus eventual compiler errors and debugging follow the usual - format of C++ statement errors. + Yes. Plus eventual compiler errors and debugging retain their usual + meaning and format.

    @@ -231,7 +231,7 @@ Yes. The variable names are repeated in the function declaration so they can be bound by value, by constant value, by reference, and by constant reference (the object this - can also be bound). + can also be bound using this_).

    @@ -241,7 +241,7 @@ at once) so they can be bound by constant value and by reference (the object this can also be bound). However, variables cannot be bound by constant references - and non-constant value (see below). + (see below).

    @@ -268,7 +268,7 @@

    Polymorphic - in the unbound parameter types + in the function parameter type

    @@ -305,42 +305,52 @@

    C++11 - lambda functions have most of the features of this library (see also - the example in the Introduction + lambda functions have most of the features of this library plus some + additional feature (see also the example in the Introduction section):

    • C++11 - lambda functions can be defined within expressions while this library + lambda functions can be defined within expressions while this library local functions can only be defined at declaration scope.
    • C++11 - lambda functions are only supported by the C++11 + lambda functions are only supported by the C++11 standard so they are not supported by all C++ compilers. This library local functions can be programmed also on C++03 compilers (and they have performances comparable to C++11 - lambda functions on C++11 + lambda functions on C++11 compilers).
    • C++11 - lambda functions do not allow to bind variables in scope by constant - reference or by non-constant value. Because a variable cannot be bound - by constant reference, C++11 - lambda functions can bind a variable by constant only if the variable + lambda functions do not allow to bind variables in scope by constant + reference. Because a variable cannot be bound by constant reference, C++11 + lambda functions can bind a variable by constant only if the variable is CopyConstructible and - the binding requires a (potentially expensive) extra copy operation. Both - constant reference and non-constant value binding are instead supported - by this library. However, C++11 - lambda functions provide a short-hand syntax to bind all variables + the binding requires a (potentially expensive) extra copy operation. Constant + reference binding is instead supported by this library. +
    • +
    • + C++11 + lambda functions do not allow to bind data members selectively + without binding also the object this + while this library local functions can bind either selected data members + or the entire object this + (using this_). +
    • +
    • + C++11 + lambda functions provide a short-hand syntax to bind all variables in scope at once (& or - =). + =) while this library local + function always require to bind variables naming them one-by-one.

    - For example, for non-copyable objects (see also noncopyable_lambda_err.cpp + For example, for non-copyable objects (see also noncopyable_cxx11_lambda_error.cpp and noncopyable_local_function.cpp):

    @@ -351,7 +361,7 @@

    - C++11 Lambda + C++11 Lambda Function

    @@ -369,11 +379,12 @@ n(int _i): i(_i) {} }; + int main(void) { n x(-1); - auto f = [x](void) { // Error: x is non-copyable, but if - assert( x.i == -1 ); // bind `&x` then `x` is not constant. + auto f = [x](void) { // Error: x is non-copyable, but if + assert(x.i == -1); // bind `&x` then `x` is not constant. }; f(); @@ -390,12 +401,13 @@ int i; n(int _i): i(_i) {} }; +BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below. -int main() { +int main(void) { n x(-1); void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy - assert( x.i == -1 ); // and constant. + assert(x.i == -1); // and constant. } BOOST_LOCAL_FUNCTION_NAME(f) f(); @@ -408,7 +420,7 @@

    - Or, for objects with expensive copy operations (see also expensive_copy_lambda.cpp + Or, for objects with expensive copy operations (see also expensive_copy_cxx11_lambda.cpp and expensive_copy_local_function.cpp):

    @@ -419,7 +431,7 @@

    - C++11 Lambda + C++11 Lambda Function

    @@ -435,16 +447,17 @@
    struct n {
         int i;
         n(int _i): i(_i) {}
    -    n(n const& x): i(x.i) { // Some time consuming copy.
    +    n(n const& x): i(x.i) { // Some time consuming copy operation.
             for (unsigned i = 0; i < 10000; ++i) std::cout << '.';
         }
     };
     
    +
     int main(void) {
         n x(-1);
     
         auto f = [x]() {        // Problem: Expensive copy, but if bind
    -        assert( x.i == -1); // by `&x` then `x` is not constant.
    +        assert(x.i == -1);  // by `&x` then `x` is not constant.
         };
         f();
     
    @@ -460,16 +473,17 @@
     
    struct n {
         int i;
         n(int _i): i(_i) {}
    -    n(n const& x): i(x.i) { // Some time consuming copy.
    +    n(n const& x): i(x.i) { // Some time consuming copy operation.
             for (unsigned i = 0; i < 10000; ++i) std::cout << '.';
         }
     };
    +BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below.
     
     int main(void) {
         n x(-1);
     
    -    void BOOST_LOCAL_FUNCTION(const bind& x) {  // OK: No copy
    -        assert( x.i == -1 );                    // and constant.
    +    void BOOST_LOCAL_FUNCTION(const bind& x) {  // OK: No copy expensive
    +        assert(x.i == -1);                      // copy but constant.
         } BOOST_LOCAL_FUNCTION_NAME(f)
         f();
     
    @@ -483,14 +497,11 @@
     

    When constant binding functionality is needed for C++11 - lambda functions, the best alternative might be to bind an extra local + lambda functions, the best alternative might be to bind an extra local variable declared constant and initialized to the original variable (for example, - const n& const_x = x and then - bind const_x instead of x to the lambda function). In many cases - the use of the extra constant variable const_x - can be acceptable but in other cases (e.g., constant blocks - presented in the Examples - section) it might be preferable to maintain the same variable name x within the function body. + see constant blocks implemented with C++11 + lambda functions in the Examples + section).

    Local Functor @@ -521,7 +532,7 @@

    -
    {
    +
    int main(void) {
         int sum = 0, factor = 10;
     
         struct local_add { // Unfortunately, boilerplate code to program the class.
    @@ -530,6 +541,7 @@
             inline void operator()(int num) { // Body uses C++ statement syntax.
                 sum += factor * num;
             }
    +
         private: // Unfortunately, cannot bind so repeat variable types.
             int& sum; // Access `sum` by reference.
             const int factor; // Make `factor` constant.
    @@ -540,7 +552,8 @@
         // Unfortunately, cannot pass as template parameter to `std::for_each`.
         for(size_t i = 0; i < 2; ++i) add(nums[i]);
     
    -    BOOST_CHECK( sum == 60 );
    +    BOOST_TEST(sum == 60);
    +    return boost::report_errors();
     }
     

    @@ -549,7 +562,7 @@

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -560,7 +573,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -604,12 +618,13 @@ inline void operator()(int num) { // Body uses C++ statement syntax. sum += factor * num; } + private: // Unfortunately, cannot bind so repeat variable types. int& sum; // Access `sum` by reference. const int factor; // Make `factor` constant. }; -BOOST_AUTO_TEST_CASE( test_add_global_functor ) { +int main(void) { int sum = 0, factor = 10; global_add add(sum, factor); @@ -618,7 +633,8 @@ int nums[] = {2, 3}; std::for_each(nums, nums + 2, add); // Passed as template parameter. - BOOST_CHECK( sum == 60 ); + BOOST_TEST(sum == 60); + return boost::report_errors(); }

    @@ -627,7 +643,7 @@

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -638,7 +654,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -679,7 +696,7 @@

    -
    {
    +
    int main(void) {
         using boost::phoenix::let;
         using boost::phoenix::local_names::_f;
         using boost::phoenix::cref;
    @@ -692,10 +709,11 @@
         // Passed to template, `factor` by constant, and defined in expression.
         std::for_each(nums, nums + 3, let(_f = cref(factor))[
             // Unfortunately, body cannot use C++ statement syntax.
    -        ref(sum) += _f * _1 // Access `sum` by reference.
    +        ref(sum) += _f * _1, _1 // Access `sum` by reference.
         ]);
     
    -    BOOST_CHECK( sum == 60 );
    +    BOOST_TEST(sum == 60);
    +    return boost::report_errors();
     }
     

    @@ -704,7 +722,7 @@

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -715,7 +733,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -735,7 +754,7 @@

    The following tables compare run-times, compile-times, and binary sizes for - the different alternatives presented here for local functions. + the different alternatives to local functions presented in this section.

    Overall, this library has compile-times and generates binary sizes similar @@ -745,14 +764,16 @@ ...). However, on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with C++11 features - enabled -std=c++0x, see also [N2657]) + enabled -std=c++0x, see also [N2657] + and Boost.Config's BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) this library automatically generates optimized code that runs as fast as the fastest of the other approaches (see the "Boost.LocalFunction" approach below). When this library local function is specified inline (see the "Boost.LocalFunction Inline" approach below and the Advanced Topics section) its run-times are always comparable to both the "Local Functor" and "Global Functor" approaches. However, in these cases the local function - cannot be portably passed as template parameter (see [N2657]) + cannot be portably passed as template parameter (see [N2657] + and Boost.Config's BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) so std::for_each is replaced by a for-loop (on MSVC the for-loop, and not the local function in fact the same applies to local functors, was measured to have worst performances than using std::for_each). @@ -769,8 +790,8 @@ The run-time performances of this library local functions are explained because on C++03 compliant compilers (e.g., GCC 4.5.3 without -std=c++0x) - this library needs to use a function pointer in order to pass the local function - class as a template parameter (see [N2657] + this library needs to use a function pointer in order to portably pass the + local function class as a template parameter (see [N2657] and the Implementation section). For all tested compilers, this function pointer prevents the compiler optimization algorithms from inlining the local function calls. Instead, @@ -779,9 +800,11 @@ calls for optimization. This run-time performance cost is not present on compilers that allow to pass local types as template parameters (e.g., MSVC 8.0 or GCC 4.5.3 with C++11 - features enabled -std=c++0x) because this library does - not have to use the extra function pointer to implement the local function - call (it directly passes the local class type as template parameter). + features enabled -std=c++0x, see Boost.Config's + BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) + because this library does not have to use the extra function pointer to implement + the local function call (it directly passes the local class type as template + parameter).

    @@ -800,8 +823,10 @@ will perform with respect to each other when a more complex set of instructions is programmed for the local function body (e.g., if a more complex set of instructions in the local function body were to inhibit - some compilers from inlining functor objects also other approaches like Boost.Phoenix could - start to show higher run-times even when optimization is enabled). + some compiler from inlining function objects also other approaches like C++11 + lambda functions and Boost.Phoenix + could start to show higher run-times even when optimization + is enabled).

    The following commands were executed from the library example directory to @@ -880,7 +905,7 @@

    - profile_legend_lambda + profile_legend_cxx11_lambda

    @@ -891,7 +916,7 @@

    - profile_lambda.cpp + profile_cxx11_lambda.cpp

    @@ -956,8 +981,8 @@

    - GCC 4.5.3 With C++11 Lambdas and "Local Types as Template Parameters" - (bjam cxxflags=-std=c++0x ...) + GCC 4.5.3 With C++11 Lambda Functions and "Local Classes as + Template Parameters" (bjam cxxflags=-std=c++0x ...)

    @@ -965,14 +990,14 @@

    Compiled with bjam release ... for maximum optimization (-O3 -finline-functions) - profile_gcc_cpp11_release + profile_gcc_cxx11_release

    Compiled with bjam debug ... for no optimization (-O0 -fno-inline) - profile_gcc_cpp11_debug + profile_gcc_cxx11_debug

    @@ -981,9 +1006,8 @@

    - MSVC 8.0 With "Local Types as Template Parameters" (Without - C++11 - Lambdas) + MSVC 8.0 With "Local Classes as Template Parameters" (Without + C++11 Lambda Functions)

    @@ -1008,7 +1032,7 @@

    GCC 4.3.4 With C++03 Only (Without C++11 - Lambdas and Without "Local Types as Template Parameters") + Lambda Functions and Without "Local Classes as Template Parameters")

    @@ -1040,7 +1064,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_localfunction/Examples.html b/doc/html/boost_localfunction/Examples.html index dc07add..eabfadc 100644 --- a/doc/html/boost_localfunction/Examples.html +++ b/doc/html/boost_localfunction/Examples.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -28,7 +28,7 @@

    GCC - Lambdas (Without C++11)
    + Lambdas (without C++11)
    Constant Blocks
    Scope Exits
    @@ -44,12 +44,12 @@

    - Combing local functions with the statement - expression extension of GCC compilers, it is possible to implement + Combing local functions with the non-standard statement + expression extension of the GCC compiler, it is possible to implement lambda functions for GCC compilers even without C++11 support.

    @@ -59,14 +59,14 @@ Warning

    - This code only works on compilers that support the statement expression - GCC extension or that support C++11 - lambda functions. + This code only works on compilers that support GCC statement expression + extension or that support C++11 + lambda functions.

    For example (see also gcc_lambda.cpp - and gcc_lambda_cpp11.cpp): + and gcc_cxx11_lambda.cpp):

    @@ -121,32 +121,63 @@

    - Where the macros are defined in gcc_lambda.hpp. + The GCC lambda function macros are implemented using local functions (see + also gcc_lambda.hpp): +

    +

    +

    +
    #   define GCC_LAMBDA_(binds, params, results) \
    +        ({ /* open statement expression (GCC extension only) */ \
    +        BOOST_LOCAL_FUNCTION( \
    +            BOOST_PP_LIST_ENUM(BOOST_PP_LIST_APPEND(binds, \
    +                BOOST_PP_LIST_APPEND(params, \
    +                    BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(results), \
    +                        (return void, BOOST_PP_NIL) /* default for lambdas */ \
    +                    , \
    +                        results \
    +                    )\
    +                ) \
    +            )) \
    +        )
    +
    +

    +

    +

    +

    +
    #define GCC_LAMBDA_END_(id) \
    +    BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(gcc_lambda_, id)) \
    +    BOOST_PP_CAT(gcc_lambda_, id); \
    +    }) /* close statement expression (GCC extension only) */
    +
    +

    This is possible because GCC statement expressions allow to use declaration statements within expressions and therefore to declare a local function within an expression. The macros automatically detect if the compiler supports C++11 - lambda functions in which case the implementation uses native lambdas - instead of local functions in statement expressions. However, C++11 - lambda functions do not support constant binding so it is best to + lambda functions in which case the implementation uses native lambdas + instead of local functions in GCC statement expressions. However, C++11 + lambda functions do not support constant binding so it is best to only use const bind - variable (same as C++11 - lambda =variable) - and bind& - variable (same as C++11 - lambda &variable) - because these have the exact same semantic between the local function and - native lambda implementation. Unfortunately, the C++11 - lambda short-hand binds & - and = (which automatically bind - all variables in scope either by reference or value) are not supported by - the macros because they are not supported by the local function implementation. - Finally, the result type return result-type + variable (same as =variable + for C++11 + lambda functions) and bind& variable + (same as &variable + for C++11 + lambda functions') because these have the exact same semantic between + the local function and the native lambda implementations. Furthermore, local + functions allow to bind data members directly while C++11 + lambda functions require to access data members via binding the object + this. Unfortunately, the short-hand + binds & and = of C++11 + lambda functions (which automatically bind all variables in scope + either by reference or value) are not supported by these GCC lambda function + macros because they are not supported by local functions. Finally, the result + type return result-type is optional and it is assumed void when it is not specified (same as with C++11 - lambda functions). + lambda functions).

    @@ -172,13 +203,14 @@ Ideally this code will not compile instead this example not only compiles but the assertion even passes the run-time check and no error is generated at all. The [N1613] - paper introduces the idea of a const-block which could - be used to wrap the assertion above and catch the programming error at compile-time. - Similarly, the following code will generate a compile-time error when operator= + paper introduces the concept of a const-block which + could be used to wrap the assertion above and catch the programming error + at compile-time. Similarly, the following code will generate a compile-time + error when operator= is mistakenly used instead of operator== because both x and y are made constants (using local functions) within the block of code performing the assertion - (see also const_block_err.cpp): + (see also const_block_error.cpp):

    @@ -223,30 +255,70 @@

    - Where the macros are defined in const_block.hpp. + The constant block macros are implemented using local functions (see also + const_block.hpp): +

    +

    +

    +
    #define CONST_BLOCK_(variables) \
    +    void BOOST_LOCAL_FUNCTION( \
    +        BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(variables, \
    +            void BOOST_PP_TUPLE_EAT(3) \
    +        , \
    +            BOOST_PP_LIST_FOR_EACH_I \
    +        )(CONST_BLOCK_BIND_, ~, variables) \
    +    )
    +
    +

    +

    +

    +

    +
    #define CONST_BLOCK_END_(id) \
    +    BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(const_block_, id)) \
    +    BOOST_PP_CAT(const_block_, id)(); /* call local function immediately */
    +
    +

    The constant block macros are implemented using a local function which binds by constant reference const bind& all the specified variables (so the variables are constant within the code block but they do not need to be CopyConstructible - and no extra copy is performed). The local function executes the assert instruction in its body which is + and no extra copy is performed). The local function executes the assert instruction in its body and it is called immediately after it is defined. More in general, constant blocks can be used to evaluate any instruction (not just assertions) within a block were all specified variables are constant.

    Unfortunately, constant blocks cannot be implemented with C++11 - lambda functions because these do not support constant binding (of - course it is always possible to introduce extra constant variables const int& const_x - = x, - etc and use these variables in the assertion). Variables bound by value using - C++11 - lambda functions (variable, + lambda functions because these do not support constant binding. Variables + bound by value using C++11 + lambda functions (variable, =variable, and =) are constant but they are required to be CopyConstructible - and they introduce potentially expensive copy operations. [27] + and they introduce potentially expensive copy operations. [29] Of course it is always possible to introduce extra constant variables + and bind these variables to the C++11 + lambda functions but the constant block code will then have to manage + the declaration and initialization of these extra variables plus it will + have to use the extra variable names instead of the original variable names: +

    +

    +

    +
    int x = 1, y = 2;
    +const decltype(x)& const_x = x; // Constant so cannot be modified
    +const decltype(y)& const_y = y; // and reference so no copy.
    +[&const_x, &const_y]() {        // Lambda functions (C++11 only).
    +    assert(const_x = const_y);  // Unfortunately, `const_` names.
    +}();
    +
    +

    +

    +

    + In many cases the use of an extra constant variable const_x + can be acceptable but in other cases it might be preferable to maintain the + same variable name x within + the function body.

    @@ -266,9 +338,20 @@ to introduce an extra const local variable, assign it to the value to bind, and then bind the const variable so to effectively have constant binding with Boost.ScopeExit - as well). In general, the authors recommend to use Boost.ScopeExit - instead of the code listed here whenever possible. + as well).

    +
    + + + + + +
    [Note]Note

    + In general, the authors recommend to use Boost.ScopeExit + instead of the code listed by this example whenever possible (because + Boost.ScopeExit + is a library deliberately designed to support the scope exit construct). +

    The following example binds p by constant reference so this variable cannot be modified within the scope @@ -308,22 +391,23 @@

    -
    person& p = persons_.back();
    -    person::evolution_t checkpoint = p.evolution_;
    +                

    +

    +
    person& p = persons_.back();
    +person::evolution_t checkpoint = p.evolution_;
     
    -    BOOST_SCOPE_EXIT(checkpoint, &p, this_) { // Or extra variable const_p.
    -        if (checkpoint == p.evolution_) this_->persons_.pop_back();
    -    } BOOST_SCOPE_EXIT_END
    +BOOST_SCOPE_EXIT(checkpoint, &p, this_) { // Or extra variable `const_p`.
    +    if (checkpoint == p.evolution_) this_->persons_.pop_back();
    +} BOOST_SCOPE_EXIT_END
     
    +

    +

    -

    - Where the macros are defined in scope_exit.hpp. -

    The scope exit macros are implemented by passing a local function when constructing - an object of the following class: + an object of the following class (see also scope_exit.hpp):

    @@ -334,6 +418,22 @@ boost::function<void (void)> f_; };
    +

    +

    +

    +

    +
    #   define SCOPE_EXIT(...) \
    +        void BOOST_LOCAL_FUNCTION(__VA_ARGS__)
    +
    +

    +

    +

    +

    +
    #define SCOPE_EXIT_END_(id) \
    +    BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(scope_exit_func_, id)) \
    +    scope_exit BOOST_PP_CAT(scope_exit_, id)( \
    +            BOOST_PP_CAT(scope_exit_func_, id));
    +

    @@ -375,7 +475,7 @@

    -
    BOOST_AUTO_TEST_CASE( test_phoenix_factorial_local ) {
    +
    int main(void) {
         using boost::phoenix::arg_names::arg1;
     
         int BOOST_LOCAL_FUNCTION(int n) { // Unfortunately, monomorphic.
    @@ -386,8 +486,9 @@
                 factorial(factorial_impl); // Phoenix function from local function.
     
         int i = 4;
    -    BOOST_CHECK( factorial(i)() == 24 );        // Call.
    -    BOOST_CHECK( factorial(arg1)(i) == 24 );    // Lazy call.
    +    BOOST_TEST(factorial(i)() == 24);      // Call.
    +    BOOST_TEST(factorial(arg1)(i) == 24);  // Lazy call.
    +    return boost::report_errors();
     }
     

    @@ -412,14 +513,15 @@ } }; -BOOST_AUTO_TEST_CASE( test_phoenix_factorial ) { +int main(void) { using boost::phoenix::arg_names::arg1; boost::phoenix::function<factorial_impl> factorial; int i = 4; - BOOST_CHECK( factorial(i)() == 24 ); // Call. - BOOST_CHECK( factorial(arg1)(i) == 24 ); // Lazy call. + BOOST_TEST(factorial(i)() == 24); // Call. + BOOST_TEST(factorial(arg1)(i) == 24); // Lazy call. + return boost::report_errors(); }

    @@ -430,9 +532,9 @@

    This is presented here mainly as a curiosity because Boost.Phoenix functions created from local functions have the important limitation that - they cannot be polymorphic. [28] Therefore, in many cases creating the Boost.Phoenix + they cannot be polymorphic. [30] Therefore, in many cases creating the Boost.Phoenix function from global functors (possibly with the help of Boost.Phoenix - adaptor macros) might be a more valuable option. + adaptor macros) might be a more useful.

    @@ -441,8 +543,9 @@

    The following are examples of closures - that illustrate how to return local functions to the calling scope (and the - relative precautions to take). + that illustrate how to return local functions to the calling scope (note + how extra care is taken in order to ensure that all bound variables remain + valid at the calling scope):

    @@ -481,15 +584,16 @@ Nested Functions

    - The GCC C compiler supports local functions under the name of nested - functions. Nested functions are exclusively a C extension of the - GCC compiler (they are not supported for C++ not even by the GCC compiler, + The GCC C compiler supports local functions as a non-standard extension under + the name of nested + functions. Note that nested functions are exclusively a C extension + of the GCC compiler (they are not supported for C++ not even by the GCC compiler, and they are not part of any C or C++ standard, nor they are supported by other compilers like MSVC).

    The following examples are taken form the GCC nested function documentation - and programmed using this library: + and programmed using local functions:

    @@ -522,8 +626,8 @@ N-Papers

    - The following examples are taken from a number of N-papers and programmed - using this library. + The following examples are taken from different C++ "N-papers" + and programmed using local functions:

    @@ -553,7 +657,7 @@

    This example is adapted from [N2550] (C++11 - lambda functions): It passes a local function to the STL + lambda functions): It passes a local function to the STL algorithm std::find_if.

    @@ -568,7 +672,7 @@

    This example is adapted from [N2529] (C++11 - lambda functions): It binds the object in scope this to a local function. + lambda functions): It binds the object in scope this to a local function.

    @@ -577,12 +681,12 @@


    -

    [27] +

    [29] Ideally, C++11 - lambda functions would allow to bind variables also using const& variable (constant reference) and const& + lambda functions would allow to bind variables also using const& variable (constant reference) and const& (all variables by constant reference).

    -

    [28] +

    [30] Rationale. Local functions can only be monomorphic because they are implemented using local classes and local classes cannot be templates in C++ (not even in C++11). @@ -600,7 +704,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_localfunction/Getting_Started.html b/doc/html/boost_localfunction/Getting_Started.html index 9226dfb..209a766 100644 --- a/doc/html/boost_localfunction/Getting_Started.html +++ b/doc/html/boost_localfunction/Getting_Started.html @@ -32,10 +32,9 @@
    Compilers and Platforms
    Installation
    -
    Configuration

    - This section explains how programmers can setup their system to use this library. + This section explains how to setup a system to use this library.

    @@ -58,12 +57,13 @@ of this library.

    - In some of the examples presented in this documentation, the Boost.Test - macro BOOST_CHECK is used - equivalently to assert and - the Boost.Test macro - BOOST_AUTO_TEST_CASE is used - equivalently to main. [3] + In most of the examples presented in this documentation, the Boost.Detail/LightweightTest + (boost/detail/lightweight_test.hpp) macro BOOST_TEST is used to check correctness + conditions. The BOOST_TEST + macro is conceptually similar to assert + but a failure of the checked condition does not abort the program, instead + it makes boost::report_errors return a non-zero program + exit code. [3]

    @@ -75,15 +75,13 @@ The implementation of this library uses preprocessor and template meta-programming (as supported by Boost.Preprocessor and Boost.MPL), templates - with partial specializations and function pointers (similarly to Boost.Function). - As a consequence, this library is fairly demanding on compilers' compliance - with the C++03 - standard. At present, this library has been successfully compiled and tested - on the following compilers and platforms: + with partial specializations and function pointers (similarly to Boost.Function), + and automatic type deduction (as supported by Boost.Typeof). + The authors originally developed and tested the library on:

    1. - GNU Compiler Collection (GCC) 4.5.1 on Ubuntu Linux 10. + GNU Compiler Collection (GCC) C++ 4.5.1 on Ubuntu Linux 10.
    2. GCC 4.3.4 and 4.5.3 (with and without C++11 @@ -91,12 +89,13 @@ on Cygwin.
    3. - Miscrosoft Visual Studio Compiler (MSVC) 8.0 on Windows XP and Windows - 7. + Miscrosoft Visual C++ (MSVC) 8.0 on Windows XP and Windows 7.

    - This library has not yet been tested on any other compiler and platform. + See the library regressions + test results for detailed information on supported compilers and + platforms.

    @@ -111,12 +110,14 @@ option for MSVC, etc) and they can start compiling code using this library.

    - This library implementation uses a number of Boost - libraries among which: Boost.Preprocessor, - Boost.ScopeExit, - Boost.Typeof, Boost.TypeTraits, and - Boost.MPL. These Boost libraries must be properly installed - on your system in order for this library to work. + The library implementation uses Boost.Typeof + to automatically deduce the types of bound variables (see the Tutorial + section). In order to compile code in type-of emulation mode, all types should + be properly registered using BOOST_TYPEOF_REGISTER_TYPE + and BOOST_TYPEOF_REGISTER_TEMPLATE, + or appropriate Boost.Typeof + headers should be included (see the source code of most examples presented + in this documentation).

    The followings are part of the library private API, they are not documented, @@ -139,19 +140,11 @@ Any symbol prefixed by BOOST_LOCAL_FUNCTION_AUX_... or BOOST_LOCAL_FUNCTION_DETAIL_... (regardless of its namespace).

    -
    -
    -

    Some of the library behaviour can be changed at compile-time by defining special configuration macros. If a configuration macro is left undefined, the library will use an appropriate default value for - it. -

    -

    - All configuration macros are defined in the header file boost/local_function/config.hpp. + it. All configuration macros are defined in the header file boost/local_function/config.hpp. It is strongly recommended not to change the library configuration macro definitions unless strictly necessary.

    @@ -159,14 +152,14 @@


    [3] - Rationale. Using Boost.Test - allows to add the documentation examples to the library regression tests - so to make sure that the listed examples always compile and run correctly. + Rationale. Using Boost.Detail/LightweightTest + allows to add the examples to the library regression tests so to make sure + that they always compile and run correctly.

    [4] Rationale. This library concatenates symbols specified by the programmers (e.g., the local function name) with other - symbols (e.g., special prefixes or preprocessor line numbers) to make internal + symbols (e.g., special prefixes or file line numbers) to make internal symbols with unique names to avoid name clashes. These symbols are separated by the letter "X" when they are concatenated so they read more easily during debugging (the @@ -176,7 +169,7 @@ underscore, the concatenation could result in a symbol with double underscores "__" which is reserved by the C++ standard). The "aux" symbols are private - to this library while the "detail" symbols can be used within + to this library while the "detail" symbols may be used within Boost by other libraries but they are still not part of this library public API.

    diff --git a/doc/html/boost_localfunction/Implementation.html b/doc/html/boost_localfunction/Implementation.html index b14123d..bf5a152 100644 --- a/doc/html/boost_localfunction/Implementation.html +++ b/doc/html/boost_localfunction/Implementation.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -53,10 +53,11 @@ local classes (and therefore the local function objects they implement) cannot be passed as template parameters (e.g., to the std::for_each algorithm), this is instead possible in C++11, - MSVC, and some other compilers (see [N2657]). + MSVC, and some other compilers (see [N2657] + and Boost.Config's BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS). To work around this limitation, this library investigated the following two - "tricks" (both tricks can be extended to support eventual function - default parameters): + "tricks" (both tricks can be extended to support function default + parameters):

    1. @@ -64,13 +65,14 @@ that calls a static member function of the local class via a function pointer. The static member function then calls the correct local function body after type casting the object from a void* pointer (local classes can always be used - for type casting). + for type casting via static_cast + or similar).
    2. The virtual functor trick derives the local functor class from a non-local base class. The correct overridden implementation of the virtual operator() - is then called via polymorphism. + is then called via dynamic binding.

    @@ -78,15 +80,14 @@

    -
    #define BOOST_TEST_MODULE TestImplTparamTricks
    -#include <boost/test/unit_test.hpp>
    +
    #include <boost/detail/lightweight_test.hpp>
     #include <vector>
     #include <algorithm>
     
     // Casting functor trick.
     struct casting_func {
    -    explicit casting_func(void* obj, void (*call)(void*, const int&)):
    -            obj_(obj), call_(call) {}
    +    explicit casting_func(void* obj, void (*call)(void*, const int&))
    +            : obj_(obj), call_(call) {}
         // Unfortunately, function pointer call is not inlined.
         inline void operator()(const int& num) { call_(obj_, num); }
     private:
    @@ -106,18 +107,17 @@
         interface* func_;
     };
     
    -BOOST_AUTO_TEST_CASE( test_impl_tparam_tricks ) {
    +int main(void) {
         int sum = 0, factor = 10;
     
         // Local class for local function.
    -    struct local_add: virtual_func::interface {
    -        explicit local_add(int& _sum, const int& _factor):
    -                sum_(_sum), factor_(_factor) {}
    +    struct local_add : virtual_func::interface {
    +        explicit local_add(int& _sum, const int& _factor)
    +                : sum_(_sum), factor_(_factor) {}
             inline void operator()(const int& num) {
                 body(sum_, factor_, num);
             }
    -        inline static void call(
    -                void* obj, const int& num) {
    +        inline static void call(void* obj, const int& num) {
                 local_add* self = static_cast<local_add*>(obj);
                 self->body(self->sum_, self->factor_, num);
             }
    @@ -134,11 +134,12 @@
         std::vector<int> v(10);
         std::fill(v.begin(), v.end(), 1);
     
    -//  std::for_each(v.begin(), v.end(), add_local); // Error but OK on C++11.
    +    // std::for_each(v.begin(), v.end(), add_local); // Error but OK on C++11.
         std::for_each(v.begin(), v.end(), add_casting); // OK.
         std::for_each(v.begin(), v.end(), add_virtual); // OK.
     
    -    BOOST_CHECK( sum == 200 );
    +    BOOST_TEST(sum == 200);
    +    return boost::report_errors();
     }
     

    @@ -148,12 +149,13 @@ the virtual functor trick so the current implementation of this library uses the casting functor trick (probably because in addition to the indirect function call, the virtual functor trick also requires accessing the virtual - function table). However, neither one of tricks has been observed to - allow for compiler optimizations that inline the local function calls (because + function table). However, neither one of the two tricks was observed + to allow for compiler optimizations that inline the local function calls (because they rely on one indirect function call via either a function pointer or a - virtual function respectively). Therefore, on compilers that accept local types + virtual function respectively). Therefore, on compilers that accept local classes as template parameters (MSVC, C++11, - etc, see [N2657]), + etc, see [N2657] + and Boost.Config's BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS), this library automatically generates code that passes the local class type directly as template parameter without using neither one of these two tricks in order to take full advantage of compiler optimizations that inline the local @@ -170,9 +172,9 @@ (to generate special code to bind the object in scope), or if the variable is bound by const (to generate special code to bind by constant), etc. The parameter tokens are inspected - using preprocessor metaprogramming and specifically using the macros defined + using preprocessor meta-programming and specifically using the macros defined by the files in the boost/local_function/detail/preprocessor/keyword/ - directory. [29] + directory. [31]

    For example, the following code defines a macro that allows the preprocessor @@ -184,8 +186,7 @@

    #include <boost/local_function/detail/preprocessor/keyword/thisunderscore.hpp>
     #include <boost/local_function/detail/preprocessor/keyword/const.hpp>
     #include <boost/local_function/detail/preprocessor/keyword/bind.hpp>
    -#define BOOST_TEST_MODULE TestImplPpKeyword
    -#include <boost/test/unit_test.hpp>
    +#include <boost/detail/lightweight_test.hpp>
     
     // Expand to 1 if space-separated tokens end with `this_`, 0 otherwise.
     #define IS_THIS_BACK(tokens) \
    @@ -195,16 +196,17 @@
             tokens \
         )))
     
    -BOOST_AUTO_TEST_CASE( test_impl_pp_keyword ) {
    -    BOOST_CHECK( IS_THIS_BACK(const bind this_) == 1 );
    -    BOOST_CHECK( IS_THIS_BACK(const bind& x) == 0 );
    +int main(void) {
    +    BOOST_TEST(IS_THIS_BACK(const bind this_) == 1);
    +    BOOST_TEST(IS_THIS_BACK(const bind& x) == 0);
    +    return boost::report_errors();
     }
     



    -

    [29] +

    [31] This technique is at the core of even more complex preprocessor parsing macros like the ones that parse the Contract++ syntax. @@ -222,7 +224,7 @@


    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_localfunction/No_Variadic_Macros.html b/doc/html/boost_localfunction/No_Variadic_Macros.html index 2137097..e8912a4 100644 --- a/doc/html/boost_localfunction/No_Variadic_Macros.html +++ b/doc/html/boost_localfunction/No_Variadic_Macros.html @@ -57,18 +57,19 @@

    -
    {                                           // Some local scope.
    -    int sum = 0, factor = 10;               // Variables in scope to bind.
    +
    int main(void) {
    +    int sum = 0, factor = 10;
     
         void BOOST_LOCAL_FUNCTION( (const bind factor) (bind& sum) (int num) ) {
    -        sum += factor * num;                // Parameters as sequence.
    +        sum += factor * num;
         } BOOST_LOCAL_FUNCTION_NAME(add)
     
    -    add(1);                                 // Call the local function.
    +    add(1);
         int nums[] = {2, 3};
    -    std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
    +    std::for_each(nums, nums + 2, add);
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);
    +    return boost::report_errors();
     }
     

    @@ -79,7 +80,7 @@

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -90,16 +91,17 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    - Note how the same macros accept both syntaxes on compilers with variadic macros + Note that the same macros accept both syntaxes on compilers with variadic macros and only the sequence syntax on compilers without variadic macros. Finally, - an parameter list is always specified using void - on compilers with and without variadic macros: + an empty local function parameter list is always specified using void on compilers with and without variadic + macros:

    @@ -107,173 +109,144 @@ return 10; } BOOST_LOCAL_FUNCTION_NAME(ten) -BOOST_CHECK( ten() == 10 ); +BOOST_TEST(ten() == 10);

    - An - Example + Examples

    - The following example shows a bit of all the different macro parameter combinations - using the sequence syntax (see also seq.cpp): -

    -

    -

    -
    struct s {
    -    void f(double p = 1.23, double q = -1.23) {
    -        { // Only params.
    -            void BOOST_LOCAL_FUNCTION( (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l(1);
    -        }
    -        { // Only const binds.
    -            int a, b;
    -
    -            const int& BOOST_LOCAL_FUNCTION( (const bind a)
    -                    (const bind& b) (const bind& p) (const bind q) ) {
    -                return b;
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l();
    -
    -            const s& BOOST_LOCAL_FUNCTION( (const bind this_) ) {
    -                return *this_;
    -            } BOOST_LOCAL_FUNCTION_NAME(t)
    -            t();
    -
    -            const int BOOST_LOCAL_FUNCTION( (const bind a)
    -                    (const bind& b) (const bind& p) (const bind q)
    -                    (const bind this_) ) {
    -                return a;
    -            } BOOST_LOCAL_FUNCTION_NAME(lt)
    -            lt();
    -        }
    -        { // Only plain binds.
    -            int c, d;
    -
    -            int& BOOST_LOCAL_FUNCTION( (bind c) (bind& d)
    -                    (bind& p) (bind& q) ) {
    -                return d;
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l();
    -
    -            s& BOOST_LOCAL_FUNCTION( (bind this_) ) {
    -                return *this_;
    -            } BOOST_LOCAL_FUNCTION_NAME(t)
    -            t();
    -
    -            int BOOST_LOCAL_FUNCTION( (bind c) (bind& d)
    -                    (bind& p) (bind& q) (bind this_) ) {
    -                return c;
    -            } BOOST_LOCAL_FUNCTION_NAME(lt)
    -            lt();
    -        }
    -
    -        { // Both params and const binds.
    -            int a, b;
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind& b)
    -                    (const bind& p) (const bind q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind this_)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(t)
    -            t(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind this_)
    -                    (const bind& b) (const bind& p) (const bind q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lt)
    -            lt(1);
    -        }
    -        { // Both params and plain binds.
    -            int c, d;
    -
    -            void BOOST_LOCAL_FUNCTION( (bind c) (bind& d) (bind& p) (bind q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (bind this_)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(t)
    -            t(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (bind c) (bind& d)
    -                    (bind& p) (bind this_) (bind q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lt)
    -            lt(1);
    -        }
    -        { // Both const and plain binds.
    -            int a, b, c, d;
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind& b)
    -                    (const bind p) (bind c) (bind& d) (bind q) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l();
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind this_)
    -                    (bind c) (bind& d) (bind q) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(ct)
    -            ct();
    -            void BOOST_LOCAL_FUNCTION( (const bind this_)
    -                    (const bind a) (const bind& b) (const bind p)
    -                    (bind c) (bind& d) (bind q) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lct)
    -            lct();
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind& b)
    -                    (const bind p) (bind this_) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(pt)
    -            pt();
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind& b)
    -                    (const bind p) (bind c) (bind this_) (bind& d) (bind q) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lpt)
    -            lpt();
    -        }
    -
    -        { // All params, const binds, and plain binds.
    -            int a, b, c, d;
    -
    -            void BOOST_LOCAL_FUNCTION(
    -                    (const bind a) (const bind& b) (const bind& p)
    -                    (bind c) (bind& d) (bind& q) (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(l)
    -            l(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind this_)
    -                    (bind c) (bind& d) (bind& q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(ct)
    -            ct(1);
    -            void BOOST_LOCAL_FUNCTION(
    -                    (const bind a) (const bind& b) (const bind& p)
    -                    (bind this_) (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(pt)
    -            pt(1);
    -
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind this_)
    -                    (const bind& b) (const bind& p) (bind c) (bind& d)
    -                    (bind& q) (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lct)
    -            lct(1);
    -            void BOOST_LOCAL_FUNCTION( (const bind a) (const bind& b)
    -                    (const bind& p) (bind c) (bind& d) (bind this_) (bind& q)
    -                    (int x) (int y)(default 0) ) {
    -            } BOOST_LOCAL_FUNCTION_NAME(lpt)
    -            lpt(1);
    -        }
    -    }
    -};
    -
    -

    + For reference, the following is a list of most of the examples presented in + this documentation reprogrammed using the sequence syntax instead of the comma-separated + syntax (in alphabetic order):

    +
    diff --git a/doc/html/boost_localfunction/Release_Notes.html b/doc/html/boost_localfunction/Release_Notes.html index 6054324..4623a54 100644 --- a/doc/html/boost_localfunction/Release_Notes.html +++ b/doc/html/boost_localfunction/Release_Notes.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -32,8 +32,8 @@

    - Version - 1.0.0 (2012-01-31) + Version + 1.0.0 (2012-04-12)
    1. @@ -65,6 +65,17 @@ Moved BOOST_IDENTITY_TYPE to Boost.Utility/IdentityType.
    2. +
    3. + Completely removed use of Boost.Typeof when bound and result types are + explicitly specified. +
    4. +
    5. + Added ..._ID + macros for multiple expansions on the same line. +
    6. +
    7. + Fixed compilation on Boost regression test platforms. +
    @@ -151,7 +162,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_localfunction/Tutorial.html b/doc/html/boost_localfunction/Tutorial.html index 315d231..5506b9a 100644 --- a/doc/html/boost_localfunction/Tutorial.html +++ b/doc/html/boost_localfunction/Tutorial.html @@ -34,7 +34,7 @@
    Templates

    - This section illustrates basic usages of this library. + This section illustrates basic usage of this library.

    @@ -44,7 +44,7 @@ Local functions are defined using macros from the header file boost/local_function.hpp. The macros must be used from within a declarative context (this is a limitation with respect to C++11 - lambda functions which can instead be declared also within expressions): + lambda functions which can instead be declared also within expressions):

    #include <boost/local_function.hpp> // This library header.
     
    @@ -65,11 +65,17 @@
             which it is declared.
           

    - The local function body is specified in a code block { - ... } - using the usual C++ syntax. The body is specified outside any of the macros - so eventual compiler error messages and related line numbers retain their - usual meaning and format. [6] + The local function result type is specified just before the BOOST_LOCAL_FUNCTION + macro. +

    +

    + The local function body is specified using the usual C++ statement syntax + in a code block { ... + } between the BOOST_LOCAL_FUNCTION + and BOOST_LOCAL_FUNCTION_NAME + macros. The body is specified outside any of the macros so eventual compiler + error messages and related line numbers retain their usual meaning and format. + [6]

    The local function parameters are passed to the BOOST_LOCAL_FUNCTION @@ -84,7 +90,7 @@ controlled at compile-time by the configuration macro BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX. For example, let's program a local function named add that adds together two integers x - and y (see also add_params.cpp): + and y (see also add_params_only.cpp):

    @@ -92,13 +98,13 @@ return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) -BOOST_CHECK( add(1, 2) == 3 ); // Local function call. +BOOST_TEST(add(1, 2) == 3); // Local function call.

    If the local function has no parameter, it is possible to pass void to the BOOST_LOCAL_FUNCTION - macro (similarly to the C syntax that allows to use result-type + macro (similarly to the C++ syntax that allows to use result-type function-name(void) to declare a function with no parameter): [7]

    @@ -113,7 +119,7 @@ return 10; } BOOST_LOCAL_FUNCTION_NAME(ten) -BOOST_CHECK( ten() == 10 ); +BOOST_TEST(ten() == 10);

    @@ -123,29 +129,12 @@ Binding Variables

    - Variables in scope (local variables, enclosing function parameters, member - variables, etc) can be bound to a local function declaration. Only bound - variables, static variables, global variables, functions, and enumerations - from the enclosing scope are accessible from within the local function body. - The types of bound variables are deduced automatically by this library. - [8] + Variables in scope (local variables, enclosing function parameters, data + members, etc) can be bound to a local function declaration. Only bound variables, + static variables, global variables, functions, and enumerations from the + enclosing scope are accessible from within the local function body. The types + of bound variables are deduced automatically by this library using Boost.Typeof. [8]

    -
    - - - - - -
    [Important]Important

    - The library implementation uses Boost.Typeof - to automatically deduce the types of the bound variables. Therefore, in - order to compile code in type-of emulation mode, all types should be properly - registered with BOOST_TYPEOF_REGISTER_TYPE - or BOOST_TYPEOF_REGISTER_TEMPLATE - macros, or appropriate Boost.Typeof - headers should be included (see the Boost.Typeof - documentation for more detail). -

    This library introduces the new "keyword" bind [9] which is used in place of the parameter type to specify the name @@ -189,9 +178,9 @@ by reference).

    - The type of a bound variable is automatically deduced and it is the exact - same type used to declare such a variable in the enclosing scope with the - following notes: + The type of a bound variable is automatically deduced using Boost.Typeof + and it is the exact same type used to declare such a variable in the enclosing + scope with the following notes:

    • @@ -203,7 +192,7 @@ scope then it will not be bound as constant unless constant binding is forced using const bind.... (Note that binding by constant reference is not supported by C++11 - lambda functions but it is supported by this library.) [11] + lambda functions but it is supported by this library.) [11]
    • If a bound variable was declared as a reference in the enclosing scope, @@ -213,11 +202,11 @@

    - When a variable is bound by value (constant or not), its type must be CopyConstructible (i.e., its must provide - a copy constructor). As with passing parameters to usual C++ functions, programmers - might want to bind variables of complex types by (possibly constant) reference - instead of by value to avoid expensive copy operations when these variables - are bound to a local function. + When a variable is bound by value (constant or not), its type must be CopyConstructible (i.e., its must + provide a copy constructor). As with passing parameters to usual C++ functions, + programmers might want to bind variables of complex types by (possibly constant) + reference instead of by value to avoid expensive copy operations when these + variables are bound to a local function.

    For example, let's program the local function add @@ -231,7 +220,7 @@

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -242,7 +231,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -315,7 +305,7 @@

    struct adder {
    -    adder(): sum_(0) {}
    +    adder() : sum_(0) {}
     
         int sum(const std::vector<int>& nums, const int factor = 10) {
     
    @@ -326,6 +316,7 @@
             std::for_each(nums.begin(), nums.end(), add);
             return sum_;
         }
    +
     private:
         int sum_;
     };
    @@ -337,7 +328,7 @@
             object this_ regardless of
             their access level (public,
             protected, or private). [15] Specifically, in the example above the local function updates
    -        the private data member sum_.
    +        the private data member sum_.
           

    @@ -346,7 +337,8 @@

    When local functions are programmed within templates, they need to be declared - using the special macro BOOST_LOCAL_FUNCTION_TPL: + using the special macros BOOST_LOCAL_FUNCTION_TPL + and BOOST_LOCAL_FUNCTION_NAME_TPL: [16]

    #include <boost/local_function.hpp> // This library header.
    @@ -356,14 +348,16 @@
         ...
         result-type BOOST_LOCAL_FUNCTION_TPL(parameters) {
             body-code
    -    } BOOST_LOCAL_FUNCTION_NAME(name)
    +    } BOOST_LOCAL_FUNCTION_NAME_TPL(name)
         ...
     }
     

    The BOOST_LOCAL_FUNCTION_TPL - macro has the exact same syntax of the BOOST_LOCAL_FUNCTION - macro that we have seen so far. + and BOOST_LOCAL_FUNCTION_NAME_TPL + macros have the exact same syntax of the BOOST_LOCAL_FUNCTION + and BOOST_LOCAL_FUNCTION_NAME + macros that we have seen so far.

    For example, let's program a local function similar to the one from the @@ -376,10 +370,10 @@ T total(const T& x, const T& y, const T& z) { T sum = T(), factor = 10; - // Using the `..._TPL` macro. + // Must use the `..._TPL` macros within templates. T BOOST_LOCAL_FUNCTION_TPL(const bind factor, bind& sum, T num) { return sum += factor * num; - } BOOST_LOCAL_FUNCTION_NAME(add) + } BOOST_LOCAL_FUNCTION_NAME_TPL(add) add(x); T nums[2]; nums[0] = y; nums[1] = z; @@ -446,8 +440,8 @@ and bind const ... equivalently. However, handling both syntaxes would have complicated the macro implementation without adding - any feature so only one syntax (const - bind ...) + any feature so only one syntax const + bind ... is supported.

    [11] @@ -471,17 +465,17 @@ is used so that references can be bound by both value [const] bind and reference [const] bind& (this is the same binding semantic adopted by Boost.ScopeExit). - On the other hand, variables originally declared as constants should - never loose their const - qualifier (to prevent their modification not just in the enclosing - scope but also in the local scope) thus they are always bound by constant - even if bind[&] + However, variables originally declared as constants should never loose + their const qualifier + (to prevent their modification not just in the enclosing scope but + also in the local scope) thus they are always bound by constant even + if bind[&] is used instead of const bind[&].

    [13] - Rationale. The special name this_ was chosen following Boost - practises which postfix with an underscore identifiers that are - named after keywords (the C++ keyword this + Rationale. The special name this_ was chosen following Boost + practise to postfix with an underscore identifiers that are named + after keywords (the C++ keyword this in this case). The special symbol this_ is needed because this is a reserved C++ keyword so it cannot be used as the name of the internal @@ -500,11 +494,10 @@ be a static member function of the local functor object in order to support recursion (because the local function name is specified by the BOOST_LOCAL_FUNCTION_NAME macro only after the body so it must be made available via a functor - member variable named after the local function and local classes cannot - have static member variables in C++) and nesting (because the argument - binding variable must be declared as a member variable so it is visible - in a local function nested within the body member function) -- see the - Implementation + data member named after the local function and local classes cannot have + static data members in C++) and nesting (because the argument binding + variable must be declared as a data member so it is visible in a local + function nested within the body member function) -- see the Implementation section. Therefore, from within the local function body the variable this is visible but it refers to the local functor and not to the bound object. @@ -520,10 +513,13 @@ needs to use typename to explicitly indicate that some expressions evaluate to a type. Because C++03 does not allow to use typename - outside templates, the special TPL - macro is used to indicate that the enclosing scope is a template so this - library can safely use typename - to resolve expression type ambiguities. + outside templates, the special ..._TPL macros are used to indicate that + the enclosing scope is a template so this library can safely use typename to resolve expression type ambiguities. + C++11 and + other compilers might compile local functions within templates even when + the ..._TPL + macros are not used. However, it is recommended to always use the ..._TPL + macros within templates to maximize portability.

    diff --git a/doc/html/index.html b/doc/html/index.html index 725a3fd..d29f2ea 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -45,7 +45,6 @@
    Compilers and Platforms
    Installation
    -
    Configuration
    Tutorial
    @@ -61,27 +60,29 @@ Parameters
    Commas and Symbols in Macros
    -
    Assigning - and Returning
    +
    Assignments + and Returns
    Nesting
    Accessing Types (concepts, etc)
    -
    Specifying - Types
    +
    Specifying + Types (no Boost.Typeof)
    Inlining
    Recursion
    Overloading
    Exception Specifications
    -
    Storage - Classifiers (auto and register)
    +
    Storage + Classifiers
    +
    Same + Line Expansions
    Limitations (operators, etc)
    Examples
    GCC - Lambdas (Without C++11)
    + Lambdas (without C++11)
    Constant Blocks
    Scope Exits
    @@ -92,33 +93,34 @@ Nested Functions
    N-Papers
    +
    Annex: Alternatives
    +
    Annex: No Variadic + Macros
    +
    Annex: Implementation
    Reference
    Header <boost/local_function.hpp>
    Header <boost/local_function/config.hpp>
    -
    Annex: Alternatives
    -
    Annex: No Variadic - Macros
    -
    Annex: Implementation
    Release Notes
    Bibliography
    Acknowledgments

    - This library allows to program functions locally, directly within the scope where - they are needed. + This library allows to program functions locally, within other functions, and + directly within the scope where they are needed.

    - Local functions are a form of information hiding + Local functions (a.k.a., nested + functions) are a form of information hiding and they are useful for dividing procedural tasks into subtasks which are only meaningful locally, avoiding cluttering other parts of the program with functions, - variables, etc unrelated to those parts. Local functions therefore complement + variables, etc unrelated to those parts. Therefore, local functions complement other structuring possibilities such as namespaces and classes. Local functions are a feature of many programming languages, notably Pascal and Ada, @@ -127,12 +129,13 @@

    Using C++11 - lambda functions, it is possible to implement local functions by naming - the lambdas assigning them to local variables. For example (see also add_lambda.cpp): + lambda functions, it is possible to implement local functions by naming + lambda functions assigning them to local variables. For example (see also + add_cxx11_lambda.cpp):

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         auto add = [factor, &sum](int num) {    // C++11 only.
    @@ -143,7 +146,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -151,13 +155,12 @@

    This library allows to program local functions portably between C++03 and C++11 (and - with performances comparable to lambdas on C++11 - compilers, see the Alternatives - section). For example (see also add.cpp): + with performances comparable to lambda functions on C++11 + compilers). For example (see also add.cpp):

    -
    {                                           // Some local scope.
    +
    int main(void) {                            // Some local scope.
         int sum = 0, factor = 10;               // Variables in scope to bind.
     
         void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
    @@ -168,7 +171,8 @@
         int nums[] = {2, 3};
         std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
     
    -    BOOST_CHECK( sum == 60 );               // Assert final summation value.
    +    BOOST_TEST(sum == 60);                  // Assert final summation value.
    +    return boost::report_errors();
     }
     

    @@ -189,7 +193,7 @@

  • Local functions can be passed as template parameters so they can be conveniently - used with STL algorithms, etc. [1] + used with STL algorithms and other templates. [1]
  • However, local functions must be specified within a declarative context @@ -200,7 +204,7 @@

    See the Alternatives section for a comparison between this library, C++11 - lambda functions, Boost.Phoenix, + lambda functions, Boost.Phoenix, and other C++ techniques that implement features related to local functions.

  • @@ -215,14 +219,14 @@

    [2] This is a weakness with respect to C++11 - lambda functions which can instead be specified also within expressions + lambda functions which can instead be specified also within expressions (see the Alternatives section).

    - +

    Last revised: February 14, 2012 at 15:46:08 GMT

    Last revised: April 13, 2012 at 00:19:19 GMT


    diff --git a/doc/html/reference.html b/doc/html/reference.html index fc02de3..7449141 100644 --- a/doc/html/reference.html +++ b/doc/html/reference.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -32,12 +32,15 @@
    -

    Local functions allow to program functions locally, directly within the scope where they are needed.

    +

    Local functions allow to program functions locally, within other functions, and directly within the scope where they are needed.

     
     BOOST_LOCAL_FUNCTION(declarations)
     BOOST_LOCAL_FUNCTION_TPL(declarations)
    -BOOST_LOCAL_FUNCTION_NAME(qualified_function_name)
    +BOOST_LOCAL_FUNCTION_ID(id, declarations)
    +BOOST_LOCAL_FUNCTION_TPL_ID(id, declarations)
    +BOOST_LOCAL_FUNCTION_NAME(qualified_name)
    +BOOST_LOCAL_FUNCTION_NAME_TPL(name)
     BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name)

    @@ -61,7 +65,7 @@

    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/implementation.qbk b/doc/implementation.qbk index e552b37..e85df5e 100644 --- a/doc/implementation.qbk +++ b/doc/implementation.qbk @@ -5,7 +5,7 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Implementation Annex: Implementation] +[section:implementation Annex: Implementation] This section gives an overview of the key programming techniques used to implement this library. @@ -14,30 +14,30 @@ The code listed here can be used by curious readers and library maintainers as a There is absolutely no guarantee that the library implementation uses the exact code listed here. ] -[h5 Local Classes as Template Parameters] +[heading Local Classes as Template Parameters] This library uses a local class to implement the local function object. -However, in __CPP03__ local classes (and therefore the local function objects they implement) cannot be passed as template parameters (e.g., to the `std::for_each` algorithm), this is instead possible in __CPP11__, MSVC, and some other compilers (see __N2657__). -To work around this limitation, this library investigated the following two "tricks" (both tricks can be extended to support eventual function default parameters): +However, in __CXX03__ local classes (and therefore the local function objects they implement) cannot be passed as template parameters (e.g., to the `std::for_each` algorithm), this is instead possible in __CXX11__, MSVC, and some other compilers (see __N2657__ and __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`). +To work around this limitation, this library investigated the following two "tricks" (both tricks can be extended to support function default parameters): # The /casting functor trick/ uses a non-local functor that calls a static member function of the local class via a function pointer. -The static member function then calls the correct local function body after type casting the object from a `void*` pointer (local classes can always be used for type casting). +The static member function then calls the correct local function body after type casting the object from a `void*` pointer (local classes can always be used for type casting via `static_cast` or similar). # The /virtual functor trick/ derives the local functor class from a non-local base class. -The correct overridden implementation of the virtual `operator()` is then called via polymorphism. +The correct overridden implementation of the virtual `operator()` is then called via dynamic binding. For example (see also [@../../example/impl_tparam_tricks.cpp =impl_tparam_tricks.cpp=]): [impl_tparam_tricks] The casting functor trick measured slightly better run-time performances than the virtual functor trick so the current implementation of this library uses the casting functor trick (probably because in addition to the indirect function call, the virtual functor trick also requires accessing the [@http://en.wikipedia.org/wiki/Virtual_method_table virtual function table]). -However, neither one of tricks has been observed to allow for compiler optimizations that inline the local function calls (because they rely on one indirect function call via either a function pointer or a virtual function respectively). -Therefore, on compilers that accept local types as template parameters (MSVC, __CPP11__, etc, see __N2657__), this library automatically generates code that passes the local class type directly as template parameter without using neither one of these two tricks in order to take full advantage of compiler optimizations that inline the local function calls. +However, neither one of the two tricks was observed to allow for compiler optimizations that inline the local function calls (because they rely on one indirect function call via either a function pointer or a virtual function respectively). +Therefore, on compilers that accept local classes as template parameters (MSVC, __CXX11__, etc, see __N2657__ and __Boost_Config__'s `BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS`), this library automatically generates code that passes the local class type directly as template parameter without using neither one of these two tricks in order to take full advantage of compiler optimizations that inline the local function calls. -[h5 Parsing Macros] +[heading Parsing Macros] This library macros can parse the list of specified parameters and detect if any of the bound variable names matches the token `this_` (to generate special code to bind the object in scope), or if the variable is bound by `const` (to generate special code to bind by constant), etc. -The parameter tokens are inspected using preprocessor metaprogramming and specifically using the macros defined by the files in the =boost/local_function/detail/preprocessor/keyword/= directory. +The parameter tokens are inspected using preprocessor meta-programming and specifically using the macros defined by the files in the =boost/local_function/detail/preprocessor/keyword/= directory. [footnote This technique is at the core of even more complex preprocessor parsing macros like the ones that parse the __Contractpp__ syntax. ] diff --git a/doc/introduction.qbk b/doc/introduction.qbk index 2f80305..a9d1456 100644 --- a/doc/introduction.qbk +++ b/doc/introduction.qbk @@ -5,18 +5,18 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Introduction Introduction] +[section Introduction] -/Local functions/ are a form of /information hiding/ and they are useful for dividing procedural tasks into subtasks which are only meaningful locally, avoiding cluttering other parts of the program with functions, variables, etc unrelated to those parts. -Local functions therefore complement other structuring possibilities such as namespaces and classes. -Local functions are a feature of many programming languages, notably [@http://en.wikipedia.org/wiki/Nested_function#An_example Pascal] and [@http://en.wikipedia.org/wiki/Nesting_(computing)#In_programming Ada], yet lacking from __CPP03__ (see also __N2511__). +/Local functions/ (a.k.a., [@http://en.wikipedia.org/wiki/Nested_function /nested functions/]) are a form of /information hiding/ and they are useful for dividing procedural tasks into subtasks which are only meaningful locally, avoiding cluttering other parts of the program with functions, variables, etc unrelated to those parts. +Therefore, local functions complement other structuring possibilities such as namespaces and classes. +Local functions are a feature of many programming languages, notably [@http://en.wikipedia.org/wiki/Nested_function#An_example Pascal] and [@http://en.wikipedia.org/wiki/Nesting_(computing)#In_programming Ada], yet lacking from __CXX03__ (see also __N2511__). -Using __CPP11_lambda__ functions, it is possible to implement local functions by naming the lambdas assigning them to local variables. -For example (see also [@../../test/add_lambda.cpp =add_lambda.cpp=]): +Using __CXX11_lambda_functions__, it is possible to implement local functions by naming lambda functions assigning them to local variables. +For example (see also [@../../example/add_cxx11_lambda.cpp =add_cxx11_lambda.cpp=]): -[add_lambda] +[add_cxx11_lambda] -This library allows to program local functions portably between __CPP03__ and __CPP11__ (and with performances comparable to lambdas on __CPP11__ compilers, see the __Alternatives__ section). +This library allows to program local functions portably between __CXX03__ and __CXX11__ (and with performances comparable to lambda functions on __CXX11__ compilers). For example (see also [@../../test/add.cpp =add.cpp=]): [add] @@ -25,16 +25,16 @@ This library supports the following features for local functions: * Local functions can capture, or better [@http://en.wikipedia.org/wiki/Name_binding /bind/], any of the variables from the enclosing scope (a function together with its captured variables is also called a [@http://en.wikipedia.org/wiki/Closure_(computer_science) /closure/]). * The local function body is programmed using the usual C++ statement syntax (as a consequence, compiler errors and debugging retain their usual meaning and format). -* Local functions can be passed as template parameters so they can be conveniently used with STL algorithms, etc. +* Local functions can be passed as template parameters so they can be conveniently used with STL algorithms and other templates. [footnote -This is a strength with respect to __CPP03__ functors implemented using local classes which cannot be passed as template parameters (see __N2657__ and the __Alternatives__ section). +This is a strength with respect to __CXX03__ functors implemented using local classes which cannot be passed as template parameters (see __N2657__ and the __Alternatives__ section). ] * However, local functions must be specified within a declarative context (e.g., at a point in the code where local variables can be declared) thus they cannot be specified within expressions. [footnote -This is a weakness with respect to __CPP11_lambda__ functions which can instead be specified also within expressions (see the __Alternatives__ section). +This is a weakness with respect to __CXX11_lambda_functions__ which can instead be specified also within expressions (see the __Alternatives__ section). ] -See the __Alternatives__ section for a comparison between this library, __CPP11_lambda__ functions, __Boost_Phoenix__, and other C++ techniques that implement features related to local functions. +See the __Alternatives__ section for a comparison between this library, __CXX11_lambda_functions__, __Boost_Phoenix__, and other C++ techniques that implement features related to local functions. [endsect] diff --git a/doc/local_function.qbk b/doc/local_function.qbk index e461e0a..42f92b6 100644 --- a/doc/local_function.qbk +++ b/doc/local_function.qbk @@ -19,8 +19,8 @@ [category Function Objects and Higher-Order Programming] ] -[def __CPP03__ [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03]] -[def __CPP11__ [@http://www.open-std.org/JTC1/SC22/WG21/ C++11]] +[def __CXX03__ [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03]] +[def __CXX11__ [@http://www.open-std.org/JTC1/SC22/WG21/ C++11]] [def __C99__ [@http://www.open-std.org/jtc1/sc22/wg14/www/projects#9899 C99]] [def __Boost__ [@http://www.boost.org Boost]] [def __Boost_LocalFunction__ [@http://www.boost.org/libs/local_function Boost.LocalFunction]] @@ -38,7 +38,8 @@ [def __Boost_TypeTraits__ [@http://www.boost.org/libs/type_traits Boost.TypeTraits]] [def __Boost_Utility_IdentityType__ [@http://www.boost.org/libs/utility/identity_type Boost.Utility/IdentityType]] [def __Boost_Chrono__ [@http://www.boost.org/libs/chrono Boost.Chrono]] -[def __CPP11_lambda__ [@http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions C++11 lambda]] +[def __Boost_Config__ [@http://www.boost.org/libs/chrono Boost.Config]] +[def __CXX11_lambda_functions__ [@http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions C++11 lambda functions]] [def __LISP__ [@http://en.wikipedia.org/wiki/Lisp_(programming_language) LISP]] [def __Contractpp__ [@http://sourceforge.net/projects/contractpp Contract++]] [def __D_Programming_Language__ [@http://d.digitalmars.com D Programming Language]] @@ -49,23 +50,22 @@ [def __N2550__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf \[N2550\]]] [def __N2657__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm \[N2657\]]] -[def __Introduction__ [link boost_localfunction.Introduction Introduction]] -[def __Getting_Started__ [link boost_localfunction.Getting_Started Getting Started]] -[def __Tutorial__ [link boost_localfunction.Tutorial Tutorial]] -[def __Advanced_Topics__ [link boost_localfunction.Advanced_Topics Advanced Topics]] -[def __Examples__ [link boost_localfunction.Examples Examples]] +[def __Introduction__ [link boost_localfunction.introduction Introduction]] +[def __Getting_Started__ [link boost_localfunction.getting_started Getting Started]] +[def __Tutorial__ [link boost_localfunction.tutorial Tutorial]] +[def __Advanced_Topics__ [link boost_localfunction.advanced_topics Advanced Topics]] +[def __Examples__ [link boost_localfunction.examples Examples]] [def __Reference__ [@reference.html Reference]] -[def __Alternatives__ [link boost_localfunction.Alternatives Alternatives]] -[def __No_Variadic_Macros__ [link boost_localfunction.No_Variadic_Macros No Variadic Macros]] -[def __Implementation__ [link boost_localfunction.Implementation Implementation]] -[def __Release_Notes__ [link boost_localfunction.Release_Notes Release Notes]] -[def __Bibliography__ [link boost_localfunction.Bibliography Bibliography]] -[def __Acknowledgments__ [link boost_localfunction.Acknowledgments Acknowledgments]] +[def __Alternatives__ [link boost_localfunction.alternatives Alternatives]] +[def __No_Variadic_Macros__ [link boost_localfunction.no_variadic_macros No Variadic Macros]] +[def __Implementation__ [link boost_localfunction.implementation Implementation]] +[def __Release_Notes__ [link boost_localfunction.release_notes Release Notes]] +[def __Bibliography__ [link boost_localfunction.bibliography Bibliography]] +[def __Acknowledgments__ [link boost_localfunction.acknowledgments Acknowledgments]] [import ../test/add.cpp] [import ../test/add_seq.cpp] -[import ../test/add_lambda.cpp] -[import ../test/add_params.cpp] +[import ../test/add_params_only.cpp] [import ../test/ten_void.cpp] [import ../test/add_this.cpp] [import ../test/add_template.cpp] @@ -83,20 +83,25 @@ [import ../test/overload.cpp] [import ../test/add_except.cpp] [import ../test/add_classifiers.cpp] -[import ../test/operator_err.cpp] -[import ../test/goto_err.cpp] -[import ../test/seq.cpp] +[import ../test/operator_error.cpp] +[import ../test/goto.cpp] +[import ../test/goto_error.cpp] +[import ../test/same_line.cpp] +[import ../example/add_cxx11_lambda.cpp] +[import ../example/gcc_lambda.hpp] [import ../example/gcc_lambda.cpp] -[import ../example/gcc_lambda_cpp11.cpp] -[import ../example/const_block_err.cpp] -[import ../example/scope_exit.cpp] +[import ../example/gcc_cxx11_lambda.cpp] +[import ../example/const_block.hpp] +[import ../example/const_block_error.cpp] +[import ../example/const_block_error_cxx11_lambda.cpp] [import ../example/scope_exit.hpp] +[import ../example/scope_exit.cpp] [import ../example/phoenix_factorial_local.cpp] [import ../example/phoenix_factorial.cpp] -[import ../example/noncopyable_lambda_err.cpp] +[import ../example/noncopyable_cxx11_lambda_error.cpp] [import ../example/noncopyable_local_function.cpp] -[import ../example/expensive_copy_lambda.cpp] +[import ../example/expensive_copy_cxx11_lambda.cpp] [import ../example/expensive_copy_local_function.cpp] [import ../example/add_local_functor.cpp] [import ../example/add_global_functor.cpp] @@ -104,17 +109,17 @@ [import ../example/impl_tparam_tricks.cpp] [import ../example/impl_pp_keyword.cpp] -This library allows to program functions locally, directly within the scope where they are needed. +This library allows to program functions locally, within other functions, and directly within the scope where they are needed. [include introduction.qbk] [include getting_started.qbk] [include tutorial.qbk] [include advanced_topics.qbk] [include examples.qbk] -[xinclude reference.xml] [include alternatives.qbk] [include no_variadic_macros.qbk] [include implementation.qbk] +[xinclude reference.xml] [include release_notes.qbk] [include bibliography.qbk] [include acknowledgements.qbk] diff --git a/doc/no_variadic_macros.qbk b/doc/no_variadic_macros.qbk index babd1ac..35f3548 100644 --- a/doc/no_variadic_macros.qbk +++ b/doc/no_variadic_macros.qbk @@ -5,13 +5,13 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:No_Variadic_Macros Annex: No Variadic Macros] +[section:no_variadic_macros Annex: No Variadic Macros] This section illustrates an alternative syntax for compilers without variadic macro support. -[h5 Sequence Syntax] +[heading Sequence Syntax] -Most modern compilers support [@http://en.wikipedia.org/wiki/Variadic_macro variaid macros] (notably, these include GCC, MSVC, and all __CPP11__ compilers). +Most modern compilers support [@http://en.wikipedia.org/wiki/Variadic_macro variaid macros] (notably, these include GCC, MSVC, and all __CXX11__ compilers). However, in the rare case that programmers need to use this library on a compiler without variadic macros, this library also allows to specify its macro parameters using a __Boost_Preprocessor__ sequence where tokens are separated by round parenthesis `()`: (token1) (token2) ... // All compilers. @@ -28,16 +28,41 @@ However, on compilers with variadic macros the comma-separated syntax we have se [add] -Note how the same macros accept both syntaxes on compilers with variadic macros and only the sequence syntax on compilers without variadic macros. -Finally, an parameter list is always specified using `void` on compilers with and without variadic macros: +Note that the same macros accept both syntaxes on compilers with variadic macros and only the sequence syntax on compilers without variadic macros. +Finally, an empty local function parameter list is always specified using `void` on compilers with and without variadic macros: [ten_void] -[h5 An Example] +[heading Examples] -The following example shows a bit of all the different macro parameter combinations using the sequence syntax (see also [@../../test/seq.cpp =seq.cpp=]): +For reference, the following is a list of most of the examples presented in this documentation reprogrammed using the sequence syntax instead of the comma-separated syntax (in alphabetic order): -[seq] +[table + [ [Files] ] + [ [[@../../test/add_classifiers_seq.cpp =add_classifiers_seq.cpp=]] ] + [ [[@../../test/add_default_seq.cpp =add_default_seq.cpp=]] ] + [ [[@../../test/add_except_seq.cpp =add_except_seq.cpp=]] ] + [ [[@../../test/add_inline_seq.cpp =add_inline_seq.cpp=]] ] + [ [[@../../test/add_params_only_seq.cpp =add_params_only_seq.cpp=]] ] + [ [[@../../test/add_template_seq.cpp =add_template_seq.cpp=]] ] + [ [[@../../test/add_this_seq.cpp =add_this_seq.cpp=]] ] + [ [[@../../test/add_typed_seq.cpp =add_typed_seq.cpp=]] ] + [ [[@../../test/add_with_default_seq.cpp =add_with_default_seq.cpp=]] ] + [ [[@../../test/all_decl_seq.cpp =all_decl_seq.cpp=]] ] + [ [[@../../test/factorial_seq.cpp =factorial_seq.cpp=]] ] + [ [[@../../test/macro_commas_seq.cpp =macro_commas_seq.cpp=]] ] + [ [[@../../test/nesting_seq.cpp =nesting_seq.cpp=]] ] + [ [[@../../test/overload_seq.cpp =overload_seq.cpp=]] ] + [ [[@../../test/return_assign_seq.cpp =return_assign_seq.cpp=]] ] + [ [[@../../test/return_derivative_seq.cpp =return_derivative_seq.cpp=]] ] + [ [[@../../test/return_inc_seq.cpp =return_inc_seq.cpp=]] ] + [ [[@../../test/return_setget_seq.cpp =return_setget_seq.cpp=]] ] + [ [[@../../test/return_this_seq.cpp =return_this_seq.cpp=]] ] + [ [[@../../test/same_line_seq.cpp =same_line_seq.cpp=]] ] + [ [[@../../test/transform_seq.cpp =transform_seq.cpp=]] ] + [ [[@../../test/typeof_seq.cpp =typeof_seq.cpp=]] ] + [ [[@../../test/typeof_template_seq.cpp =typeof_template_seq.cpp=]] ] +] [endsect] diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 8b1c54d..0fbf209 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -5,11 +5,11 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Release_Notes Release Notes] +[section Release Notes] This section lists the major changes between different library releases (in chronological order). -[h5 Version 1.0.0 (2012-01-31)] +[heading Version 1.0.0 (2012-04-12)] # Incorporated all comments from the [@http://lists.boost.org/boost-announce/2011/12/0340.php Boost review of this library]. # Removed local blocks and local exits. @@ -19,8 +19,11 @@ This section lists the major changes between different library releases (in chro # Added GCC lambda and constant block examples. # Moved `overloaded_function` to Boost.Functional/OverloadedFunction. # Moved `BOOST_IDENTITY_TYPE` to Boost.Utility/IdentityType. +# Completely removed use of Boost.Typeof when bound and result types are explicitly specified. +# Added `..._ID` macros for multiple expansions on the same line. +# Fixed compilation on Boost regression test platforms. -[h5 Version 0.2.0 (2011-05-14)] +[heading Version 0.2.0 (2011-05-14)] # Replaced parenthesized syntax with variadic and sequencing macro syntaxes. # Profiled library performances against other approaches. @@ -33,17 +36,17 @@ This section lists the major changes between different library releases (in chro # Added functor to overload local functions (and functors in general). # Implemented support for nesting local functions, blocks, and exits into one another. -[h5 Version 0.1.1 (2011-01-10)] +[heading Version 0.1.1 (2011-01-10)] # Uploaded library source into Boost SVN sandbox. # Fixed prev/next arrows and other minor layouts in documentation. # Added Release section to documentation. -[h5 Version 0.1.0 (2011-01-03)] +[heading Version 0.1.0 (2011-01-03)] # Shared with Boost for first round of comments. -[h5 Version 0.0.1 (2010-12-15)] +[heading Version 0.0.1 (2010-12-15)] # Completed development, examples, and documentation. diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 8d15c29..3313d58 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -5,14 +5,14 @@ [/ http://www.boost.org/LICENSE_1_0.txt) ] [/ Home at http://www.boost.org/libs/local_function ] -[section:Tutorial Tutorial] +[section Tutorial] -This section illustrates basic usages of this library. +This section illustrates basic usage of this library. [section Local Functions] Local functions are defined using macros from the header file [headerref boost/local_function.hpp]. -The macros must be used from within a declarative context (this is a limitation with respect to __CPP11_lambda__ functions which can instead be declared also within expressions): +The macros must be used from within a declarative context (this is a limitation with respect to __CXX11_lambda_functions__ which can instead be declared also within expressions): #include // This library header. @@ -33,7 +33,9 @@ Therefore the local function name cannot be specified within the [macroref BOOST ] The usual C++ scope visibility rules apply to local functions for which a local function is visible only within the enclosing scope in which it is declared. -The local function body is specified in a code block `{ ... }` using the usual C++ syntax. +The local function result type is specified just before the [macroref BOOST_LOCAL_FUNCTION] macro. + +The local function body is specified using the usual C++ statement syntax in a code block `{ ... }` between the [macroref BOOST_LOCAL_FUNCTION] and [macroref BOOST_LOCAL_FUNCTION_NAME] macros. The body is specified outside any of the macros so eventual compiler error messages and related line numbers retain their usual meaning and format. [footnote *Rationale.* @@ -46,14 +48,14 @@ The local function parameters are passed to the [macroref BOOST_LOCAL_FUNCTION] BOOST_LOCAL_FUNCTION(``[^/parameter-type1 parameter-name1/]``,`` [^/parameter-type2 parameter-name2, .../]``) The maximum number of parameters that can be passed to a local function is controlled at compile-time by the configuration macro [macroref BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX]. -For example, let's program a local function named `add` that adds together two integers `x` and `y` (see also [@../../test/add_params.cpp =add_params.cpp=]): +For example, let's program a local function named `add` that adds together two integers `x` and `y` (see also [@../../test/add_params_only.cpp =add_params_only.cpp=]): -[add_params] +[add_params_only] -If the local function has no parameter, it is possible to pass `void` to the [macroref BOOST_LOCAL_FUNCTION] macro (similarly to the C syntax that allows to use [^['result-type function-name]]`(void)` to declare a function with no parameter): +If the local function has no parameter, it is possible to pass `void` to the [macroref BOOST_LOCAL_FUNCTION] macro (similarly to the C++ syntax that allows to use [^['result-type function-name]]`(void)` to declare a function with no parameter): [footnote *Rationale.* -The __CPP03__ standard does not allow to pass empty parameters to a macro so the macro cannot be invoked as `BOOST_LOCAL_FUNCTION()`. +The __CXX03__ standard does not allow to pass empty parameters to a macro so the macro cannot be invoked as `BOOST_LOCAL_FUNCTION()`. On __C99__ compilers with properly implemented empty macro parameter support, it would be possible to allow `BOOST_LOCAL_FUNCTION()` but this is already not the case for MSVC so this syntax is never allowed to ensure better portability. ] @@ -67,9 +69,9 @@ For example, let's program a local function that always returns `10` (see also [ [section:Binding Binding Variables] -Variables in scope (local variables, enclosing function parameters, member variables, etc) can be bound to a local function declaration. +Variables in scope (local variables, enclosing function parameters, data members, etc) can be bound to a local function declaration. Only bound variables, static variables, global variables, functions, and enumerations from the enclosing scope are accessible from within the local function body. -The types of bound variables are deduced automatically by this library. +The types of bound variables are deduced automatically by this library using __Boost_Typeof__. [footnote *Rationale.* By binding a variable in scope, the local function declaration is specifying that such a variable should be accessible within the local function body regardless of its type. @@ -78,11 +80,6 @@ Therefore, contrary to the semantic of passing a function parameter, the semanti For example, this reduces maintenance because if a bound variable type is changed, the local function declaration does not have to change. ] -[important -The library implementation uses __Boost_Typeof__ to automatically deduce the types of the bound variables. -Therefore, in order to compile code in type-of emulation mode, all types should be properly registered with `BOOST_TYPEOF_REGISTER_TYPE` or `BOOST_TYPEOF_REGISTER_TEMPLATE` macros, or appropriate __Boost_Typeof__ headers should be included (see the __Boost_Typeof__ documentation for more detail). -] - This library introduces the new "keyword" `bind` [footnote Obviously, the token `bind` is not a keyword of the C++ language. @@ -110,18 +107,18 @@ Note that when `const` is used, it must always precede `bind`. [footnote *Rationale.* The library macros could have been implemented to accept both syntaxes `const bind ...` and `bind const ...` equivalently. -However, handling both syntaxes would have complicated the macro implementation without adding any feature so only one syntax (`const bind ...`) is supported. +However, handling both syntaxes would have complicated the macro implementation without adding any feature so only one syntax `const bind ...` is supported. ] If a variable is bound by value, then a copy of the variable value is taken at the point of the local function declaration. If a variable is bound by reference instead, the variable will refer to the value it has at the point of the local function call. Furthermore, it is the programmers' responsibility to ensure that variables bound by reference survive the existence scope of the local function otherwise the bound references will be invalid when the local function is called resulting in undefined behaviour (in other words, the usual care in using C++ references must be taken for variables bound by reference). -The type of a bound variable is automatically deduced and it is the exact same type used to declare such a variable in the enclosing scope with the following notes: +The type of a bound variable is automatically deduced using __Boost_Typeof__ and it is the exact same type used to declare such a variable in the enclosing scope with the following notes: * If a bound variable was declared constant in the enclosing scope, it will always be bound by constant value or constant reference even if `bind...` is used instead of `const bind...` . However, if a bound variable was not declared constant in the enclosing scope then it will not be bound as constant unless constant binding is forced using `const bind...`. -(Note that binding by constant reference is not supported by __CPP11_lambda__ functions but it is supported by this library.) +(Note that binding by constant reference is not supported by __CXX11_lambda_functions__ but it is supported by this library.) [footnote An historical note: Constant binding of variables in scope was the main use case that originally motivated the authors in developing this library. The authors needed to locally create a chuck of code to assert some correctness conditions while these assertions were not supposed to modify any of the variables they were using (see the __Contractpp__ library). @@ -132,10 +129,10 @@ This way if any of the assertions mistakenly changes a bound variable (for examp [footnote *Rationale.* Variables originally declared as references are bound by value unless `[const] bind&` is used so that references can be bound by both value `[const] bind` and reference `[const] bind&` (this is the same binding semantic adopted by __Boost_ScopeExit__). -On the other hand, variables originally declared as constants should never loose their `const` qualifier (to prevent their modification not just in the enclosing scope but also in the local scope) thus they are always bound by constant even if `bind[&]` is used instead of `const bind[&]`. +However, variables originally declared as constants should never loose their `const` qualifier (to prevent their modification not just in the enclosing scope but also in the local scope) thus they are always bound by constant even if `bind[&]` is used instead of `const bind[&]`. ] -When a variable is bound by value (constant or not), its type must be `CopyConstructible` (i.e., its must provide a copy constructor). +When a variable is bound by value (constant or not), its type must be [@http://www.boost.org/doc/libs/release/doc/html/CopyConstructible.html `CopyConstructible`] (i.e., its must provide a copy constructor). As with passing parameters to usual C++ functions, programmers might want to bind variables of complex types by (possibly constant) reference instead of by value to avoid expensive copy operations when these variables are bound to a local function. For example, let's program the local function `add` from the example in the __Introduction__ section. @@ -151,7 +148,7 @@ It is also possible to bind the object `this` when it is in scope (e.g., from an This is done by using the special symbol `this_` (instead of `this`) as the name of the variable to bind in the local function declaration and also to access the object within the local function body. [footnote *Rationale.* -The special name `this_` was chosen following [@http://boost.2283326.n4.nabble.com/local-this-or-this-td3423912.html Boost practises] which postfix with an underscore identifiers that are named after keywords (the C++ keyword `this` in this case). +The special name `this_` was chosen following [@http://lists.boost.org/Archives/boost/2011/04/179729.php Boost practise] to postfix with an underscore identifiers that are named after keywords (the C++ keyword `this` in this case). The special symbol `this_` is needed because `this` is a reserved C++ keyword so it cannot be used as the name of the internal parameter that passes the bound object to the local function body. It would have been possible to use `this` (instead of `this_`) within the local function body either at the expenses of copying the bound object (which would introduce run-time overhead and also the stringent requirement that the bound object must have a deep copy constructor) or by relying on an [@http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/d3a86f27277f713b undefined behaviour of `static_cast`] (which might not work on all platforms at the cost of portability). ] @@ -161,7 +158,7 @@ The library will generate a compile-time error if `this` is mistakenly used inst However, mistakenly using `this` instead of `this_` to access the object within the local function body will leads to undefined behaviour and it will not necessarily generate a compile-time error. [footnote *Rationale.* -The local function body cannot be a static member function of the local functor object in order to support recursion (because the local function name is specified by the [macroref BOOST_LOCAL_FUNCTION_NAME] macro only after the body so it must be made available via a functor member variable named after the local function and local classes cannot have static member variables in C++) and nesting (because the argument binding variable must be declared as a member variable so it is visible in a local function nested within the body member function) -- see the __Implementation__ section. +The local function body cannot be a static member function of the local functor object in order to support recursion (because the local function name is specified by the [macroref BOOST_LOCAL_FUNCTION_NAME] macro only after the body so it must be made available via a functor data member named after the local function and local classes cannot have static data members in C++) and nesting (because the argument binding variable must be declared as a data member so it is visible in a local function nested within the body member function) -- see the __Implementation__ section. Therefore, from within the local function body the variable `this` is visible but it refers to the local functor and not to the bound object. ] Programmers are ultimately responsible to make sure that `this` is never used within a local function. @@ -190,17 +187,19 @@ Note that the local function has access to all class members via the bound objec *Rationale.* This is possible because of the fix to C++ [@http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45 defect 45] that made inner and local types able to access all outer class members regardless of their access level. ] -Specifically, in the example above the local function updates the `private` data member `sum_`. +Specifically, in the example above the local function updates the private data member `sum_`. [endsect] [section Templates] -When local functions are programmed within templates, they need to be declared using the special macro [macroref BOOST_LOCAL_FUNCTION_TPL]: +When local functions are programmed within templates, they need to be declared using the special macros [macroref BOOST_LOCAL_FUNCTION_TPL] and [macroref BOOST_LOCAL_FUNCTION_NAME_TPL]: [footnote *Rationale.* Within templates, this library needs to use `typename` to explicitly indicate that some expressions evaluate to a type. -Because __CPP03__ does not allow to use `typename` outside templates, the special `TPL` macro is used to indicate that the enclosing scope is a template so this library can safely use `typename` to resolve expression type ambiguities. +Because __CXX03__ does not allow to use `typename` outside templates, the special `..._TPL` macros are used to indicate that the enclosing scope is a template so this library can safely use `typename` to resolve expression type ambiguities. +__CXX11__ and other compilers might compile local functions within templates even when the `..._TPL` macros are not used. +However, it is recommended to always use the `..._TPL` macros within templates to maximize portability. ] #include // This library header. @@ -210,11 +209,11 @@ Because __CPP03__ does not allow to use `typename` outside templates, the specia ... ``/result-type/`` BOOST_LOCAL_FUNCTION_TPL(``/parameters/``) { ``/body-code/`` - } BOOST_LOCAL_FUNCTION_NAME(``/name/``) + } BOOST_LOCAL_FUNCTION_NAME_TPL(``/name/``) ... } -The [macroref BOOST_LOCAL_FUNCTION_TPL] macro has the exact same syntax of the [macroref BOOST_LOCAL_FUNCTION] macro that we have seen so far. +The [macroref BOOST_LOCAL_FUNCTION_TPL] and [macroref BOOST_LOCAL_FUNCTION_NAME_TPL] macros have the exact same syntax of the [macroref BOOST_LOCAL_FUNCTION] and [macroref BOOST_LOCAL_FUNCTION_NAME] macros that we have seen so far. For example, let's program a local function similar to the one from the __Introduction__ section but within a template (see also [@../../test/add_template.cpp =add_template.cpp=]): diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 86842d4..1980271 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -7,23 +7,25 @@ import testing ; -project : requirements /boost//unit_test_framework ; +# Sun does not automatically detect type-of emulation mode (force it). +project : requirements sun:BOOST_TYPEOF_EMULATION ; +run add_cxx11_lambda.cpp ; run add_global_functor.cpp ; run add_local_functor.cpp ; -# I'm not sure why this does not compile... I've asked Booster. -#run add_phoenix.cpp ; +run add_phoenix.cpp ; run const_block.cpp ; -# Compilation fails for debug but not for release builds so commented out. -#compile-fail const_block_err.cpp ; +compile-fail const_block_error.cpp : debug : ; +run const_block_error.cpp : release : ; +compile-fail const_block_error_cxx11_lambda.cpp ; -run expensive_copy_lambda.cpp ; +run expensive_copy_cxx11_lambda.cpp ; run expensive_copy_local_function.cpp ; run gcc_access.cpp ; run gcc_lambda.cpp ; -run gcc_lambda_cpp11.cpp ; +run gcc_cxx11_lambda.cpp ; run gcc_square.cpp ; run gcc_store.cpp ; @@ -33,18 +35,19 @@ run impl_tparam_tricks.cpp ; run n2529_this.cpp ; run n2550_find_if.cpp ; -compile-fail noncopyable_lambda_err.cpp ; +compile-fail noncopyable_cxx11_lambda_error.cpp ; run noncopyable_local_function.cpp ; run phoenix_factorial.cpp ; run phoenix_factorial_local.cpp ; +# Only compile but do not run profiling programs (they take a long time to run). exe profile_global_functor : profile_global_functor.cpp : /boost/chrono//boost_chrono /boost/system//boost_system static ; -exe profile_lambda : profile_lambda.cpp +exe profile_cxx11_lambda : profile_cxx11_lambda.cpp : /boost/chrono//boost_chrono /boost/system//boost_system static diff --git a/test/add_lambda.cpp b/example/add_cxx11_lambda.cpp similarity index 64% rename from test/add_lambda.cpp rename to example/add_cxx11_lambda.cpp index 1e446e4..d7085bb 100644 --- a/test/add_lambda.cpp +++ b/example/add_cxx11_lambda.cpp @@ -6,15 +6,15 @@ // Home at http://www.boost.org/libs/local_function #include -#ifndef BOOST_NO_LAMBDAS +#ifdef BOOST_NO_LAMBDAS +# error "lambda functions required" +#else -#define BOOST_TEST_MODULE TestAddLambda -#include +#include #include -BOOST_AUTO_TEST_CASE( test_add_lambda ) -//[add_lambda -{ // Some local scope. +//[add_cxx11_lambda +int main(void) { // Some local scope. int sum = 0, factor = 10; // Variables in scope to bind. auto add = [factor, &sum](int num) { // C++11 only. @@ -25,13 +25,10 @@ BOOST_AUTO_TEST_CASE( test_add_lambda ) int nums[] = {2, 3}; std::for_each(nums, nums + 2, add); // Pass it to an algorithm. - BOOST_CHECK( sum == 60 ); // Assert final summation value. + BOOST_TEST(sum == 60); // Assert final summation value. + return boost::report_errors(); } //] -#else // NO_LAMBDAS - -int main(void) { return 0; } // Trivial program. - -#endif // NO_LAMBDAS +#endif diff --git a/example/add_global_functor.cpp b/example/add_global_functor.cpp index 479c1d3..229b315 100644 --- a/example/add_global_functor.cpp +++ b/example/add_global_functor.cpp @@ -5,8 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#define BOOST_TEST_MODULE TestAddGlobalFunctor -#include +#include #include //[add_global_functor @@ -17,12 +16,13 @@ struct global_add { // Unfortunately, boilerplate code to program the class. inline void operator()(int num) { // Body uses C++ statement syntax. sum += factor * num; } + private: // Unfortunately, cannot bind so repeat variable types. int& sum; // Access `sum` by reference. const int factor; // Make `factor` constant. }; -BOOST_AUTO_TEST_CASE( test_add_global_functor ) { +int main(void) { int sum = 0, factor = 10; global_add add(sum, factor); @@ -31,7 +31,8 @@ BOOST_AUTO_TEST_CASE( test_add_global_functor ) { int nums[] = {2, 3}; std::for_each(nums, nums + 2, add); // Passed as template parameter. - BOOST_CHECK( sum == 60 ); + BOOST_TEST(sum == 60); + return boost::report_errors(); } //] diff --git a/example/add_local_functor.cpp b/example/add_local_functor.cpp index f856d94..e75f83f 100644 --- a/example/add_local_functor.cpp +++ b/example/add_local_functor.cpp @@ -5,12 +5,10 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#define BOOST_TEST_MODULE TestAddLocalFunctor -#include +#include -BOOST_AUTO_TEST_CASE( test_add_local_functor ) //[add_local_functor -{ +int main(void) { int sum = 0, factor = 10; struct local_add { // Unfortunately, boilerplate code to program the class. @@ -19,6 +17,7 @@ BOOST_AUTO_TEST_CASE( test_add_local_functor ) inline void operator()(int num) { // Body uses C++ statement syntax. sum += factor * num; } + private: // Unfortunately, cannot bind so repeat variable types. int& sum; // Access `sum` by reference. const int factor; // Make `factor` constant. @@ -29,7 +28,8 @@ BOOST_AUTO_TEST_CASE( test_add_local_functor ) // Unfortunately, cannot pass as template parameter to `std::for_each`. for(size_t i = 0; i < 2; ++i) add(nums[i]); - BOOST_CHECK( sum == 60 ); + BOOST_TEST(sum == 60); + return boost::report_errors(); } //] diff --git a/example/add_phoenix.cpp b/example/add_phoenix.cpp index b971c8a..10b5342 100644 --- a/example/add_phoenix.cpp +++ b/example/add_phoenix.cpp @@ -6,14 +6,12 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestAddPhoenix -#include +#include #include #include -BOOST_AUTO_TEST_CASE( test_add_phoenix ) //[add_phoenix -{ +int main(void) { using boost::phoenix::let; using boost::phoenix::local_names::_f; using boost::phoenix::cref; @@ -26,10 +24,11 @@ BOOST_AUTO_TEST_CASE( test_add_phoenix ) // Passed to template, `factor` by constant, and defined in expression. std::for_each(nums, nums + 3, let(_f = cref(factor))[ // Unfortunately, body cannot use C++ statement syntax. - ref(sum) += _f * _1 // Access `sum` by reference. + ref(sum) += _f * _1, _1 // Access `sum` by reference. ]); - BOOST_CHECK( sum == 60 ); + BOOST_TEST(sum == 60); + return boost::report_errors(); } //] diff --git a/example/chrono.py b/example/chrono.py index 0766821..84d6dfb 100755 --- a/example/chrono.py +++ b/example/chrono.py @@ -9,7 +9,10 @@ import sys import time import os -# Usage: python crono.py COMMAND [COMMAND_OPTIONS] +if len(sys.argv) < 2: + print "Usage: python " + sys.argv[0] + " COMMAND [COMMAND_OPTIONS]" + print "Measure run-time of executing the specified command." + exit(1) cmd = "" for arg in sys.argv[1:]: cmd += str(arg) + " " diff --git a/example/const_block.hpp b/example/const_block.hpp index 824fb01..c8d828b 100644 --- a/example/const_block.hpp +++ b/example/const_block.hpp @@ -17,25 +17,28 @@ #include #include #include -#include // PRIVATE // #define CONST_BLOCK_BIND_(r, unused, i, var) \ BOOST_PP_COMMA_IF(i) const bind& var -#define CONST_BLOCK_(list) \ +//[const_block_macro +#define CONST_BLOCK_(variables) \ void BOOST_LOCAL_FUNCTION( \ - BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(list), \ + BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(variables), \ void BOOST_PP_TUPLE_EAT(3) \ , \ BOOST_PP_LIST_FOR_EACH_I \ - )(CONST_BLOCK_BIND_, ~, list) \ + )(CONST_BLOCK_BIND_, ~, variables) \ ) +//] +//[const_block_end_macro #define CONST_BLOCK_END_(id) \ - BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(const_assert_, id)) \ - BOOST_PP_CAT(const_assert_, id)(); /* call local function immediately */ + BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(const_block_, id)) \ + BOOST_PP_CAT(const_block_, id)(); /* call local function immediately */ +//] // PUBLIC // diff --git a/example/const_block_err.cpp b/example/const_block_error.cpp similarity index 100% rename from example/const_block_err.cpp rename to example/const_block_error.cpp diff --git a/example/const_block_error_cxx11_lambda.cpp b/example/const_block_error_cxx11_lambda.cpp new file mode 100644 index 0000000..862667d --- /dev/null +++ b/example/const_block_error_cxx11_lambda.cpp @@ -0,0 +1,28 @@ + +// 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/local_function + +#include +#ifdef BOOST_NO_LAMBDAS +# error "requires lambda functions" +#else + +#include + +int main(void) { + //[const_block_cxx11_lambda + int x = 1, y = 2; + const decltype(x)& const_x = x; // Constant so cannot be modified + const decltype(y)& const_y = y; // and reference so no copy. + [&const_x, &const_y]() { // Lambda functions (C++11 only). + assert(const_x = const_y); // Unfortunately, `const_` names. + }(); + //] + return 0; +} + +#endif // LAMBDAS + diff --git a/example/expensive_copy_lambda.cpp b/example/expensive_copy_cxx11_lambda.cpp similarity index 71% rename from example/expensive_copy_lambda.cpp rename to example/expensive_copy_cxx11_lambda.cpp index d87cff5..cebeba9 100644 --- a/example/expensive_copy_lambda.cpp +++ b/example/expensive_copy_cxx11_lambda.cpp @@ -6,25 +6,28 @@ // Home at http://www.boost.org/libs/local_function #include -#ifndef BOOST_NO_LAMBDAS +#ifdef BOOST_NO_LAMBDAS +# error "lambda functions required" +#else #include #include -//[expensive_copy_lambda +//[expensive_copy_cxx11_lambda struct n { int i; n(int _i): i(_i) {} - n(n const& x): i(x.i) { // Some time consuming copy. + n(n const& x): i(x.i) { // Some time consuming copy operation. for (unsigned i = 0; i < 10000; ++i) std::cout << '.'; } }; + int main(void) { n x(-1); auto f = [x]() { // Problem: Expensive copy, but if bind - assert( x.i == -1); // by `&x` then `x` is not constant. + assert(x.i == -1); // by `&x` then `x` is not constant. }; f(); @@ -32,9 +35,5 @@ int main(void) { } //] -#else // NO_LAMBDAS - -int main(void) { return 0; } // Trivial program. - #endif // NO_LAMBDAS diff --git a/example/expensive_copy_local_function.cpp b/example/expensive_copy_local_function.cpp index d732533..ed67fec 100644 --- a/example/expensive_copy_local_function.cpp +++ b/example/expensive_copy_local_function.cpp @@ -6,6 +6,8 @@ // Home at http://www.boost.org/libs/local_function #include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include #include @@ -13,16 +15,17 @@ struct n { int i; n(int _i): i(_i) {} - n(n const& x): i(x.i) { // Some time consuming copy. + n(n const& x): i(x.i) { // Some time consuming copy operation. for (unsigned i = 0; i < 10000; ++i) std::cout << '.'; } }; +BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below. int main(void) { n x(-1); - void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy - assert( x.i == -1 ); // and constant. + void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy expensive + assert(x.i == -1); // copy but constant. } BOOST_LOCAL_FUNCTION_NAME(f) f(); diff --git a/example/gcc_access.cpp b/example/gcc_access.cpp index bd7872b..0b0e171 100644 --- a/example/gcc_access.cpp +++ b/example/gcc_access.cpp @@ -6,18 +6,18 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestGccAccess -#include +#include -BOOST_AUTO_TEST_CASE( test_gcc_access ) { +int main(void) { int nums[] = {1, 2, 3}; int offset = -1; int BOOST_LOCAL_FUNCTION(const bind offset, int* array, int index) { return array[index + offset]; } BOOST_LOCAL_FUNCTION_NAME(access) - BOOST_CHECK( access(nums, 1) == 1 ); - BOOST_CHECK( access(nums, 2) == 2 ); - BOOST_CHECK( access(nums, 3) == 3 ); + BOOST_TEST(access(nums, 1) == 1); + BOOST_TEST(access(nums, 2) == 2); + BOOST_TEST(access(nums, 3) == 3); + return boost::report_errors(); } diff --git a/example/gcc_lambda_cpp11.cpp b/example/gcc_cxx11_lambda.cpp similarity index 60% rename from example/gcc_lambda_cpp11.cpp rename to example/gcc_cxx11_lambda.cpp index 904bfa9..90c4a7e 100644 --- a/example/gcc_lambda_cpp11.cpp +++ b/example/gcc_cxx11_lambda.cpp @@ -6,14 +6,15 @@ // Home at http://www.boost.org/libs/local_function #include -#ifndef BOOST_NO_LAMBDAS +#ifdef BOOST_NO_LAMBDAS +# error "lambda functions required" +#else -#define BOOST_TEST_MODULE TestGccLambdaCpp11 -#include +#include #include -BOOST_AUTO_TEST_CASE( test_gcc_lambda_cpp11 ) { - //[gcc_lambda_cpp11 +int main(void) { + //[gcc_cxx11_lambda int val = 2; int nums[] = {1, 2, 3}; int* end = nums + 3; @@ -25,13 +26,10 @@ BOOST_AUTO_TEST_CASE( test_gcc_lambda_cpp11 ) { ); //] - BOOST_CHECK( iter != end ); - BOOST_CHECK( *iter == val ); + BOOST_TEST(iter != end); + BOOST_TEST(*iter == val); + return boost::report_errors(); } -#else // NO_LAMBDAS - -int main(void) { return 0; } // Trivial test. - -#endif // NO_LAMBDAS +#endif // LAMBDAS diff --git a/example/gcc_lambda.cpp b/example/gcc_lambda.cpp index 196c5e4..602ad81 100644 --- a/example/gcc_lambda.cpp +++ b/example/gcc_lambda.cpp @@ -6,14 +6,15 @@ // Home at http://www.boost.org/libs/local_function #include -#if defined(__GCC__) || !defined(BOOST_NO_LAMBDAS) +#ifndef __GNUC__ +# error "GCC required (using non-standard GCC statement expressions)" +#else #include "gcc_lambda.hpp" -#define BOOST_TEST_MODULE TestGccLambda -#include +#include #include -BOOST_AUTO_TEST_CASE( test_gcc_lambda ) { +int main(void) { //[gcc_lambda int val = 2; int nums[] = {1, 2, 3}; @@ -26,13 +27,10 @@ BOOST_AUTO_TEST_CASE( test_gcc_lambda ) { ); //] - BOOST_CHECK( iter != end ); - BOOST_CHECK( *iter == val ); + BOOST_TEST(iter != end); + BOOST_TEST(*iter == val); + return boost::report_errors(); } -#else // GCC || !NO_LAMBDAS - -int main(void) { return 0; } - -#endif // GCC || !NO_LAMBDAS +#endif // GCC diff --git a/example/gcc_lambda.hpp b/example/gcc_lambda.hpp index 561e3df..4bee7a1 100644 --- a/example/gcc_lambda.hpp +++ b/example/gcc_lambda.hpp @@ -65,6 +65,7 @@ BOOST_PP_LIST_FIRST(results)) #ifdef BOOST_NO_LAMBDAS +//[gcc_lambda_macro # define GCC_LAMBDA_(binds, params, results) \ ({ /* open statement expression (GCC extension only) */ \ BOOST_LOCAL_FUNCTION( \ @@ -78,6 +79,7 @@ ) \ )) \ ) +//] #else # define GCC_LAMBDA_(binds, params, results) \ /* ignore const binding because not supported by C++11 lambdas */ \ @@ -95,10 +97,12 @@ BOOST_PP_TUPLE_ELEM(3, 1, binds_params_results), \ BOOST_PP_TUPLE_ELEM(3, 2, binds_params_results)) +//[gcc_lambda_end_macro #define GCC_LAMBDA_END_(id) \ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(gcc_lambda_, id)) \ BOOST_PP_CAT(gcc_lambda_, id); \ }) /* close statement expression (GCC extension only) */ +//] // PUBLIC // diff --git a/example/gcc_square.cpp b/example/gcc_square.cpp index 9f7bbd7..6bd16e8 100644 --- a/example/gcc_square.cpp +++ b/example/gcc_square.cpp @@ -6,18 +6,18 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestGccSquare -#include +#include -double add_square(double a, double b) { - double BOOST_LOCAL_FUNCTION(double z) { +int add_square(int a, int b) { + int BOOST_LOCAL_FUNCTION(int z) { return z * z; } BOOST_LOCAL_FUNCTION_NAME(square) return square(a) + square(b); } -BOOST_AUTO_TEST_CASE( test_gcc_square ) { - BOOST_CHECK( add_square(2.0, 4.0) == 20.0 ); +int main(void) { + BOOST_TEST(add_square(2, 4) == 20); + return boost::report_errors(); } diff --git a/example/gcc_store.cpp b/example/gcc_store.cpp index aca8dd9..57b68ad 100644 --- a/example/gcc_store.cpp +++ b/example/gcc_store.cpp @@ -7,8 +7,7 @@ #include #include -#define BOOST_TEST_MODULE TestGccStore -#include +#include void intermediate(boost::function store_func, int size) { store_func(size - 1, -1); @@ -22,12 +21,13 @@ void hack(int* array, int size) { intermediate(store, size); } -BOOST_AUTO_TEST_CASE( test_gcc_store ) { +int main(void) { int nums[] = {1, 2, 3}; hack(nums, 3); - BOOST_CHECK( nums[0] == 1 ); - BOOST_CHECK( nums[1] == 2 ); - BOOST_CHECK( nums[2] == -1 ); + BOOST_TEST(nums[0] == 1); + BOOST_TEST(nums[1] == 2); + BOOST_TEST(nums[2] == -1); + return boost::report_errors(); } diff --git a/example/impl_pp_keyword.cpp b/example/impl_pp_keyword.cpp index 2598705..7a03ae7 100644 --- a/example/impl_pp_keyword.cpp +++ b/example/impl_pp_keyword.cpp @@ -9,8 +9,7 @@ #include #include #include -#define BOOST_TEST_MODULE TestImplPpKeyword -#include +#include // Expand to 1 if space-separated tokens end with `this_`, 0 otherwise. #define IS_THIS_BACK(tokens) \ @@ -20,9 +19,10 @@ tokens \ ))) -BOOST_AUTO_TEST_CASE( test_impl_pp_keyword ) { - BOOST_CHECK( IS_THIS_BACK(const bind this_) == 1 ); - BOOST_CHECK( IS_THIS_BACK(const bind& x) == 0 ); +int main(void) { + BOOST_TEST(IS_THIS_BACK(const bind this_) == 1); + BOOST_TEST(IS_THIS_BACK(const bind& x) == 0); + return boost::report_errors(); } //] diff --git a/example/impl_tparam_tricks.cpp b/example/impl_tparam_tricks.cpp index 924471a..aa394df 100644 --- a/example/impl_tparam_tricks.cpp +++ b/example/impl_tparam_tricks.cpp @@ -6,15 +6,14 @@ // Home at http://www.boost.org/libs/local_function //[impl_tparam_tricks -#define BOOST_TEST_MODULE TestImplTparamTricks -#include +#include #include #include // Casting functor trick. struct casting_func { - explicit casting_func(void* obj, void (*call)(void*, const int&)): - obj_(obj), call_(call) {} + explicit casting_func(void* obj, void (*call)(void*, const int&)) + : obj_(obj), call_(call) {} // Unfortunately, function pointer call is not inlined. inline void operator()(const int& num) { call_(obj_, num); } private: @@ -34,18 +33,17 @@ private: interface* func_; }; -BOOST_AUTO_TEST_CASE( test_impl_tparam_tricks ) { +int main(void) { int sum = 0, factor = 10; // Local class for local function. - struct local_add: virtual_func::interface { - explicit local_add(int& _sum, const int& _factor): - sum_(_sum), factor_(_factor) {} + struct local_add : virtual_func::interface { + explicit local_add(int& _sum, const int& _factor) + : sum_(_sum), factor_(_factor) {} inline void operator()(const int& num) { body(sum_, factor_, num); } - inline static void call( - void* obj, const int& num) { + inline static void call(void* obj, const int& num) { local_add* self = static_cast(obj); self->body(self->sum_, self->factor_, num); } @@ -62,11 +60,12 @@ BOOST_AUTO_TEST_CASE( test_impl_tparam_tricks ) { std::vector v(10); std::fill(v.begin(), v.end(), 1); -// std::for_each(v.begin(), v.end(), add_local); // Error but OK on C++11. + // std::for_each(v.begin(), v.end(), add_local); // Error but OK on C++11. std::for_each(v.begin(), v.end(), add_casting); // OK. std::for_each(v.begin(), v.end(), add_virtual); // OK. - BOOST_CHECK( sum == 200 ); + BOOST_TEST(sum == 200); + return boost::report_errors(); } //] diff --git a/example/n2529_this.cpp b/example/n2529_this.cpp index 2388588..1a954ad 100644 --- a/example/n2529_this.cpp +++ b/example/n2529_this.cpp @@ -6,11 +6,15 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestN2529This -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include #include #include +struct v; +BOOST_TYPEOF_REGISTER_TYPE(v) // Register before `bind this_` below. + struct v { std::vector nums; @@ -25,7 +29,7 @@ struct v { } }; -BOOST_AUTO_TEST_CASE( test_n2529_this ) { +int main(void) { std::vector n(3); n[0] = 1; n[1] = 2; n[2] = 3; @@ -35,8 +39,9 @@ BOOST_AUTO_TEST_CASE( test_n2529_this ) { v vn(n); vn.change_sign_all(i); - BOOST_CHECK( vn.nums.at(0) == -1 ); - BOOST_CHECK( vn.nums.at(1) == 2 ); - BOOST_CHECK( vn.nums.at(2) == -3 ); + BOOST_TEST(vn.nums.at(0) == -1); + BOOST_TEST(vn.nums.at(1) == 2); + BOOST_TEST(vn.nums.at(2) == -3); + return boost::report_errors(); } diff --git a/example/n2550_find_if.cpp b/example/n2550_find_if.cpp index 46e3596..f372707 100644 --- a/example/n2550_find_if.cpp +++ b/example/n2550_find_if.cpp @@ -6,8 +6,9 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestN2550FindIf -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include #include #include @@ -15,10 +16,11 @@ struct employee { int salary; explicit employee(const int& a_salary): salary(a_salary) {} }; +BOOST_TYPEOF_REGISTER_TYPE(employee) // Register for `NAME` below. -BOOST_AUTO_TEST_CASE( test_n2550_find_if ) { +int main(void) { std::vector employees; - employees.push_back(employee( 85000)); + employees.push_back(employee(85000)); employees.push_back(employee(100000)); employees.push_back(employee(120000)); @@ -35,7 +37,8 @@ BOOST_AUTO_TEST_CASE( test_n2550_find_if ) { std::vector::iterator i = std::find_if( employees.begin(), employees.end(), between); - BOOST_CHECK( i != employees.end() ); - BOOST_CHECK( i->salary >= min_salary && i->salary < u_limit ); + BOOST_TEST(i != employees.end()); + BOOST_TEST(i->salary >= min_salary && i->salary < u_limit); + return boost::report_errors(); } diff --git a/example/noncopyable_lambda_err.cpp b/example/noncopyable_cxx11_lambda_error.cpp similarity index 64% rename from example/noncopyable_lambda_err.cpp rename to example/noncopyable_cxx11_lambda_error.cpp index 6e92d12..6e9a66b 100644 --- a/example/noncopyable_lambda_err.cpp +++ b/example/noncopyable_cxx11_lambda_error.cpp @@ -6,22 +6,25 @@ // Home at http://www.boost.org/libs/local_function #include -#ifndef BOOST_NO_LAMBDAS +#ifdef BOOST_NO_LAMBDAS +# error "lambda functions required" +#else #include #include -//[noncopyable_lambda_err +//[noncopyable_cxx11_lambda_error struct n: boost::noncopyable { int i; n(int _i): i(_i) {} }; + int main(void) { n x(-1); - auto f = [x](void) { // Error: x is non-copyable, but if - assert( x.i == -1 ); // bind `&x` then `x` is not constant. + auto f = [x](void) { // Error: x is non-copyable, but if + assert(x.i == -1); // bind `&x` then `x` is not constant. }; f(); @@ -29,9 +32,5 @@ int main(void) { } //] -#else // NO_LAMBDAS - -#error "Trivial failure." - -#endif // NO_LAMBDAS +#endif // LAMBDAS diff --git a/example/noncopyable_local_function.cpp b/example/noncopyable_local_function.cpp index 9f76afb..b4ef9ad 100644 --- a/example/noncopyable_local_function.cpp +++ b/example/noncopyable_local_function.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() #include //[noncopyable_local_function @@ -14,12 +16,13 @@ struct n: boost::noncopyable { int i; n(int _i): i(_i) {} }; +BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below. -int main() { +int main(void) { n x(-1); void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy - assert( x.i == -1 ); // and constant. + assert(x.i == -1); // and constant. } BOOST_LOCAL_FUNCTION_NAME(f) f(); diff --git a/example/phoenix_factorial.cpp b/example/phoenix_factorial.cpp index e3cb92b..bdc8306 100644 --- a/example/phoenix_factorial.cpp +++ b/example/phoenix_factorial.cpp @@ -7,8 +7,7 @@ #include #include -#define BOOST_TEST_MODULE TestPhoenixFactorial -#include +#include //[phoenix_factorial struct factorial_impl { // Phoenix function from global functor. @@ -27,14 +26,15 @@ struct factorial_impl { // Phoenix function from global functor. } }; -BOOST_AUTO_TEST_CASE( test_phoenix_factorial ) { +int main(void) { using boost::phoenix::arg_names::arg1; boost::phoenix::function factorial; int i = 4; - BOOST_CHECK( factorial(i)() == 24 ); // Call. - BOOST_CHECK( factorial(arg1)(i) == 24 ); // Lazy call. + BOOST_TEST(factorial(i)() == 24); // Call. + BOOST_TEST(factorial(arg1)(i) == 24); // Lazy call. + return boost::report_errors(); } //] diff --git a/example/phoenix_factorial_local.cpp b/example/phoenix_factorial_local.cpp index 94f358f..c52c094 100644 --- a/example/phoenix_factorial_local.cpp +++ b/example/phoenix_factorial_local.cpp @@ -9,11 +9,10 @@ #include #include #include -#define BOOST_TEST_MODULE TestPhoenixFactorialLocal -#include +#include //[phoenix_factorial_local -BOOST_AUTO_TEST_CASE( test_phoenix_factorial_local ) { +int main(void) { using boost::phoenix::arg_names::arg1; int BOOST_LOCAL_FUNCTION(int n) { // Unfortunately, monomorphic. @@ -24,8 +23,9 @@ BOOST_AUTO_TEST_CASE( test_phoenix_factorial_local ) { factorial(factorial_impl); // Phoenix function from local function. int i = 4; - BOOST_CHECK( factorial(i)() == 24 ); // Call. - BOOST_CHECK( factorial(arg1)(i) == 24 ); // Lazy call. + BOOST_TEST(factorial(i)() == 24); // Call. + BOOST_TEST(factorial(arg1)(i) == 24); // Lazy call. + return boost::report_errors(); } //] diff --git a/example/profile_lambda.cpp b/example/profile_cxx11_lambda.cpp similarity index 90% rename from example/profile_lambda.cpp rename to example/profile_cxx11_lambda.cpp index a30ef8c..c07ee08 100644 --- a/example/profile_lambda.cpp +++ b/example/profile_cxx11_lambda.cpp @@ -6,7 +6,9 @@ // Home at http://www.boost.org/libs/local_function #include -#ifndef BOOST_NO_LAMBDAS +#ifdef BOOST_NO_LAMBDAS +# error "lambda functions required" +#else #include #include @@ -38,9 +40,5 @@ int main(int argc, char* argv[]) { return 0; } -#else // NO_LAMBDAS - -int main(void) { return 0; } // Trivial program. - -#endif // NO_LAMBDAS +#endif // LAMBDAS diff --git a/example/profile_gcc_cpp11_debug.png b/example/profile_gcc_cxx11_debug.png similarity index 100% rename from example/profile_gcc_cpp11_debug.png rename to example/profile_gcc_cxx11_debug.png diff --git a/example/profile_gcc_cpp11_release.png b/example/profile_gcc_cxx11_release.png similarity index 100% rename from example/profile_gcc_cpp11_release.png rename to example/profile_gcc_cxx11_release.png diff --git a/example/profile_legend_lambda.png b/example/profile_legend_cxx11_lambda.png similarity index 100% rename from example/profile_legend_lambda.png rename to example/profile_legend_cxx11_lambda.png diff --git a/example/scope_exit.cpp b/example/scope_exit.cpp index 438f8ca..607bf6b 100644 --- a/example/scope_exit.cpp +++ b/example/scope_exit.cpp @@ -10,13 +10,11 @@ #include #include #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() -#define BOOST_TEST_MODULE TestScopeExit -#include +#include #include #include #include -class person; BOOST_TYPEOF_REGISTER_TYPE(person) class person { friend class world; public: @@ -32,8 +30,8 @@ private: id_t id_; evolution_t evolution_; }; +BOOST_TYPEOF_REGISTER_TYPE(person) -class world; BOOST_TYPEOF_REGISTER_TYPE(world) class world { public: typedef unsigned int id_t; @@ -53,6 +51,7 @@ private: id_t next_id_; std::vector persons_; }; +BOOST_TYPEOF_REGISTER_TYPE(world) void world::add_person(person const& a_person) { persons_.push_back(a_person); @@ -87,17 +86,17 @@ void world::add_person(person const& a_person) { checkpoint = ++p.evolution_; } -BOOST_AUTO_TEST_CASE( test_scope_exit ) { +int main(void) { person adam, eva; std::ostringstream oss; oss << adam; std::cout << oss.str() << std::endl; - BOOST_CHECK( oss.str() == "person(0, 0)" ); + BOOST_TEST(oss.str() == "person(0, 0)"); oss.str(""); oss << eva; std::cout << oss.str() << std::endl; - BOOST_CHECK( oss.str() == "person(0, 0)" ); + BOOST_TEST(oss.str() == "person(0, 0)"); world w; w.add_person(adam); @@ -105,6 +104,7 @@ BOOST_AUTO_TEST_CASE( test_scope_exit ) { oss.str(""); oss << w; std::cout << oss.str() << std::endl; - BOOST_CHECK( oss.str() == "world(3, { person(1, 2), person(2, 2), })" ); + BOOST_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })"); + return boost::report_errors(); } diff --git a/example/scope_exit.hpp b/example/scope_exit.hpp index 2b1b387..795a2c1 100644 --- a/example/scope_exit.hpp +++ b/example/scope_exit.hpp @@ -25,10 +25,12 @@ private: // PRIVATE // +//[scope_exit_end_macro #define SCOPE_EXIT_END_(id) \ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(scope_exit_func_, id)) \ scope_exit BOOST_PP_CAT(scope_exit_, id)( \ BOOST_PP_CAT(scope_exit_func_, id)); +//] // PUBLIC // @@ -36,8 +38,10 @@ private: # define SCOPE_EXIT(void_or_seq) \ void BOOST_LOCAL_FUNCTION(void_or_seq) #else +//[scope_exit_macro # define SCOPE_EXIT(...) \ void BOOST_LOCAL_FUNCTION(__VA_ARGS__) +//] #endif #define SCOPE_EXIT_END \ diff --git a/include/boost/local_function.hpp b/include/boost/local_function.hpp index e447594..9f259e6 100644 --- a/include/boost/local_function.hpp +++ b/include/boost/local_function.hpp @@ -21,39 +21,43 @@ // PUBLIC // #ifdef BOOST_NO_VARIADIC_MACROS +# define BOOST_LOCAL_FUNCTION_ID(id, declarations) \ + BOOST_LOCAL_FUNCTION_AUX_DECL(id, 0 /* not within template */, \ + BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST( \ + declarations))) # define BOOST_LOCAL_FUNCTION(declarations) \ - BOOST_LOCAL_FUNCTION_AUX_DECL( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER \ - , 0 /* not within template */ \ - , BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(declarations)) \ - ) + BOOST_LOCAL_FUNCTION_ID( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, declarations) +# define BOOST_LOCAL_FUNCTION_ID_TPL(id, declarations) \ + BOOST_LOCAL_FUNCTION_AUX_DECL(id, 1 /* within template */, \ + BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST( \ + declarations))) # define BOOST_LOCAL_FUNCTION_TPL(declarations) \ - BOOST_LOCAL_FUNCTION_AUX_DECL( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER \ - , 1 /* within template */ \ - , BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(declarations)) \ - ) + BOOST_LOCAL_FUNCTION_ID_TPL( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, declarations) #else // VARIADIC +# define BOOST_LOCAL_FUNCTION_ID(id, ...) \ + BOOST_LOCAL_FUNCTION_AUX_DECL(id, 0 /* not within template */, \ + BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__))) # define BOOST_LOCAL_FUNCTION(...) \ - BOOST_LOCAL_FUNCTION_AUX_DECL( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER \ - , 0 /* not within template */ \ - , BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__)) \ - ) + BOOST_LOCAL_FUNCTION_ID( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, __VA_ARGS__) +# define BOOST_LOCAL_FUNCTION_ID_TPL(id, ...) \ + BOOST_LOCAL_FUNCTION_AUX_DECL(id, 1 /* within template */, \ + BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__))) # define BOOST_LOCAL_FUNCTION_TPL(...) \ - BOOST_LOCAL_FUNCTION_AUX_DECL( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER \ - , 1 /* within template */ \ - , BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__)) \ - ) + BOOST_LOCAL_FUNCTION_ID_TPL( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, __VA_ARGS__) #endif // VARIADIC -#define BOOST_LOCAL_FUNCTION_NAME(qualified_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_NAME(qualified_function_name) +#define BOOST_LOCAL_FUNCTION_NAME(qualified_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME(0 /* not within template */, qualified_name) +#define BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME(1 /* within template */, qualified_name) #define BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name) \ BOOST_LOCAL_FUNCTION_AUX_TYPEOF_TYPE(bound_variable_name) @@ -63,8 +67,8 @@ #else // DOXYGEN /** @file -@brief Local functions allow to program functions locally, directly within the -scope where they are needed. +@brief Local functions allow to program functions locally, within other +functions, and directly within the scope where they are needed. */ /** @@ -73,13 +77,14 @@ scope where they are needed. This macro must be used within a declarative context, it must follow the local function result type, it must be followed by the local function body code, and then by the @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro (see the -@RefSect{Tutorial} and @RefSectId{Advanced_Topics, Advanced Topics} sections): +@RefSect{tutorial, Tutorial} and @RefSect{advanced_topics, Advanced Topics} +sections): @code { // Some declarative context. ... result_type BOOST_LOCAL_FUNCTION(declarations) { ... // Body code. - } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name) + } BOOST_LOCAL_FUNCTION_NAME(qualified_name) ... } @endcode @@ -88,10 +93,10 @@ As usual, exceptions specifications can be optionally programmed just after the macro and before the body code block { ... } (but the exception specifications will only apply to the body code and not to the library code automatically generated by the macro expansion, see the -@RefSectId{Advanced_Topics, Advanced Topics} section). +@RefSect{advanced_topics, Advanced Topics} section). -Within templates, the special macro @RefMacro{BOOST_LOCAL_FUNCTION_TPL} must be -used instead of@RefMacro{BOOST_LOCAL_FUNCTION}. +Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_TPL} +and @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used. @Params @Param{declarations, @@ -122,16 +127,15 @@ cannot be used: void | declaration_sequence @endcode -Lexical conventions: token1 | token2 means either token1 or +(Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; -{expression} means the token resulting from the expression. +{expression} means the token resulting from the expression.) } @EndParams Note that on compilers that support variadic macros, commas can be used to separate the declarations resembling more closely the usual C++ function -declaration syntax. -This is the preferred syntax. +declaration syntax (this is the preferred syntax). However, for portability, on all C++ compilers (with and without variadic macros) the same library macros also accept parameter declarations specified as a Boost.Preprocessor sequence separated by round parenthesis (). @@ -147,54 +151,153 @@ macro declarations prefixed by return (but not in both places). Within the local function body it possible to access the result type using result_type, the type of the first parameter using arg1_type, the type of the second parameter using arg2_type, etc. The bound variable types can be accessed using @RefMacro{BOOST_LOCAL_FUNCTION_TYPEOF}. +This macro cannot be portably expanded multiple times on the same line. +In these cases, use the @RefMacro{BOOST_LOCAL_FUNCTION_ID} macro instead. + The maximum number of local function parameters (excluding bound variables) is specified by the configuration macro @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}. The maximum number of bound variables is specified by the configuration macro @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}. +The configuration macro +@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS} can be used to force +optimizations that reduce the local function call run-time overhead. @Note Local functions are functors so they can be assigned to other functors like boost::function (see Boost.Function). -@Note This macro cannot be portably used multiple times on the same line -(because on GCC and other compilers, it internally uses the line number -__LINE__ to generate unique identifiers). - -@See @RefSect{Tutorial} section, -@RefSectId{Advanced_Topics, Advanced Topics} section, -@RefMacro{BOOST_LOCAL_FUNCTION_TPL}, -@RefMacro{BOOST_LOCAL_FUNCTION_NAME}, -@RefMacro{BOOST_LOCAL_FUNCTION_TYPEOF}, +@See @RefSect{tutorial, Tutorial} section, +@RefSect{advanced_topics, Advanced Topics} section, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME}, @RefMacro{BOOST_LOCAL_FUNCTION_TPL}, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}, +@RefMacro{BOOST_LOCAL_FUNCTION_TYPEOF}, @RefMacro{BOOST_LOCAL_FUNCTION_ID}, @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}, -@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}. +@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}, +@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS}. */ #define BOOST_LOCAL_FUNCTION(declarations) /** -@brief This macro is used to start a local function declaration within templates. +@brief This macro is used to start a local function declaration within +templates. -This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION} when declaring a local function within a template. -A part from that, this macro has the exact same syntax as @RefMacro{BOOST_LOCAL_FUNCTION} (see @RefMacro{BOOST_LOCAL_FUNCTION} for more information): +This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION} when +declaring a local function within a template. +A part from that, this macro has the exact same syntax a +@RefMacro{BOOST_LOCAL_FUNCTION} (see @RefMacro{BOOST_LOCAL_FUNCTION} for more +information): @code -{ // Some declarative context with a template. +{ // Some declarative context within a template. ... result_type BOOST_LOCAL_FUNCTION_TPL(declarations) { ... // Body code. - } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name) + } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) ... } @endcode +Note that @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used with this +macro instead of @RefMacro{BOOST_LOCAL_FUNCTION_NAME}. + +This macro cannot be portably expanded multiple times on the same line. +In these cases, use the @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL} macro instead. + @Note C++03 does not allow to use typename outside templates. This library internally manipulates types, these operations require -typename but only within templates so this macro is used to indicate to -the library when the enclosing scope is a template. +typename but only within templates. +This macro is used to indicate to the library when the enclosing scope is a +template so the library can correctly use typename. -@See @RefSect{Tutorial} section, @RefMacro{BOOST_LOCAL_FUNCTION}, -@RefMacro{BOOST_LOCAL_FUNCTION_NAME}. +@See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_LOCAL_FUNCTION}, +@RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL}, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}. */ #define BOOST_LOCAL_FUNCTION_TPL(declarations) +/** +@brief This macro allows to declare multiple local functions on the same line. + +This macro is equivalent to @RefMacro{BOOST_LOCAL_FUNCTION} but it can be +expanded multiple times on the same line if different identifiers id are +provided for each expansion (see the +@RefSect{advanced_topics, Advanced Topics} section). + +@Params +@Param{id, +A unique identifier token which can be concatenated by the preprocessor +(__LINE__\, local_function_number_1_on_line_123\, etc). +} +@Param{declarations, +Same as the declarations parameter of the +@RefMacro{BOOST_LOCAL_FUNCTION} macro. +} +@EndParams + +The @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro should be used to end each one +of the multiple local function declarations as usual (and it will specify a +unique name for each local function). + +Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL} +must be used. + +@Note This macro can be useful when the local function macros are expanded +within user-defined macros (because macros all expand on the same line). +On some compilers (e.g., MSVC which supports the non-standard +__COUNTER__ macro) it might not be necessary to use this macro but +the use of this macro when expanding multiple local function macros on the same +line is always necessary to ensure portability (this is because this library +can only portably use __LINE__ to internally generate unique +identifiers). + +@See @RefSect{advanced_topics, Advanced Topics} section, +@RefMacro{BOOST_LOCAL_FUNCTION}, @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, +@RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL}. +*/ +#define BOOST_LOCAL_FUNCTION_ID(id, declarations) + +/** +@brief This macro allows to declare multiple local functions on the same line +within templates. + +This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION_TPL} when +declaring multiple local functions on the same line within a template. +A part from that, this macro has the exact same syntax as +@RefMacro{BOOST_LOCAL_FUNCTION_TPL} (see @RefMacro{BOOST_LOCAL_FUNCTION_TPL} +for more information). + +@Params +@Param{id, +A unique identifier token which can be concatenated by the preprocessor +(__LINE__\, local_function_number_1_on_line_123\, etc). +} +@Param{declarations, +Same as the declarations parameter of the +@RefMacro{BOOST_LOCAL_FUNCTION_TPL} macro. +} +@EndParams + +The @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro should be used to end each one +of the multiple local function declarations as usual (and it will specify a +unique name for each local function). + +Outside template, the macro @RefMacro{BOOST_LOCAL_FUNCTION_ID} should be used +to declare multiple local functions on the same line. + +@Note This macro can be useful when the local function macros are expanded +within user-defined macros (because macros all expand on the same line). +On some compilers (e.g., MSVC which supports the non-standard +__COUNTER__ macro) it might not be necessary to use this macro but +the use of this macro when expanding multiple local function macros on the same +line is always necessary to ensure portability (this is because this library +can only portably use __LINE__ to internally generate unique +identifiers). + +@See @RefSect{advanced_topics, Advanced Topics} section, +@RefMacro{BOOST_LOCAL_FUNCTION_TPL}, @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, +@RefMacro{BOOST_LOCAL_FUNCTION_ID}. +*/ +#define BOOST_LOCAL_FUNCTION_ID_TPL(id, declarations) + /** @brief This macro is used to end a local function declaration specifying its name. @@ -205,68 +308,115 @@ This macro must follow the local function body code block { ... }: ... result_type BOOST_LOCAL_FUNCTION(declarations) { ... // Body code. - } BOOST_LOCAL_FUNCTION_NAME(qualified_function_name) + } BOOST_LOCAL_FUNCTION_NAME(qualified_name) ... } @endcode +Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_TPL} and +@RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used. + @Params -@Param{qualified_function_name, +@Param{qualified_name, The name of the local function optionally qualified as follow: @code -qualified_function_name: - [inline] [recursive] name + name: + [inline] [recursive] local_function_name @endcode -Lexical conventions: token1 | token2 means either token1 or +(Lexical conventions: token1 | token2 means either token1 or token2; [token] means either token or nothing; -{expression} means the token resulting from the expression. +{expression} means the token resulting from the expression.) } @EndParams The local function name can be qualified by prefixing it with the keyword -inline (see the @RefSectId{Advanced_Topics, Advanced Topics} section): -BOOST_LOCAL_FUNCTION_NAME(inline name). +inline (see the @RefSect{advanced_topics, Advanced Topics} section): +@code + BOOST_LOCAL_FUNCTION_NAME(inline local_function_name) +@endcode This increases the chances that the compiler will be able to inline the local function calls (thus reducing run-time). -However, inlined local functions cannot be passed as template parameters (e.g., to std::for_each) or assigned to other functors (e.g., to +However, inline local functions cannot be passed as template parameters (e.g., to std::for_each) or assigned to other functors (e.g., to boost::function). -That is true on C++03 compilers but inlined local functions can instead be +That is true on C++03 compilers but inline local functions can instead be passed as template parameters on C++11 compilers. On C++11 compilers, there is no need to declare a local function lined because this library will automatically use C++11 specific features to inline the local function while always allowing to pass it as a template parameter. +This optimization is automatically enabled when the Boost.Config macro +BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS is not defined but it also be +forced using @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS}. The local function name can also be qualified by prefixing it with the "keyword" recursive (see the -@RefSectId{Advanced_Topics, Advanced Topics} section): -BOOST_LOCAL_FUNCTION_NAME(recursive name). +@RefSect{advanced_topics, Advanced Topics} section): +@code + BOOST_LOCAL_FUNCTION_NAME(recursive local_function_name) +@endcode This allows the local function to recursively call itself from its body (as usual in C++). -However, compilers have not been observed to be able to inline recursive -local function calls (not even when the recursive local function is also -declared inline: BOOST_LOCAL_FUNCTION(inline recursive name)). -Furthermore, recursive local functions should only be called within their +However, recursive local functions should only be called within their declaration scope (otherwise the result is undefined behaviour). +Finally, compilers have not been observed to be able to inline recursive local +function calls, not even when the recursive local function is also declared +inline: +@code + BOOST_LOCAL_FUNCTION(inline recursive local_function_name) +@endcode @Note The local function name cannot be the name of an operator operator... and it cannot be the same name of another local function declared within the same enclosing scope (but boost::overloaded_function can be used to overload local functions, see Boost.Functional/OverloadedFunction and the -@RefSectId{Advanced_Topics, Advanced Topics} section). +@RefSect{advanced_topics, Advanced Topics} section). -@See @RefSect{Tutorial} section, -@RefSectId{Advanced_Topics, Advanced Topics} section, -@RefMacro{BOOST_LOCAL_FUNCTION}. +@See @RefSect{tutorial, Tutorial} section, +@RefSect{advanced_topics, Advanced Topics} section, +@RefMacro{BOOST_LOCAL_FUNCTION}, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}. */ -#define BOOST_LOCAL_FUNCTION_NAME(qualified_function_name) +#define BOOST_LOCAL_FUNCTION_NAME(qualified_name) + +/** +@brief This macro is used to end a local function declaration specifying its +name within templates. + +This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION_NAME} when +declaring a local function within a template. +A part from that, this macro has the exact same syntax a +@RefMacro{BOOST_LOCAL_FUNCTION_NAME} (see @RefMacro{BOOST_LOCAL_FUNCTION_NAME} +for more information): +@code +{ // Some declarative context within a template. + ... + result_type BOOST_LOCAL_FUNCTION_TPL(declarations) { + ... // Body code. + } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) + ... +} +@endcode + +Note that @RefMacro{BOOST_LOCAL_FUNCTION_TPL} must be used with this macro +instead of @RefMacro{BOOST_LOCAL_FUNCTION}. + +@Note C++03 does not allow to use typename outside templates. +This library internally manipulates types, these operations require +typename but only within templates. +This macro is used to indicate to the library when the enclosing scope is a +template so the library can correctly use typename. + +@See @RefSect{tutorial, Tutorial} section, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME}, @RefMacro{BOOST_LOCAL_FUNCTION_TPL}. +*/ +#define BOOST_LOCAL_FUNCTION_NAME_TPL(name) /** @brief This macro expands to the type of the specified bound variable. This macro can be used within the local functions body to refer to the bound variable types so to declare local variables, check concepts (using -Boost.ConceptCheck), etc (see the @RefSectId{Advanced_Topics, Advanced Topics} +Boost.ConceptCheck), etc (see the @RefSect{advanced_topics, Advanced Topics} section). This way the local function can be programmed entirely without explicitly specifying the bound variable types thus facilitating maintenance (e.g., if @@ -292,11 +442,13 @@ For example, if a variable named t of type T is: @li Bound by constant reference using const bind& t then BOOST_LOCAL_FUNCTION_TYPEOF(t) is const T&. -This macro must be prefixed by typename when used in a type dependant context. +This macro must be prefixed by typename when used within templates. -It is best to use this macro instead of Boost.Typeof so to reduce the number of times Boost.Typeof is used to deduce types (see the @RefSectId{Advanced_Topics, Advanced Topics} section). +@Note It is best to use this macro instead of Boost.Typeof so to reduce the +number of times Boost.Typeof is used to deduce types (see the +@RefSect{advanced_topics, Advanced Topics} section). -@See @RefSectId{Advanced_Topics, Advanced Topics} section, +@See @RefSect{advanced_topics, Advanced Topics} section, @RefMacro{BOOST_LOCAL_FUNCTION}. */ #define BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name) diff --git a/include/boost/local_function/aux_/config.hpp b/include/boost/local_function/aux_/config.hpp deleted file mode 100644 index 3f764ac..0000000 --- a/include/boost/local_function/aux_/config.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -// 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/local_function - -#ifndef BOOST_LOCAL_FUNCTION_AUX_CONFIG_HPP_ -#define BOOST_LOCAL_FUNCTION_AUX_CONFIG_HPP_ - -#include - -// PRIVATE // - -// FUTURE: Replace this with BOOST_NO_LOCAL_TYPES_AS_TEMPLATE_PARAMS after -// that macro is added to Boost.Config. -// If it is possible to pass local types (classes, etc) as template parameters. -// This is not possible in pure C++03 but it is possible in some C++03 -// extensions (MSVC, GCC 4.5.x, etc). -#if !((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)) && \ - defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(BOOST_MSVC) - // Not GCC 4.5.x with -std=c++0x and not MSVC. -# define BOOST_LOCAL_FUNCTION_AUX_CONFIG_NO_LOCAL_TYPES_AS_TEMPLATE_PARAMS -#endif - -// PUBLIC // - -#ifdef BOOST_LOCAL_FUNCTION_AUX_CONFIG_NO_LOCAL_TYPES_AS_TEMPLATE_PARAMS -# define BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 0 -#else -# define BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 1 -#endif - -#endif // #include guard - diff --git a/include/boost/local_function/aux_/function.hpp b/include/boost/local_function/aux_/function.hpp index 580c30a..55c9ca1 100644 --- a/include/boost/local_function/aux_/function.hpp +++ b/include/boost/local_function/aux_/function.hpp @@ -10,7 +10,6 @@ # define BOOST_LOCAL_FUNCTION_AUX_FUNCTION_HPP_ # include -# include # include # include # include @@ -35,6 +34,9 @@ #define BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC \ BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (init_call) ) +#define BOOST_LOCAL_FUNCTION_AUX_typename_seq(z, n, unused) \ + (typename) + #define BOOST_LOCAL_FUNCTION_AUX_arg_type(z, arg_n, unused) \ BOOST_PP_CAT(A, arg_n) @@ -111,7 +113,7 @@ #define BOOST_LOCAL_FUNCTION_AUX_call_typedef(z, n, arity) \ typedef R (*BOOST_LOCAL_FUNCTION_AUX_call_ptr(z, n, ~))( \ object_ptr \ - BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, \ BOOST_PP_TUPLE_EAT(3) \ , \ BOOST_PP_REPEAT_ ## z \ @@ -150,7 +152,7 @@ return BOOST_LOCAL_FUNCTION_AUX_call_member(z, defaults_n, ~)( \ object_ \ BOOST_PP_IIF( \ - BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01,\ + BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,\ BOOST_PP_TUPLE_EAT(3) \ , \ BOOST_PP_REPEAT_ ## z \ @@ -166,7 +168,7 @@ namespace boost { namespace local_function { namespace aux { template< typename F , size_t defaults -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam, ~) #endif @@ -184,15 +186,18 @@ class function {}; // Empty template, only use its specializations. // Register type for type-of emu (NAME use TYPEOF to deduce this fctor type). #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() BOOST_TYPEOF_REGISTER_TEMPLATE(boost::local_function::aux::function, - BOOST_PP_ADD(2, // F and defaults tparams. - BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, - 0 // No additional tparam. - , - BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX // Bind tparams. - ) - ) + (typename) // For `F` tparam. + (size_t) // For `defaults` tparam. + // MSVC error if using #if instead of PP_IIF here. + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, + BOOST_PP_TUPLE_EAT(3) // Nothing. + , + BOOST_PP_REPEAT // For bind tparams. + )(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, + BOOST_LOCAL_FUNCTION_AUX_typename_seq, ~) ) +#undef BOOST_LOCAL_FUNCTION_AUX_typename_seq #undef BOOST_LOCAL_FUNCTION_AUX_arg_type #undef BOOST_LOCAL_FUNCTION_AUX_arg_typedef #undef BOOST_LOCAL_FUNCTION_AUX_comma_arg_tparam @@ -235,7 +240,7 @@ template< typename R BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_AUX_arity, BOOST_LOCAL_FUNCTION_AUX_comma_arg_tparam, ~) -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam, ~) #endif @@ -246,7 +251,7 @@ class function< BOOST_LOCAL_FUNCTION_AUX_arg_type, ~) ) , BOOST_LOCAL_FUNCTION_AUX_defaults -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_comma_bind_type, ~) #endif @@ -282,7 +287,7 @@ public: // so used internal symbol. inline void BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC( object_ptr object -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_comma_bind_param_decl, ~) #endif @@ -290,7 +295,7 @@ public: BOOST_LOCAL_FUNCTION_AUX_comma_call_param_decl, ~) ) { object_ = object; -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_bind_member_init, ~) #endif @@ -308,7 +313,7 @@ public: private: object_ptr object_; -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, BOOST_LOCAL_FUNCTION_AUX_bind_member_decl, ~) #endif diff --git a/include/boost/local_function/aux_/macro/code_/bind.hpp b/include/boost/local_function/aux_/macro/code_/bind.hpp index 387612d..b235e73 100644 --- a/include/boost/local_function/aux_/macro/code_/bind.hpp +++ b/include/boost/local_function/aux_/macro/code_/bind.hpp @@ -64,11 +64,7 @@ id \ , \ /* ScopeExit expects typename or EMPTY() here */ \ - BOOST_PP_IIF(typename01, \ - BOOST_PP_IDENTITY(typename) \ - , \ - BOOST_PP_EMPTY \ - )() \ + BOOST_PP_EXPR_IIF(typename01, typename) \ ), \ i, BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \ bind_traits)) @@ -90,11 +86,9 @@ BOOST_PP_TUPLE_ELEM(2, 0, id_typename) \ , \ /* ScopeExit expects typename or EMPTY() here */ \ - BOOST_PP_IIF(BOOST_PP_TUPLE_ELEM(2, 1, id_typename), \ - BOOST_PP_IDENTITY(typename) \ - , \ - BOOST_PP_EMPTY \ - )() \ + BOOST_PP_EXPR_IIF(BOOST_PP_TUPLE_ELEM(2, 1, id_typename), \ + typename \ + ) \ ), \ i, BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \ bind_traits)) @@ -123,21 +117,28 @@ BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \ bind_traits)) +#define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \ + BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_capture_type)(id) ) + +#define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) \ + BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_type)(id) ) + #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_DEDUCED_( \ - id, all_bind_this_types) \ + id, typename01, all_bind_this_types) \ BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id)) + BOOST_PP_EXPR_IIF(typename01, typename), /* otherwise EMPTY() */ \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id)) #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_TYPED_( \ - id, all_bind_this_types) \ + id, typename01, all_bind_this_types) \ typedef \ BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_THIS_TYPE(BOOST_PP_LIST_FIRST( \ all_bind_this_types)) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \ ; #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_( \ - id, all_bind_this_types) \ + id, typename01, all_bind_this_types) \ /* typedef type_ */ \ BOOST_PP_IIF(BOOST_PP_IS_EMPTY( \ /* all_bind_this_type is list with 1 elem (possibly PP_EMPTY), */ \ @@ -147,7 +148,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_DEDUCED_ \ , \ BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_TYPED_ \ - )(id, all_bind_this_types) + )(id, typename01, all_bind_this_types) #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_ALL_( \ all_binds, all_bind_this_types, id, typename01) \ @@ -155,16 +156,21 @@ BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \ BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_ \ , \ - BOOST_PP_TUPLE_EAT(2) \ - )(id, all_bind_this_types) \ + BOOST_PP_TUPLE_EAT(3) \ + )(id, typename01, all_bind_this_types) \ BOOST_PP_LIST_FOR_EACH_I(BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_TAG_DECL_, id, \ all_binds) \ BOOST_PP_LIST_FOR_EACH_I(BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_, \ (id, typename01), all_binds) \ /* binding class */ \ struct BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) { \ + /* interim capture types to workaround internal error on old GCC */ \ BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ + typedef BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) ; \ + ) \ + BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) \ BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_VAR; \ ) \ BOOST_PP_LIST_FOR_EACH_I( \ @@ -207,8 +213,10 @@ // PUBLIC // -#define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_type)(id) ) +#define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) \ + BOOST_PP_EXPR_IIF(typename01, typename) \ + BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id):: \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_VAR \ BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_var) ) diff --git a/include/boost/local_function/aux_/macro/code_/end.hpp b/include/boost/local_function/aux_/macro/code_/end.hpp deleted file mode 100644 index 1ba8027..0000000 --- a/include/boost/local_function/aux_/macro/code_/end.hpp +++ /dev/null @@ -1,97 +0,0 @@ - -// 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/local_function - -#ifndef BOOST_CLOSURE_AUX_CODE_END_HPP_ -#define BOOST_CLOSURE_AUX_CODE_END_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// PRIVATE // - -#define BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_PTR_ \ - BOOST_CLOSURE_AUX_SYMBOL( (functor_ptr) ) - -#define BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_(id, \ - local_function_name, local_functor_name, nonlocal_functor_name) \ - /* `PARAMS() { ... }` expandsion here -- still within functor class */ \ - /* class functor ## __LINE__ { ... */ \ - public: \ - /* LIMITATION: member var used to deduce functor type using TYPEOF */ \ - /* (so it must be public, ptr to always allow for default init); */ \ - /* unfortunately, this introduces a dependency with Boost.Typeof */ \ - /* that cannot be removed even when all binds and result types are */ \ - /* explicitly specified but this is necessary because the functor */ \ - /* type is known to the CLOSURE macro which must pass it to the */ \ - /* END macro that is defined on a different line */ \ - BOOST_CLOSURE_AUX_CODE_FUNCTOR_TYPE* \ - BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_PTR_; \ - /* local functor can be passed as tparam only on C++11 (faster) */ \ - } local_functor_name(BOOST_CLOSURE_AUX_CLOSURE_ARGS_VAR.value); \ - /* non-local functor can always be passed as tparam (but slower) */ \ - BOOST_TYPEOF(*(local_functor_name.BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_PTR_))\ - nonlocal_functor_name; \ - /* initialization */ \ - local_functor_name.BOOST_CLOSURE_AUX_FUNCTION_INIT_CALL_FUNC( \ - &local_functor_name, nonlocal_functor_name); - -#define BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_VAR_(local_function_name) \ - BOOST_CLOSURE_AUX_SYMBOL( (local_function_name) ) - -// This can always be passed as a template parameters (on all compilers). -// However, it is slower because it cannot be inlined. -// Passed at tparam: Yes (on all C++). Inlineable: No. Recursive: No. -#define BOOST_CLOSURE_AUX_CODE_END_(local_function_name) \ - BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_(__LINE__, local_function_name, \ - /* local functor */ \ - BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_VAR_(local_function_name), \ - /* local function declared as non-local functor -- but it can */ \ - /* be inlined only by C++11 and it cannot be recursive */ \ - local_function_name) - -// This is faster on some compilers but not all (e.g., it is faster on GCC -// because its optimization inlines it but not on MSVC). However, it cannot be -// passed as a template parameter on non C++11 compilers. -// Passed at tparam: Only on C++11. Inlineable: Yes. Recursive: No. -#define BOOST_CLOSURE_AUX_CODE_END_INLINE_(local_function_name) \ - BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_(__LINE__, local_function_name, \ - /* inlined local function declared as local functor (maybe */ \ - /* inlined even by non C++11 -- but it can be passed as */ \ - /* template parameter only on C++11 */ \ - local_function_name, \ - /* non-local functor */ \ - BOOST_CLOSURE_AUX_CODE_END_FUNCTOR_VAR_(local_function_name)) - -// PUBLIC // - -// Inlined local functions are specified by `..._NAME(inline name)`. -// They have more chances to be inlined for faster run-times by some compilers -// (for example by GCC but not by MSVC). C++11 compilers can always inline -// local functions even if they are not explicitly specified inline. -#define BOOST_CLOSURE_AUX_CODE_END(qualified_name) \ - BOOST_PP_IIF(BOOST_PP_BITOR( \ - BOOST_CLOSURE_AUX_CONFIG_LOCAL_TYPES_AS_TEMPLATE_PARAMS_01, \ - BOOST_CLOSURE_DETAIL_PP_KEYWORD_IS_INLINE_FRONT(qualified_name)), \ - /* on C++11 always use inlining because compilers might optimize */ \ - /* it to be faster and it can also be passed as tparam */ \ - BOOST_CLOSURE_AUX_CODE_END_INLINE_ \ - , \ - /* on non C++11 don't use liniling unless explicitly specified by */ \ - /* programmers `inline name` the inlined local function cannot be */ \ - /* passed as tparam */ \ - BOOST_CLOSURE_AUX_CODE_END_ \ - )(BOOST_CLOSURE_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT(qualified_name)) - -#endif // #include guard - diff --git a/include/boost/local_function/aux_/macro/code_/functor.hpp b/include/boost/local_function/aux_/macro/code_/functor.hpp index 78735a2..cc34946 100644 --- a/include/boost/local_function/aux_/macro/code_/functor.hpp +++ b/include/boost/local_function/aux_/macro/code_/functor.hpp @@ -8,8 +8,8 @@ #ifndef BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_HPP_ #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_HPP_ +#include #include -#include #include #include #include @@ -237,14 +237,16 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_MAYBECONST_BIND_PARAM_DECL_( \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_MAYBECONST_BIND_PARAM_( \ BOOST_PP_TUPLE_ELEM(4, 2, id_typename_offset_const), i) -#define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_TYPE_(id) \ - , BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) +#define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_TYPE_( \ + id, typename01) \ + , BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BIND_THIS_PARAM_ \ bind_this -#define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_PARAM_DECL_(id) \ - , BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) & \ +#define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_PARAM_DECL_( \ + id, typename01) \ + , BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) & \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BIND_THIS_PARAM_ #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_NOBIND_(z, n, unused) \ @@ -323,8 +325,8 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_MAYBECONST_BIND_MEMBER_INIT_ENUM_( \ // Expand to the function type `R (A1, ...)`. #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_( \ - id, decl_traits, has_type, function_type) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ + id, typename01, decl_traits, has_type, function_type) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ BOOST_PP_EXPR_IIF(has_type, (function_type) ) \ ( \ BOOST_PP_LIST_FOR_EACH_I( \ @@ -383,7 +385,8 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_MAYBECONST_BIND_MEMBER_INIT_ENUM_( \ #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_CALL_(z, defaults_n, \ id, typename01, decl_traits, params, \ const_binds, has_const_bind_this, binds, has_bind_this) \ - inline BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) operator()( \ + inline BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ + operator()( \ BOOST_PP_LIST_FOR_EACH_I( \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_PARAM_ARG_DECL_ENUM_, \ typename01, params) \ @@ -423,8 +426,8 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ has_const_bind_this), \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_PARAM_DECL_ \ , \ - BOOST_PP_TUPLE_EAT(1) \ - )(id) \ + BOOST_PP_TUPLE_EAT(2) \ + )(id, typename01) \ /* fill with nobind_t (if no local-types as tparams) */ \ BOOST_PP_REPEAT(BOOST_PP_SUB(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, \ BOOST_PP_IIF(BOOST_PP_BITOR(has_bind_this, \ @@ -459,10 +462,10 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_(z, defaults_n, \ id, typename01, decl_traits, params, \ const_binds, has_const_bind_this, binds, has_bind_this) \ - inline static BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ + inline static BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_FUNC_(z, defaults_n, ~)( \ void* object \ - BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, \ BOOST_PP_TUPLE_EAT(6) \ , \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_ \ @@ -484,7 +487,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ static_cast< \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_CLASS_TYPE_(id)* \ >(object)-> \ - BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01,\ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,\ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_OPERATOR_ \ , \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_BODY_ \ @@ -541,8 +544,8 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ has_const_bind_this), \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_THIS_TYPE_ \ , \ - BOOST_PP_TUPLE_EAT(1) \ - )(id) \ + BOOST_PP_TUPLE_EAT(2) \ + )(id, typename01) \ /* fill with nobind_t (if no local-types as tparams) */ \ BOOST_PP_REPEAT(BOOST_PP_SUB(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, \ BOOST_PP_IIF(BOOST_PP_BITOR(has_bind_this, has_const_bind_this), \ @@ -575,7 +578,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ typedef BOOST_LOCAL_FUNCTION_AUX_TYPEOF_TYPE( \ BOOST_PP_EXPR_IIF(typename01, typename) \ ::boost::local_function::aux::add_pointed_const< \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) \ >::type \ this_ \ ) ; /* close typedef */ \ @@ -583,7 +586,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ /* ... or, non-const this */ \ BOOST_PP_EXPR_IIF(has_bind_this, \ typedef BOOST_LOCAL_FUNCTION_AUX_TYPEOF_TYPE( \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) \ this_ \ ) ; /* close typedef */ \ ) @@ -605,8 +608,9 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ /* bind this const or not (pointed-const is not added here because */ \ /* this is a reference, it is added to the this_ body param instead */ \ BOOST_PP_EXPR_IIF(BOOST_PP_BITOR(has_bind_this, has_const_bind_this), \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id)/* this is * so no & */\ - BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BIND_MEMBER_THIS_ \ + /* this is * so no & */ \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BIND_MEMBER_THIS_ \ ; /* end member variable declaration */ \ ) @@ -683,25 +687,27 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ #define BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_( \ id, typename01, decl_traits, params, \ default_count, const_binds, has_const_bind_this, binds, has_bind_this) \ - class BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_CLASS_TYPE_(id) \ + typedef class BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_CLASS_TYPE_(id) \ /* run-time: do not use base class to allow for compiler optimizations */ \ { \ /* function type */ \ + private: \ typedef \ - BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_(id, decl_traits, \ - 1 /* has type */, \ + BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_(id, typename01, \ + decl_traits, 1 /* has type */, \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_TYPE_) \ ; \ /* functor type -- this type cannot have ID postfix because it is */ \ /* used the `NAME` macro (this symbol is within functor class so */ \ - /* it does not have to have ID postfix) */ \ + /* it does not have to have ID postfix), must be public so it */ \ + /* can be accessed by `NAME` macro from outside this class */ \ + public: \ typedef BOOST_PP_EXPR_IIF(typename01, typename) \ BOOST_IDENTITY_TYPE(( /* IDENTITY for template param comma */ \ ::boost::local_function::aux::function< \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_TYPE_ \ , default_count \ - BOOST_PP_IIF( \ - BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,\ BOOST_PP_TUPLE_EAT(6) \ , \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_BIND_TYPES_\ @@ -711,6 +717,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ )) \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE \ ; \ + private: \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BIND_TYPEOF_TYPEDEFS_( \ id, typename01, \ const_binds, has_const_bind_this, binds, has_bind_this) \ @@ -719,7 +726,8 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ /* (traits must be defined in both this and the global functor) */ \ enum { arity = ::boost::function_traits< /* can't use static data */ \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_F_TYPE_ >::arity }; \ - typedef BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) result_type; \ + typedef BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ + result_type; \ BOOST_PP_LIST_FOR_EACH_I( \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_ARG_TYPEDEF_, \ typename01, params) \ @@ -764,8 +772,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ ) { \ functor.BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC( \ object \ - BOOST_PP_IIF( \ - BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,\ BOOST_PP_TUPLE_EAT(6) \ , \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_COMMA_STATIC_BINDS_ \ @@ -790,7 +797,7 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ /* body function (unfortunately, cannot be static to allow access */ \ /* to member var with local function name for recursion but doing */ \ /* so also allows the body to misuse `this` instead of `this_`) */ \ - inline BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ + inline BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_BODY_FUNC_( \ /* const binds */ \ BOOST_PP_LIST_FOR_EACH_I( \ @@ -823,14 +830,16 @@ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_STATIC_CALL_COMMA_BIND_PARAM_DECLS_( \ BOOST_PP_EXPR_IIF(has_const_bind_this, \ BOOST_PP_EXPR_IIF(typename01, typename) \ ::boost::local_function::aux::add_pointed_const< \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) \ - >::type const \ - this_ /* special name to access object this */ \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, \ + typename01) \ + >::type \ + const this_ /* special name to access object this */ \ ) \ /* const pointer to non-const object */ \ BOOST_PP_EXPR_IIF(has_bind_this, \ - BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id) const \ - this_ /* special name to access object this */ \ + BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, \ + typename01) \ + const this_ /* special name to access object this */ \ ) \ /* params (last because they can have defaults) */ \ BOOST_PP_COMMA_IF( \ diff --git a/include/boost/local_function/aux_/macro/code_/name.hpp b/include/boost/local_function/aux_/macro/code_/name.hpp deleted file mode 100644 index f73bab6..0000000 --- a/include/boost/local_function/aux_/macro/code_/name.hpp +++ /dev/null @@ -1,103 +0,0 @@ - -// 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/local_function - -#ifndef BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_HPP_ -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// PRIVATE // - -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_PTR_ \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (functor_ptr) ) - -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_(id, \ - local_function_name, local_functor_name, nonlocal_functor_name) \ - /* `PARAMS() { ... }` expandsion here -- still within functor class */ \ - /* class functor ## __LINE__ { ... */ \ - public: \ - /* LIMITATION: member var used to deduce functor type using TYPEOF */ \ - /* (so it must be public, ptr to always allow for default init); */ \ - /* unfortunately, this introduces a dependency with Boost.Typeof */ \ - /* that cannot be removed even when all binds and result types are */ \ - /* explicitly specified but this is necessary because the functor */ \ - /* type is known to the LOCAL_FUNCTION macro which must pass it to */ \ - /* the NAME macro that is defined on a different line */ \ - BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE* \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_PTR_; \ - /* local functor can be passed as tparam only on C++11 (faster) */ \ - } local_functor_name( \ - BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR.value); \ - /* non-local functor can always be passed as tparam (but slower) */ \ - BOOST_TYPEOF(*(local_functor_name. \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_PTR_)) \ - nonlocal_functor_name; \ - /* initialization */ \ - local_functor_name.BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC( \ - &local_functor_name, nonlocal_functor_name); - -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_VAR_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (local_function_name) ) - -// This can always be passed as a template parameters (on all compilers). -// However, it is slower because it cannot be inlined. -// Passed at tparam: Yes (on all C++). Inlineable: No. Recursive: No. -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_(__LINE__, local_function_name, \ - /* local functor */ \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_VAR_( \ - local_function_name), \ - /* local function declared as non-local functor -- but it can */ \ - /* be inlined only by C++11 and it cannot be recursive */ \ - local_function_name) - -// This is faster on some compilers but not all (e.g., it is faster on GCC -// because its optimization inlines it but not on MSVC). However, it cannot be -// passed as a template parameter on non C++11 compilers. -// Passed at tparam: Only on C++11. Inlineable: Yes. Recursive: No. -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_INLINE_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_(__LINE__, local_function_name, \ - /* inlined local function declared as local functor (maybe */ \ - /* inlined even by non C++11 -- but it can be passed as */ \ - /* template parameter only on C++11 */ \ - local_function_name, \ - /* non-local functor */ \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_FUNCTOR_VAR_( \ - local_function_name)) - -// PUBLIC // - -// Inlined local functions are specified by `..._NAME(inline name)`. -// They have more chances to be inlined for faster run-times by some compilers -// (for example by GCC but not by MSVC). C++11 compilers can always inline -// local functions even if they are not explicitly specified inline. -#define BOOST_LOCAL_FUNCTION_AUX_CODE_NAME(qualified_name) \ - BOOST_PP_IIF(BOOST_PP_BITOR( \ - BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_INLINE_FRONT( \ - qualified_name)), \ - /* on C++11 always use inlining because compilers might optimize */ \ - /* it to be faster and it can also be passed as tparam */ \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_INLINE_ \ - , \ - /* on non C++11 don't use liniling unless explicitly specified by */ \ - /* programmers `inline name` the inlined local function cannot be */ \ - /* passed as tparam */ \ - BOOST_LOCAL_FUNCTION_AUX_CODE_NAME_ \ - )(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ - qualified_name)) - -#endif // #include guard - diff --git a/include/boost/local_function/aux_/macro/code_/result.hpp b/include/boost/local_function/aux_/macro/code_/result.hpp index d4a3f2c..84334e7 100644 --- a/include/boost/local_function/aux_/macro/code_/result.hpp +++ b/include/boost/local_function/aux_/macro/code_/result.hpp @@ -21,86 +21,76 @@ // PRIVATE // -#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TAG_(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_tag)(id) ) - #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id) \ /* symbol (not internal) also gives error if missing result type */ \ BOOST_PP_CAT( \ ERROR_missing_result_type_before_the_local_function_parameter_macro_id, \ id) -#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_WRAP_(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_wrap)(id) ) - -#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_CAPTURE_(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_capture)(id) ) - #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) \ BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_params)(id) ) -#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_TYPE_(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (deduce_result_function_type)(id) ) +#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ + BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (result_type)(id) ) + +#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_ \ + /* this does not have to be an integral index because ScopeExit uses */ \ + /* just as a symbol to concatenate go generate unique symbols (but */ \ + /* if it'd ever needed to became integral, the number of function */ \ + /* params + 1 as in the macro CONFIG_ARITY_MAX could be used) */ \ + result // User did not explicitly specified result type, deduce it (using Typeof). #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DEDUCE_( \ id, typename01, decl_traits) \ + /* user specified result type here */ \ BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DECL(id) \ - /* the many tagging, wrapping, etc that follow are taken from ScopeExit */ \ - /* type deduction mechanism and they are necessary within templates */ \ - /* (at least on GCC) to work around an compiler internal error */ \ - typedef \ - void (*BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TAG_(id))( \ - int BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id) \ - ) \ - ; \ - typedef \ - BOOST_PP_IIF(typename01, BOOST_TYPEOF_TPL, BOOST_TYPEOF)( \ - ::boost::scope_exit::detail::wrap( \ - ::boost::scope_exit::detail::deref( \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id), \ - (BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TAG_(id))0 \ - ) \ - ) \ - ) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_WRAP_(id) \ - ; \ - typedef BOOST_PP_EXPR_IIF(typename01, typename) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_WRAP_(id)::type \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_CAPTURE_(id) \ - ; \ + /* tagging, wrapping, etc as from ScopeExit type deduction are */ \ + /* necessary within templates (at least on GCC) to work around an */ \ + /* compiler internal errors) */ \ + BOOST_SCOPE_EXIT_DETAIL_TAG_DECL(0, /* no recursive step r */ \ + id, BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ + BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(0, /* no recursive step r */ \ + ( id, BOOST_PP_EXPR_IIF(typename01, typename) ), \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ + /* extra struct to workaround GCC and other compiler's issues */ \ struct BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) { \ - /* this typedef is internal to struct so its name will not clash */ \ - typedef BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_CAPTURE_(id) \ - function_ptr; \ - }; \ - typedef BOOST_PP_EXPR_IIF(typename01, typename) \ - ::boost::remove_pointer< BOOST_PP_EXPR_IIF(typename01, typename) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id)::function_ptr \ - >::type \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_TYPE_(id) \ - ; \ - typedef BOOST_PP_EXPR_IIF(typename01, typename) \ - ::boost::function_traits< \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_TYPE_(id) \ - >::result_type \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ - ; + typedef \ + BOOST_PP_EXPR_IIF(typename01, typename) \ + ::boost::function_traits< \ + BOOST_PP_EXPR_IIF(typename01, typename) \ + ::boost::remove_pointer< \ + BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(id, \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_INDEX_, \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id)) \ + >::type \ + >::result_type \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ + ; \ + }; // Use result type as explicitly specified by user (no type deduction needed). // Precondition: RETURNS(decl_traits) != NIL #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPED_( \ id, typename01, decl_traits) \ - typedef \ - BOOST_PP_LIST_FIRST(BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_RETURNS( \ - decl_traits)) \ - BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ - ; + /* user specified result type here */ \ + struct BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) { \ + typedef \ + BOOST_PP_LIST_FIRST( \ + BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_RETURNS( \ + decl_traits)) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) \ + ; \ + }; // PUBLIC // -#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id) \ - BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (result_type)(id) ) +#define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE(id, typename01) \ + BOOST_PP_EXPR_IIF(typename01, typename) \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_PARAMS_(id) :: \ + BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_TYPE_(id) #define BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_DECL(id) \ /* result type here */ (*BOOST_LOCAL_FUNCTION_AUX_CODE_RESULT_FUNC_(id))(); diff --git a/include/boost/local_function/aux_/macro/name.hpp b/include/boost/local_function/aux_/macro/name.hpp index c74aa0a..7f6dc6a 100644 --- a/include/boost/local_function/aux_/macro/name.hpp +++ b/include/boost/local_function/aux_/macro/name.hpp @@ -8,14 +8,13 @@ #ifndef BOOST_LOCAL_FUNCTION_AUX_NAME_HPP_ #define BOOST_LOCAL_FUNCTION_AUX_NAME_HPP_ +#include #include #include #include #include #include #include -#include -#include #include #include #include @@ -23,6 +22,9 @@ // PRIVATE // +#define BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name) \ + BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (local_type)(local_function_name) ) + #define BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_ \ BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (init_recursion) ) @@ -34,40 +36,40 @@ BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (nonrecursive_local_function_name) ) \ ) -#define BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(id, \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \ local_function_name, is_recursive, \ local_functor_name, nonlocal_functor_name) \ - /* `PARAMS() { ... }` expandsion here -- still within functor class */ \ - /* class functor ## __LINE__ { ... */ \ - public: \ - /* member var with function name for recursive calls; must be */ \ - /* `public` because is it also used by this macro but outside */ \ - /* the functor class to deduce the functor type; it cannot be */ \ + /* FUNCTION macro expanded to: typedef class functor ## __LINE__ { ... */ \ + BOOST_PP_EXPR_IIF(is_recursive, \ + /* member var with function name for recursive calls; it cannot be */ \ /* `const` because it is init after construction (because */ \ /* constructor doesn't know local function name) */ \ /* run-time: even when optimizing, recursive calls cannot be */ \ /* optimized (i.e., they must be via the non-local functor) */ \ /* because this cannot be a mem ref because its name is not known */ \ /* by the constructor so it cannot be set by the mem init list */ \ + private: \ BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE \ BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_FUNC_(is_recursive, \ local_function_name); \ - BOOST_PP_EXPR_IIF(is_recursive, \ - /* run-time: the `init_recursion()` function cannot be called */ \ - /* by the constructor to allow for compiler optimization */ \ - /* (inlining) so it must be public */ \ - inline void BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_( \ - BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE& functor) { \ - local_function_name = functor; \ - } \ - ) \ + /* run-time: the `init_recursion()` function cannot be called */ \ + /* by the constructor to allow for compiler optimization */ \ + /* (inlining) so it must be public to be called (see below) */ \ + public: \ + inline void BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_( \ + BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE& functor) { \ + local_function_name = functor; \ + } \ + ) \ + } BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name); \ /* local functor can be passed as tparam only on C++11 (faster) */ \ - } local_functor_name(BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR.value); \ + BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name) \ + local_functor_name(BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR.value); \ /* non-local functor can always be passed as tparam (but slower) */ \ - BOOST_TYPEOF(local_functor_name. \ - BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_FUNC_(is_recursive, \ - local_function_name)) \ - nonlocal_functor_name; \ + BOOST_PP_EXPR_IIF(typename01, typename) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name):: \ + BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE \ + nonlocal_functor_name; /* functor variable */ \ /* the order of the following 2 function calls cannot be changed */ \ /* because init_recursion uses the local_functor so the local_functor */ \ /* must be init first */ \ @@ -87,8 +89,8 @@ // This can always be passed as a template parameters (on all compilers). // However, it is slower because it cannot be inlined. // Passed at tparam: Yes (on all C++). Inlineable: No. Recursive: No. -#define BOOST_LOCAL_FUNCTION_AUX_NAME_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(__LINE__, \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_(typename01, local_function_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \ local_function_name, \ /* local function is not recursive (because recursion and its */ \ /* initialization cannot be inlined even on C++11, */ \ @@ -104,8 +106,8 @@ // because its optimization inlines it but not on MSVC). However, it cannot be // passed as a template parameter on non C++11 compilers. // Passed at tparam: Only on C++11. Inlineable: Yes. Recursive: No. -#define BOOST_LOCAL_FUNCTION_AUX_NAME_INLINE_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(__LINE__, \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_INLINE_(typename01, local_function_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \ local_function_name, \ /* inlined local function is never recursive (because recursion */ \ /* and its initialization cannot be inlined)*/ \ @@ -120,8 +122,9 @@ // This is slower on all compilers (C++11 and non) because recursion and its // initialization can never be inlined. // Passed at tparam: Yes. Inlineable: No. Recursive: Yes. -#define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_(local_function_name) \ - BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(__LINE__, \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_( \ + typename01, local_function_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \ local_function_name, \ /* recursive local function -- but it cannot be inlined */ \ 1 /* recursive */ , \ @@ -135,9 +138,10 @@ // They have more chances to be inlined for faster run-times by some compilers // (for example by GCC but not by MSVC). C++11 compilers can always inline // local functions even if they are not explicitly specified inline. -#define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_INLINE_(qualified_name) \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_INLINE_( \ + typename01, qualified_name) \ BOOST_PP_IIF(BOOST_PP_BITOR( \ - BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01, \ + BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, \ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_INLINE_FRONT( \ qualified_name)), \ /* on C++11 always use inlining because compilers might optimize */ \ @@ -148,7 +152,7 @@ /* programmers `inline name` the inlined local function cannot be */ \ /* passed as tparam */ \ BOOST_LOCAL_FUNCTION_AUX_NAME_ \ - )(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ + )(typename01, BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ qualified_name)) // Expand to 1 iff `recursive name` or `recursive inline name` or @@ -178,18 +182,20 @@ // Recursive local function are specified by `..._NAME(recursive name)`. // They can never be inlined for faster run-time (not even by C++11 compilers). -#define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_(qualified_name) \ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_( \ + typename01, qualified_name) \ BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name), \ /* recursion can never be inlined (not even on C++11) */ \ BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_ \ , \ BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_INLINE_ \ - )(BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name)) + )(typename01, \ + BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name)) // PUBLIC // -#define BOOST_LOCAL_FUNCTION_AUX_NAME(qualified_name) \ - BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_(qualified_name) +#define BOOST_LOCAL_FUNCTION_AUX_NAME(typename01, qualified_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_(typename01, qualified_name) #endif // #include guard diff --git a/include/boost/local_function/aux_/member.hpp b/include/boost/local_function/aux_/member.hpp index 82beb6c..27d2973 100644 --- a/include/boost/local_function/aux_/member.hpp +++ b/include/boost/local_function/aux_/member.hpp @@ -16,24 +16,34 @@ template struct member_type { typedef T& reference; typedef T* pointer; }; + template struct member_type { typedef T*& reference; typedef T* pointer; }; + +template struct member_type { + typedef T* const& reference; + typedef T* pointer; +}; + template struct member_type { typedef T const*& reference; typedef T const* pointer; }; -template T* member_addr(T& data) { return &data; } -template T const* member_addr(T const& data) { return &data; } -template T* member_addr(T* data) { return data; } -template T const* member_addr(T const* data) { return data; } +template struct member_type { + typedef T const* const& reference; + typedef T const* pointer; +}; +// NOTE: Do not add specializations for T const[&/*] (ambiguous on VACPP). +template T* member_addr(T& data) { return &data; } +template T* member_addr(T* data) { return data; } + +// NOTE: Do not add specializations for T const[&/*] (ambiguous on VACPP). template T& member_deref(T& data) { return data; } -template T const& member_deref(T const& data) { return data; } template T& member_deref(T* data) { return *data; } -template T const& member_deref(T const* data) { return *data; } } } } // namespace diff --git a/include/boost/local_function/aux_/nobind.hpp b/include/boost/local_function/aux_/nobind.hpp index 9c3a77e..73afc6f 100644 --- a/include/boost/local_function/aux_/nobind.hpp +++ b/include/boost/local_function/aux_/nobind.hpp @@ -8,17 +8,21 @@ #ifndef BOOST_LOCAL_FUNCTION_AUX_NOBIND_HPP_ #define BOOST_LOCAL_FUNCTION_AUX_NOBIND_HPP_ -#include +#include // NOTE: The current implementation needs no-bind placeholders only when // local types cannot be passed as template parameters. -#if !BOOST_LOCAL_FUNCTION_AUX_CONFIG_LOCALS_AS_TPARAMS_01 +#if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS namespace boost { namespace local_function { namespace aux { typedef int nobind_t; // Tag no-bind type. -nobind_t nobind; // Global variable so all no-binds can reference it. +static nobind_t nobind; // Global variable so all no-binds can reference it. + +// NOTE: Used only to get rid of unused static variable `nobind` (this function +// is never actually called so it does not need to be defined). +void no_unused_nobind_warning_(nobind_t* ptr = &nobind); } } } // namespace diff --git a/include/boost/local_function/config.hpp b/include/boost/local_function/config.hpp index 7285695..bab2953 100644 --- a/include/boost/local_function/config.hpp +++ b/include/boost/local_function/config.hpp @@ -10,12 +10,25 @@ #ifndef DOXYGEN +#include + #ifndef BOOST_LOCAL_FUNCTION_CONFIG_FUNCTION_ARITY_MAX -#define BOOST_LOCAL_FUNCTION_CONFIG_FUNCTION_ARITY_MAX 5 +# define BOOST_LOCAL_FUNCTION_CONFIG_FUNCTION_ARITY_MAX 5 #endif #ifndef BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX -#define BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX 10 +# define BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX 10 +#endif + +#ifndef BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS +# ifdef BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS +# define BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS 0 +# else +# define BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS 1 +# endif +#elif BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS // If true, force it to 1. +# undef BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS +# define BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS 1 #endif #else // DOXYGEN @@ -36,8 +49,9 @@ When defined by programmers, this macro must be a non-negative integer number. excluding bound variables (which are instead specified by @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}). -@See @RefSect{Tutorial} section, @RefSectId{Getting_Started, Getting Started} -section, @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}. +@See @RefSect{tutorial, Tutorial} section, +@RefSect{getting_started, Getting Started} section, +@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}. */ #define BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX @@ -52,11 +66,48 @@ When defined by programmers, this macro must be a non-negative integer number. local function parameters (which are instead specified by @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}). -@See @RefSect{Tutorial} section, @RefSectId{Getting_Started, Getting Started} -section, @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}. +@See @RefSect{tutorial, Tutorial} section, +@RefSect{getting_started, Getting Started} section, +@RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}. */ #define BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX +/** +@brief Specify when local functions can be passed as template parameters +without introducing any run-time overhead. + +If this macro is defined to 1, this library will assume that the +compiler allows to pass local classes as template parameters: +@code + template void f(void) {} + + int main(void) { + struct local_class {}; + f(); + return 0; + } +@endcode +This is the case for C++11 compilers and some C++03 compilers (e.g., MSVC), but +it is not the case in general for most C++03 compilers (including GCC). +This will allow the library to pass local functions as template parameters +without introducing any run-time overhead (specifically without preventing the +compiler from optimizing local function calls by inlining their assembly code). + +If this macro is defined to 0 instead, this library will introduce +a run-time overhead associated to resolving a function pointer call in order to +still allow to pass the local functions as template parameters. + +It is recommended to leave this macro undefined. +In this case, the library will automatically define this macro to 0 if +the Boost.Config macro BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS is +defined for the specific compiler, and to 1 otherwise. + +@See @RefSect{getting_started, Getting Started} section, +@RefSect{advanced_topics, Advanced Topics} section, +@RefMacro{BOOST_LOCAL_FUNCTION_NAME}. +*/ +#define BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS + #endif // DOXYGEN #endif // #include guard diff --git a/include/boost/local_function/detail/preprocessor/keyword/facility/add.hpp b/include/boost/local_function/detail/preprocessor/keyword/facility/add.hpp index bf9ef31..13f5699 100644 --- a/include/boost/local_function/detail/preprocessor/keyword/facility/add.hpp +++ b/include/boost/local_function/detail/preprocessor/keyword/facility/add.hpp @@ -12,12 +12,12 @@ #include // `is_front_macro(tokens)` is 1 if `tokens` start w/ `keyword` to add, else 0. -#define BOOST_CLOURE_DETAIL_PP_KEYWORD_FACILITY_ADD_FRONT( \ +#define BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_FACILITY_ADD_FRONT( \ tokens, is_front_macro, keyword) \ BOOST_PP_EXPR_IIF(BOOST_PP_COMPL(is_front_macro(tokens)), keyword) tokens // `is_back_macro(tokens)` is 1 if `tokens` end with `keyword` to add, else 0. -#define BOOST_CLOURE_DETAIL_PP_KEYWORD_FACILITY_ADD_BACK( \ +#define BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_FACILITY_ADD_BACK( \ tokens, is_back_macro, keyword) \ tokens BOOST_PP_EXPR_IIF(BOOST_PP_COMPL(is_back_macro(tokens)), keyword) diff --git a/include/boost/local_function/detail/preprocessor/void_list.hpp b/include/boost/local_function/detail/preprocessor/void_list.hpp index acc6760..2a302c6 100644 --- a/include/boost/local_function/detail/preprocessor/void_list.hpp +++ b/include/boost/local_function/detail/preprocessor/void_list.hpp @@ -44,7 +44,7 @@ #ifdef BOOST_NO_VARIADIC_MACROS #define BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST_(is_void_macro, seq) \ - BOOST_LOCAL_FUNCTION_DETAIL_PP_VOId_LIST_HANDLE_SEQ_(is_void_macro, seq) + BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST_HANDLE_SEQ_(is_void_macro, seq) #else // VARIADICS diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 91ff04d..a12f5c3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -7,39 +7,45 @@ import testing ; -project : requirements /boost//unit_test_framework ; +# Sun does not automatically detect type-of emulation mode (force it). +project : requirements sun:BOOST_TYPEOF_EMULATION ; -run add.cpp ; -run add_classifiers.cpp ; -run add_default.cpp ; -run add_except.cpp ; -run add_inline.cpp ; -run add_lambda.cpp ; -run add_params.cpp ; -run add_template.cpp ; -run add_this.cpp ; -run add_typed.cpp ; -run add_with_default.cpp ; +rule vaseq ( command target ) +{ + $(command) $(target).cpp ; + $(command) $(target)_seq.cpp ; + $(command) $(target)_seq_nova.cpp ; +} + +vaseq run add ; +vaseq run add_classifiers ; +vaseq run add_default ; +vaseq run add_except ; +vaseq run add_inline ; +vaseq run add_params_only ; +vaseq run add_template ; +vaseq run add_this ; +vaseq run add_typed ; +vaseq run add_with_default ; +vaseq run all_decl ; +vaseq run factorial ; +vaseq run goto ; +vaseq compile-fail goto_error ; +vaseq run macro_commas ; +vaseq run nesting ; +vaseq run operator ; +vaseq compile-fail operator_error ; +vaseq run overload ; +vaseq run return_assign ; +vaseq run return_derivative ; +vaseq run return_inc ; +vaseq run return_setget ; +vaseq run return_this ; +vaseq run same_line ; +vaseq run transform ; +vaseq run typeof ; +vaseq run typeof_template ; -run factorial.cpp ; -run goto.cpp ; -compile-fail goto_err.cpp ; -run macro_commas.cpp ; -run nesting.cpp ; -run operator.cpp ; -compile-fail operator_err.cpp ; -run overload.cpp ; run ten_void.cpp ; -run transform.cpp ; -run typeof.cpp ; -run typeof_template.cpp ; - -run return_assign.cpp ; -run return_derivative.cpp ; -run return_inc.cpp ; -run return_setget.cpp ; -run return_this.cpp ; - -run add_seq.cpp ; -run seq.cpp ; +run ten_void_nova.cpp ; diff --git a/test/add.cpp b/test/add.cpp index 10994e9..d6f983d 100644 --- a/test/add.cpp +++ b/test/add.cpp @@ -5,14 +5,17 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAdd -#include +#include #include -BOOST_AUTO_TEST_CASE( test_add ) //[add -{ // Some local scope. +int main(void) { // Some local scope. int sum = 0, factor = 10; // Variables in scope to bind. void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { @@ -23,7 +26,10 @@ BOOST_AUTO_TEST_CASE( test_add ) int nums[] = {2, 3}; std::for_each(nums, nums + 2, add); // Pass it to an algorithm. - BOOST_CHECK( sum == 60 ); // Assert final summation value. + BOOST_TEST(sum == 60); // Assert final summation value. + return boost::report_errors(); } //] +#endif // VARIADIC_MACROS + diff --git a/test/add_classifiers.cpp b/test/add_classifiers.cpp index ed05a02..758e2c5 100644 --- a/test/add_classifiers.cpp +++ b/test/add_classifiers.cpp @@ -6,25 +6,25 @@ // Home at http://www.boost.org/libs/local_function #include -#ifdef BOOST_NO_AUTO_DECLARATIONS // No C++11 auto declarations. +#if !defined(BOOST_NO_AUTO_DECLARATIONS) +# error "auto-declarations not allowed (using `auto` as storage classifier)" +#elif defined(BOOST_NO_VARIADIC_MACROS) +# error "variadic macros required" +#else #include -#define BOOST_TEST_MODULE TestAddClassifiers -#include +#include -BOOST_AUTO_TEST_CASE( test_add_classifiers ) { +int main(void) { //[add_classifiers int BOOST_LOCAL_FUNCTION(auto int x, register int y) { // Classifiers. return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) //] - BOOST_CHECK( add(1, 2) == 3 ); + BOOST_TEST(add(1, 2) == 3); + return boost::report_errors(); } -#else // C++11 auto declarations. - -int main(void) { return 0; } // Trivial program. - -#endif +#endif // AUTO_DECLARATIONS && VARIADIC_MACROS diff --git a/test/add_classifiers_seq.cpp b/test/add_classifiers_seq.cpp new file mode 100644 index 0000000..4249d28 --- /dev/null +++ b/test/add_classifiers_seq.cpp @@ -0,0 +1,26 @@ + +// 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/local_function + +#include +#ifndef BOOST_NO_AUTO_DECLARATIONS +# error "auto-declarations not allowed (using `auto` as storage classifier)" +#else + +#include +#include + +int main(void) { + int BOOST_LOCAL_FUNCTION( (auto int x) (register int y) ) { + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + + BOOST_TEST(add(1, 2) == 3); + return boost::report_errors(); +} + +#endif // AUTO_DECLARATIONS + diff --git a/test/add_classifiers_seq_nova.cpp b/test/add_classifiers_seq_nova.cpp new file mode 100644 index 0000000..3462584 --- /dev/null +++ b/test/add_classifiers_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_classifiers_seq.cpp" + diff --git a/test/add_default.cpp b/test/add_default.cpp index 6247f07..902855f 100644 --- a/test/add_default.cpp +++ b/test/add_default.cpp @@ -5,18 +5,24 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#include -#define BOOST_TEST_MODULE TestAddDefault -#include +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else -BOOST_AUTO_TEST_CASE( test_add_default ) { +#include +#include + +int main(void) { //[add_default - int BOOST_LOCAL_FUNCTION(int x, int y, default 2) { // Default. + int BOOST_LOCAL_FUNCTION(int x, int y, default 2) { // Default parameter. return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) - BOOST_CHECK( add(1) == 3 ); + BOOST_TEST(add(1) == 3); //] + return boost::report_errors(); } -//] + +#endif // VARIADIC_MACROS diff --git a/test/add_default_seq.cpp b/test/add_default_seq.cpp new file mode 100644 index 0000000..8130a90 --- /dev/null +++ b/test/add_default_seq.cpp @@ -0,0 +1,19 @@ + +// 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/local_function + +#include +#include + +int main(void) { + int BOOST_LOCAL_FUNCTION( (int x) (int y)(default 2) ) { + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + + BOOST_TEST(add(1) == 3); + return boost::report_errors(); +} + diff --git a/test/add_default_seq_nova.cpp b/test/add_default_seq_nova.cpp new file mode 100644 index 0000000..92e4ea7 --- /dev/null +++ b/test/add_default_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_default_seq.cpp" + diff --git a/test/add_except.cpp b/test/add_except.cpp index c2cd08b..8cd82fe 100644 --- a/test/add_except.cpp +++ b/test/add_except.cpp @@ -5,11 +5,15 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#include -#define BOOST_TEST_MODULE TestAddExcept -#include +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else -BOOST_AUTO_TEST_CASE( test_except ) { +#include +#include + +int main(void) { //[add_except double sum = 0.0; int factor = 10; @@ -21,7 +25,10 @@ BOOST_AUTO_TEST_CASE( test_except ) { add(100); //] - - BOOST_CHECK( sum == 1000 ); + + BOOST_TEST(sum == 1000); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/add_except_seq.cpp b/test/add_except_seq.cpp new file mode 100644 index 0000000..be1d186 --- /dev/null +++ b/test/add_except_seq.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/local_function + +#include +#include + +int main(void) { + double sum = 0.0; + int factor = 10; + + void BOOST_LOCAL_FUNCTION( (const bind factor) (bind& sum) + (double num) ) throw() { + sum += factor * num; + } BOOST_LOCAL_FUNCTION_NAME(add) + + add(100); + + BOOST_TEST(sum == 1000); + return boost::report_errors(); +} + diff --git a/test/add_except_seq_nova.cpp b/test/add_except_seq_nova.cpp new file mode 100644 index 0000000..44f53a2 --- /dev/null +++ b/test/add_except_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_except_seq.cpp" + diff --git a/test/add_inline.cpp b/test/add_inline.cpp index 6045750..54e48ee 100644 --- a/test/add_inline.cpp +++ b/test/add_inline.cpp @@ -5,20 +5,23 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -//[ add_function_inline_cpp +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAddInline -#include +#include #include #include -BOOST_AUTO_TEST_CASE( test_add_inline ) { +int main(void) { //[add_inline int sum = 0, factor = 10; void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { sum += factor * num; - } BOOST_LOCAL_FUNCTION_NAME(inline add) // Inlined. + } BOOST_LOCAL_FUNCTION_NAME(inline add) // Inlining. std::vector v(100); std::fill(v.begin(), v.end(), 1); @@ -26,6 +29,9 @@ BOOST_AUTO_TEST_CASE( test_add_inline ) { for(size_t i = 0; i < v.size(); ++i) add(v[i]); // Cannot use for_each. //] - BOOST_CHECK( sum == 1000 ); + BOOST_TEST(sum == 1000); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/add_inline_seq.cpp b/test/add_inline_seq.cpp new file mode 100644 index 0000000..7802621 --- /dev/null +++ b/test/add_inline_seq.cpp @@ -0,0 +1,28 @@ + +// 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/local_function + +#include +#include +#include +#include + +int main(void) { + int sum = 0, factor = 10; + + void BOOST_LOCAL_FUNCTION( (const bind factor) (bind& sum) (int num) ) { + sum += factor * num; + } BOOST_LOCAL_FUNCTION_NAME(inline add) + + std::vector v(100); + std::fill(v.begin(), v.end(), 1); + + for(size_t i = 0; i < v.size(); ++i) add(v[i]); + + BOOST_TEST(sum == 1000); + return boost::report_errors(); +} + diff --git a/test/add_inline_seq_nova.cpp b/test/add_inline_seq_nova.cpp new file mode 100644 index 0000000..e040ad6 --- /dev/null +++ b/test/add_inline_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_inline_seq.cpp" + diff --git a/test/add_params.cpp b/test/add_params_only.cpp similarity index 58% rename from test/add_params.cpp rename to test/add_params_only.cpp index c9bb138..08e48c8 100644 --- a/test/add_params.cpp +++ b/test/add_params_only.cpp @@ -5,18 +5,24 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#include -#define BOOST_TEST_MODULE TestAddParams -#include +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else -BOOST_AUTO_TEST_CASE( test_add_params ) { - //[add_params +#include +#include + +int main(void) { + //[add_params_only int BOOST_LOCAL_FUNCTION(int x, int y) { // Local function. return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) - BOOST_CHECK( add(1, 2) == 3 ); // Local function call. + BOOST_TEST(add(1, 2) == 3); // Local function call. //] + return boost::report_errors(); } -//] + +#endif // VARIADIC_MACROS diff --git a/test/add_params_only_seq.cpp b/test/add_params_only_seq.cpp new file mode 100644 index 0000000..565d5ff --- /dev/null +++ b/test/add_params_only_seq.cpp @@ -0,0 +1,19 @@ + +// 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/local_function + +#include +#include + +int main(void) { + int BOOST_LOCAL_FUNCTION( (int x) (int y) ) { + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + + BOOST_TEST(add(1, 2) == 3); + return boost::report_errors(); +} + diff --git a/test/add_params_only_seq_nova.cpp b/test/add_params_only_seq_nova.cpp new file mode 100644 index 0000000..7123aae --- /dev/null +++ b/test/add_params_only_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_params_only_seq.cpp" + diff --git a/test/add_seq.cpp b/test/add_seq.cpp index eaf93de..d04819b 100644 --- a/test/add_seq.cpp +++ b/test/add_seq.cpp @@ -6,24 +6,23 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestAddSeq -#include +#include #include -BOOST_AUTO_TEST_CASE( test_add_seq ) //[add_seq -{ // Some local scope. - int sum = 0, factor = 10; // Variables in scope to bind. +int main(void) { + int sum = 0, factor = 10; void BOOST_LOCAL_FUNCTION( (const bind factor) (bind& sum) (int num) ) { - sum += factor * num; // Parameters as sequence. + sum += factor * num; } BOOST_LOCAL_FUNCTION_NAME(add) - add(1); // Call the local function. + add(1); int nums[] = {2, 3}; - std::for_each(nums, nums + 2, add); // Pass it to an algorithm. + std::for_each(nums, nums + 2, add); - BOOST_CHECK( sum == 60 ); // Assert final summation value. + BOOST_TEST(sum == 60); + return boost::report_errors(); } //] diff --git a/test/add_seq_nova.cpp b/test/add_seq_nova.cpp new file mode 100644 index 0000000..ce0c279 --- /dev/null +++ b/test/add_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_seq.cpp" + diff --git a/test/add_template.cpp b/test/add_template.cpp index 233c26f..5ce77cf 100644 --- a/test/add_template.cpp +++ b/test/add_template.cpp @@ -5,9 +5,13 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAddTemplate -#include +#include #include //[add_template @@ -15,10 +19,10 @@ template T total(const T& x, const T& y, const T& z) { T sum = T(), factor = 10; - // Using the `..._TPL` macro. + // Must use the `..._TPL` macros within templates. T BOOST_LOCAL_FUNCTION_TPL(const bind factor, bind& sum, T num) { return sum += factor * num; - } BOOST_LOCAL_FUNCTION_NAME(add) + } BOOST_LOCAL_FUNCTION_NAME_TPL(add) add(x); T nums[2]; nums[0] = y; nums[1] = z; @@ -28,7 +32,10 @@ T total(const T& x, const T& y, const T& z) { } //] -BOOST_AUTO_TEST_CASE( test_add_template ) { - BOOST_CHECK( total(1, 2, 3) == 60 ); +int main(void) { + BOOST_TEST(total(1, 2, 3) == 60); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/add_template_seq.cpp b/test/add_template_seq.cpp new file mode 100644 index 0000000..3c0ea71 --- /dev/null +++ b/test/add_template_seq.cpp @@ -0,0 +1,31 @@ + +// 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/local_function + +#include +#include +#include + +template +T total(const T& x, const T& y, const T& z) { + T sum = T(), factor = 10; + + T BOOST_LOCAL_FUNCTION_TPL( (const bind factor) (bind& sum) (T num) ) { + return sum += factor * num; + } BOOST_LOCAL_FUNCTION_NAME_TPL(add) + + add(x); + T nums[2]; nums[0] = y; nums[1] = z; + std::for_each(nums, nums + 2, add); + + return sum; +} + +int main(void) { + BOOST_TEST(total(1, 2, 3) == 60); + return boost::report_errors(); +} + diff --git a/test/add_template_seq_nova.cpp b/test/add_template_seq_nova.cpp new file mode 100644 index 0000000..9c02384 --- /dev/null +++ b/test/add_template_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_template_seq.cpp" + diff --git a/test/add_this.cpp b/test/add_this.cpp index c7f4ba6..11071d2 100644 --- a/test/add_this.cpp +++ b/test/add_this.cpp @@ -5,15 +5,24 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAddThis -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include #include #include +struct adder; +BOOST_TYPEOF_REGISTER_TYPE(adder) // Register before `bind this_` below. + //[add_this struct adder { - adder(): sum_(0) {} + adder() : sum_(0) {} int sum(const std::vector& nums, const int factor = 10) { @@ -24,15 +33,19 @@ struct adder { std::for_each(nums.begin(), nums.end(), add); return sum_; } + private: int sum_; }; //] -BOOST_AUTO_TEST_CASE( test_add_this ) { +int main(void) { std::vector v(3); v[0] = 1; v[1] = 2; v[2] = 3; - BOOST_CHECK( adder().sum(v) == 60 ); + BOOST_TEST(adder().sum(v) == 60); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/add_this_seq.cpp b/test/add_this_seq.cpp new file mode 100644 index 0000000..9957122 --- /dev/null +++ b/test/add_this_seq.cpp @@ -0,0 +1,43 @@ + +// 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/local_function + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include +#include +#include + +struct adder; +BOOST_TYPEOF_REGISTER_TYPE(adder) // Register before `bind this_` below. + +struct adder { + adder() : sum_(0) {} + + int sum(const std::vector& nums, const int factor = 10) { + + void BOOST_LOCAL_FUNCTION( (const bind factor) (bind this_) + (int num) ) { + this_->sum_ += factor * num; + } BOOST_LOCAL_FUNCTION_NAME(add) + + std::for_each(nums.begin(), nums.end(), add); + return sum_; + } + +private: + int sum_; +}; + +int main(void) { + std::vector v(3); + v[0] = 1; v[1] = 2; v[2] = 3; + + BOOST_TEST(adder().sum(v) == 60); + return boost::report_errors(); +} + diff --git a/test/add_this_seq_nova.cpp b/test/add_this_seq_nova.cpp new file mode 100644 index 0000000..e015739 --- /dev/null +++ b/test/add_this_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_this_seq.cpp" + diff --git a/test/add_typed.cpp b/test/add_typed.cpp index 57dfabe..80c26dd 100644 --- a/test/add_typed.cpp +++ b/test/add_typed.cpp @@ -5,18 +5,22 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAddTyped -#include +#include #include #include //[add_typed struct adder { - adder(): sum_(0) {} + adder(void) : sum_(0) {} int sum(const std::vector& nums, const int& factor = 10) { - // Explicitly specify bound variable and result types. + // Explicitly specify bound variable and return types (no type-of). BOOST_LOCAL_FUNCTION(const bind(const int&) factor, bind(adder*) this_, int num, return int) { return this_->sum_ += factor * num; @@ -25,15 +29,19 @@ struct adder { std::for_each(nums.begin(), nums.end(), add); return sum_; } + private: int sum_; }; //] -BOOST_AUTO_TEST_CASE( test_add_typed ) { +int main(void) { std::vector v(3); v[0] = 1; v[1] = 2; v[2] = 3; - BOOST_CHECK( adder().sum(v) == 60 ); + BOOST_TEST(adder().sum(v) == 60); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/add_typed_seq.cpp b/test/add_typed_seq.cpp new file mode 100644 index 0000000..e62ff50 --- /dev/null +++ b/test/add_typed_seq.cpp @@ -0,0 +1,37 @@ + +// 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/local_function + +#include +#include +#include +#include + +struct adder { + adder(void) : sum_(0) {} + + int sum(const std::vector& nums, const int& factor = 10) { + BOOST_LOCAL_FUNCTION( (const bind(const int&) factor) + (bind(adder*) this_) (int num) (return int) ) { + return this_->sum_ += factor * num; + } BOOST_LOCAL_FUNCTION_NAME(add) + + std::for_each(nums.begin(), nums.end(), add); + return sum_; + } + +private: + int sum_; +}; + +int main(void) { + std::vector v(3); + v[0] = 1; v[1] = 2; v[2] = 3; + + BOOST_TEST(adder().sum(v) == 60); + return boost::report_errors(); +} + diff --git a/test/add_typed_seq_nova.cpp b/test/add_typed_seq_nova.cpp new file mode 100644 index 0000000..0cdb356 --- /dev/null +++ b/test/add_typed_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_typed_seq.cpp" + diff --git a/test/add_with_default.cpp b/test/add_with_default.cpp index ceab084..fc3e446 100644 --- a/test/add_with_default.cpp +++ b/test/add_with_default.cpp @@ -5,22 +5,28 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestAddWithDefault -#include +#include //[add_with_default_macro #define WITH_DEFAULT , default //] -BOOST_AUTO_TEST_CASE( test_add_with_default ) { +int main(void) { //[add_with_default int BOOST_LOCAL_FUNCTION(int x, int y WITH_DEFAULT 2) { // Default. return x + y; } BOOST_LOCAL_FUNCTION_NAME(add) - BOOST_CHECK( add(1) == 3 ); + BOOST_TEST(add(1) == 3); //] + return boost::report_errors(); } -//] + +#endif // VARIADIC_MACROS diff --git a/test/add_with_default_seq.cpp b/test/add_with_default_seq.cpp new file mode 100644 index 0000000..1513af0 --- /dev/null +++ b/test/add_with_default_seq.cpp @@ -0,0 +1,21 @@ + +// 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/local_function + +#include +#include + +#define WITH_DEFAULT )(default + +int main(void) { + int BOOST_LOCAL_FUNCTION( (int x) (int y WITH_DEFAULT 2) ) { + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + + BOOST_TEST(add(1) == 3); + return boost::report_errors(); +} + diff --git a/test/add_with_default_seq_nova.cpp b/test/add_with_default_seq_nova.cpp new file mode 100644 index 0000000..d7149cc --- /dev/null +++ b/test/add_with_default_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "add_with_default_seq.cpp" + diff --git a/test/addable.hpp b/test/addable.hpp index d8d51f6..7329d5a 100644 --- a/test/addable.hpp +++ b/test/addable.hpp @@ -15,10 +15,13 @@ struct Addable { // User-defined concept. BOOST_CONCEPT_USAGE(Addable) { return_type(x + y); // Check addition `T operator+(T x, T y)`. } + private: - T x; - T y; - void return_type(T const&); // Used to check addition returns type `T`. + T const& x; + T const& y; + + void return_type(T const&) // Used to check addition returns type `T`. + {} // Do nothing implementation (required for some linkers). }; #endif // #include guard diff --git a/test/all_decl.cpp b/test/all_decl.cpp new file mode 100644 index 0000000..0366aaa --- /dev/null +++ b/test/all_decl.cpp @@ -0,0 +1,177 @@ + +// 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/local_function + +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() + +struct s; +BOOST_TYPEOF_REGISTER_TYPE(s) // Register before binding `this_` below. + +// Compile all local function declaration combinations. +struct s { + void f(double p = 1.23, double q = -1.23) { + { // Only params. + void BOOST_LOCAL_FUNCTION(int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(l) + l(1); + } + { // Only const binds. + int a, b; + + const int& BOOST_LOCAL_FUNCTION(const bind a, + const bind& b, const bind& p, const bind q) { + return b; + } BOOST_LOCAL_FUNCTION_NAME(l) + l(); + + const s& BOOST_LOCAL_FUNCTION(const bind this_) { + return *this_; + } BOOST_LOCAL_FUNCTION_NAME(t) + t(); + + const int BOOST_LOCAL_FUNCTION(const bind a, + const bind& b, const bind& p, const bind q, + const bind this_) { + return a; + } BOOST_LOCAL_FUNCTION_NAME(lt) + lt(); + } + { // Only plain binds. + int c, d; + + int& BOOST_LOCAL_FUNCTION(bind c, bind& d, + bind& p, bind& q) { + return d; + } BOOST_LOCAL_FUNCTION_NAME(l) + l(); + + s& BOOST_LOCAL_FUNCTION(bind this_) { + return *this_; + } BOOST_LOCAL_FUNCTION_NAME(t) + t(); + + int BOOST_LOCAL_FUNCTION(bind c, bind& d, + bind& p, bind& q, bind this_) { + return c; + } BOOST_LOCAL_FUNCTION_NAME(lt) + lt(); + } + + { // Both params and const binds. + int a, b; + + void BOOST_LOCAL_FUNCTION(const bind a, const bind& b, + const bind& p, const bind q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(l) + l(1); + + void BOOST_LOCAL_FUNCTION(const bind this_, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(t) + t(1); + + void BOOST_LOCAL_FUNCTION(const bind a, const bind this_, + const bind& b, const bind& p, const bind q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(lt) + lt(1); + } + { // Both params and plain binds. + int c, d; + + void BOOST_LOCAL_FUNCTION(bind c, bind& d, bind& p, bind q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(l) + l(1); + + void BOOST_LOCAL_FUNCTION(bind this_, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(t) + t(1); + + void BOOST_LOCAL_FUNCTION(bind c, bind& d, + bind& p, bind this_, bind q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(lt) + lt(1); + } + { // Both const and plain binds. + int a, b, c, d; + + void BOOST_LOCAL_FUNCTION(const bind a, const bind& b, + const bind p, bind c, bind& d, bind q) { + } BOOST_LOCAL_FUNCTION_NAME(l) + l(); + + void BOOST_LOCAL_FUNCTION(const bind this_, + bind c, bind& d, bind q) { + } BOOST_LOCAL_FUNCTION_NAME(ct) + ct(); + void BOOST_LOCAL_FUNCTION(const bind this_, + const bind a, const bind& b, const bind p, + bind c, bind& d, bind q) { + } BOOST_LOCAL_FUNCTION_NAME(lct) + lct(); + + void BOOST_LOCAL_FUNCTION(const bind a, const bind& b, + const bind p, bind this_) { + } BOOST_LOCAL_FUNCTION_NAME(pt) + pt(); + void BOOST_LOCAL_FUNCTION(const bind a, const bind& b, + const bind p, bind c, bind this_, bind& d, bind q) { + } BOOST_LOCAL_FUNCTION_NAME(lpt) + lpt(); + } + + { // All params, const binds, and plain binds. + int a, b, c, d; + + void BOOST_LOCAL_FUNCTION( + const bind a, const bind& b, const bind& p, + bind c, bind& d, bind& q, int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(l) + l(1); + + void BOOST_LOCAL_FUNCTION(const bind this_, + bind c, bind& d, bind& q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(ct) + ct(1); + void BOOST_LOCAL_FUNCTION( + const bind a, const bind& b, const bind& p, + bind this_, int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(pt) + pt(1); + + void BOOST_LOCAL_FUNCTION(const bind a, const bind this_, + const bind& b, const bind& p, bind c, bind& d, + bind& q, int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(lct) + lct(1); + void BOOST_LOCAL_FUNCTION(const bind a, const bind& b, + const bind& p, bind c, bind& d, bind this_, bind& q, + int x, int y, default 0) { + } BOOST_LOCAL_FUNCTION_NAME(lpt) + lpt(1); + } + } +}; + +int main(void) { + s().f(); + return 0; +} + +#endif // VARIADIC_MACROS + diff --git a/test/seq.cpp b/test/all_decl_seq.cpp similarity index 96% rename from test/seq.cpp rename to test/all_decl_seq.cpp index cca62a5..95fb75e 100644 --- a/test/seq.cpp +++ b/test/all_decl_seq.cpp @@ -6,8 +6,13 @@ // Home at http://www.boost.org/libs/local_function #include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() -//[seq +struct s; +BOOST_TYPEOF_REGISTER_TYPE(s); // Register before bind `this_` below. + +// Compile all local function declaration combinations. struct s { void f(double p = 1.23, double q = -1.23) { { // Only params. @@ -157,8 +162,7 @@ struct s { } } }; -//] - + int main(void) { s().f(); return 0; diff --git a/test/all_decl_seq_nova.cpp b/test/all_decl_seq_nova.cpp new file mode 100644 index 0000000..8333b28 --- /dev/null +++ b/test/all_decl_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "all_decl_seq.cpp" + diff --git a/test/factorial.cpp b/test/factorial.cpp index 11d837d..07d98f3 100644 --- a/test/factorial.cpp +++ b/test/factorial.cpp @@ -5,12 +5,21 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestFactorial -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include #include #include +struct calculator; +BOOST_TYPEOF_REGISTER_TYPE(calculator) // Register before `bind this_` below. + //[factorial struct calculator { std::vector results; @@ -32,14 +41,17 @@ struct calculator { }; //] -BOOST_AUTO_TEST_CASE( test_factorial ) { +int main(void) { std::vector v(3); v[0] = 1; v[1] = 3; v[2] = 4; calculator calc; calc.factorials(v); - BOOST_CHECK( calc.results[0] == 1 ); - BOOST_CHECK( calc.results[1] == 6 ); - BOOST_CHECK( calc.results[2] == 24 ); + BOOST_TEST(calc.results[0] == 1); + BOOST_TEST(calc.results[1] == 6); + BOOST_TEST(calc.results[2] == 24); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/factorial_seq.cpp b/test/factorial_seq.cpp new file mode 100644 index 0000000..e7c242c --- /dev/null +++ b/test/factorial_seq.cpp @@ -0,0 +1,48 @@ + +// 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/local_function + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include +#include +#include + +struct calculator; +BOOST_TYPEOF_REGISTER_TYPE(calculator) // Register before `bind this_` below. + +struct calculator { + std::vector results; + + void factorials(const std::vector& nums) { + int BOOST_LOCAL_FUNCTION( (bind this_) (int num) + (bool recursion)(default false) ) { + int result = 0; + + if(num <= 0) result = 1; + else result = num * factorial(num - 1, true); + + if(!recursion) this_->results.push_back(result); + return result; + } BOOST_LOCAL_FUNCTION_NAME(recursive factorial) + + std::for_each(nums.begin(), nums.end(), factorial); + } +}; + +int main(void) { + std::vector v(3); + v[0] = 1; v[1] = 3; v[2] = 4; + + calculator calc; + calc.factorials(v); + BOOST_TEST(calc.results[0] == 1); + BOOST_TEST(calc.results[1] == 6); + BOOST_TEST(calc.results[2] == 24); + return boost::report_errors(); +} + diff --git a/test/factorial_seq_nova.cpp b/test/factorial_seq_nova.cpp new file mode 100644 index 0000000..b937612 --- /dev/null +++ b/test/factorial_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "factorial_seq.cpp" + diff --git a/test/goto.cpp b/test/goto.cpp index 6356584..a030f58 100644 --- a/test/goto.cpp +++ b/test/goto.cpp @@ -5,14 +5,17 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestGoto -#include //[goto int error(int x, int y) { - int BOOST_LOCAL_FUNCTION(int x) { - if(x > 0) goto success; // OK: Can jump within local function. + int BOOST_LOCAL_FUNCTION(int z) { + if(z > 0) goto success; // OK: Can jump within local function. return -1; success: return 0; @@ -22,7 +25,10 @@ int error(int x, int y) { } //] -BOOST_AUTO_TEST_CASE( test_goto ) { +int main(void) { error(1, 2); + return 0; } +#endif // VARIADIC_MACROS + diff --git a/test/goto_err.cpp b/test/goto_error.cpp similarity index 67% rename from test/goto_err.cpp rename to test/goto_error.cpp index f62f9f6..55ad95a 100644 --- a/test/goto_err.cpp +++ b/test/goto_error.cpp @@ -5,27 +5,32 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestGotoErr -#include -//[goto_err +//[goto_error int error(int x, int y) { - int BOOST_LOCAL_FUNCTION(int x) { - if(x <= 0) goto failure; // Error: Cannot jump to enclosing scope. + int BOOST_LOCAL_FUNCTION(int z) { + if(z <= 0) goto failure; // Error: Cannot jump to enclosing scope. else goto success; // OK: Can jump within local function. - success: return 0; } BOOST_LOCAL_FUNCTION_NAME(validate) return validate(x + y); -faliure: +failure: return -1; } //] -BOOST_AUTO_TEST_CASE( test_goto_err ) { +int main(void) { error(1, 2); + return 0; } +#endif + diff --git a/test/goto_error_seq.cpp b/test/goto_error_seq.cpp new file mode 100644 index 0000000..178ac43 --- /dev/null +++ b/test/goto_error_seq.cpp @@ -0,0 +1,27 @@ + +// 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/local_function + +#include + +int error(int x, int y) { + int BOOST_LOCAL_FUNCTION( (int z) ) { + if(z <= 0) goto failure; + else goto success; + success: + return 0; + } BOOST_LOCAL_FUNCTION_NAME(validate) + + return validate(x + y); +failure: + return -1; +} + +int main(void) { + error(1, 2); + return 0; +} + diff --git a/test/goto_error_seq_nova.cpp b/test/goto_error_seq_nova.cpp new file mode 100644 index 0000000..6433add --- /dev/null +++ b/test/goto_error_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "goto_error_seq.cpp" + diff --git a/test/goto_seq.cpp b/test/goto_seq.cpp new file mode 100644 index 0000000..5acb5b4 --- /dev/null +++ b/test/goto_seq.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/local_function + +#include + +int error(int x, int y) { + int BOOST_LOCAL_FUNCTION( (int z) ) { + if(z > 0) goto success; + return -1; + success: + return 0; + } BOOST_LOCAL_FUNCTION_NAME(validate) + + return validate(x + y); +} + +int main(void) { + error(1, 2); + return 0; +} + diff --git a/test/goto_seq_nova.cpp b/test/goto_seq_nova.cpp new file mode 100644 index 0000000..edec9f2 --- /dev/null +++ b/test/goto_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "goto_seq.cpp" + diff --git a/test/macro_commas.cpp b/test/macro_commas.cpp index 8ce6e95..a1e1d77 100644 --- a/test/macro_commas.cpp +++ b/test/macro_commas.cpp @@ -5,11 +5,15 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#include -#define BOOST_TEST_MODULE TestMacroCommas -#include +#include // Type-of registrations +#include // needed for `NAME` macro. #include #include @@ -17,12 +21,15 @@ std::string cat(const std::string& x, const std::string& y) { return x + y; } template struct key_sizeof { - BOOST_STATIC_CONSTANT(int, value = sizeof(K)); + static int const value; }; +template +int const key_sizeof::value = sizeof(K); + typedef int sign_t; -BOOST_AUTO_TEST_CASE( test_macro_commas ) { +int main(void) { //[macro_commas void BOOST_LOCAL_FUNCTION( BOOST_IDENTITY_TYPE((const std::map&)) m, @@ -38,5 +45,8 @@ BOOST_AUTO_TEST_CASE( test_macro_commas ) { std::map m; ::sign_t sign = -1; f(m, sign); + return 0; } +#endif // VARIADIC_MACROS + diff --git a/test/macro_commas_seq.cpp b/test/macro_commas_seq.cpp new file mode 100644 index 0000000..f2e0f49 --- /dev/null +++ b/test/macro_commas_seq.cpp @@ -0,0 +1,44 @@ + +// 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/local_function + +#include +#include +#include // Type-of registrations +#include // needed for `NAME` macro. +#include +#include +#include + +std::string cat(const std::string& x, const std::string& y) { return x + y; } + +template +struct key_sizeof { + static int const value; +}; + +template +int const key_sizeof::value = sizeof(K); + +typedef int sign_t; + +int main(void) { + void BOOST_LOCAL_FUNCTION( + (BOOST_IDENTITY_TYPE((const std::map&)) m) + (BOOST_IDENTITY_TYPE((::sign_t)) sign) + (const size_t& factor) + (default (key_sizeof::value)) + (const std::string& separator)(default cat(":", " ")) + ) { + // Do something... + } BOOST_LOCAL_FUNCTION_NAME(f) + + std::map m; + ::sign_t sign = -1; + f(m, sign); + return 0; +} + diff --git a/test/macro_commas_seq_nova.cpp b/test/macro_commas_seq_nova.cpp new file mode 100644 index 0000000..4252379 --- /dev/null +++ b/test/macro_commas_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "macro_commas_seq.cpp" + diff --git a/test/nesting.cpp b/test/nesting.cpp index 5b22e8d..bb97d64 100644 --- a/test/nesting.cpp +++ b/test/nesting.cpp @@ -5,11 +5,15 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#include -#define BOOST_TEST_MODULE TestNesting -#include +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else -BOOST_AUTO_TEST_CASE( test_nesting ) { +#include +#include + +int main(void) { //[nesting int x = 0; @@ -24,6 +28,10 @@ BOOST_AUTO_TEST_CASE( test_nesting ) { f(); //] - BOOST_CHECK( x == 0 ); + + BOOST_TEST(x == 0); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/nesting_seq.cpp b/test/nesting_seq.cpp new file mode 100644 index 0000000..6e18558 --- /dev/null +++ b/test/nesting_seq.cpp @@ -0,0 +1,28 @@ + +// 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/local_function + +#include +#include + +int main(void) { + int x = 0; + + void BOOST_LOCAL_FUNCTION( (bind& x) ) { + void BOOST_LOCAL_FUNCTION( (bind& x) ) { + x++; + } BOOST_LOCAL_FUNCTION_NAME(g) + + x--; + g(); + } BOOST_LOCAL_FUNCTION_NAME(f) + + f(); + + BOOST_TEST(x == 0); + return boost::report_errors(); +} + diff --git a/test/nesting_seq_nova.cpp b/test/nesting_seq_nova.cpp new file mode 100644 index 0000000..caeb072 --- /dev/null +++ b/test/nesting_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "nesting_seq.cpp" + diff --git a/test/nova.hpp b/test/nova.hpp new file mode 100644 index 0000000..58984ac --- /dev/null +++ b/test/nova.hpp @@ -0,0 +1,21 @@ + +// Copyright (C) 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/scope_exit + +#ifndef NOVA_HPP_ +#define NOVA_HPP_ + +#include + +// WARNING: This file must be included first in each compilation unit. + +// Force no variadic macros but avoiding macro redefinition warning/error. +#ifndef BOOST_NO_VARIADIC_MACROS +# define BOOST_NO_VARIADIC_MACROS +#endif + +#endif // #include guard + diff --git a/test/operator.cpp b/test/operator.cpp index 4899070..e5cdd96 100644 --- a/test/operator.cpp +++ b/test/operator.cpp @@ -5,24 +5,34 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestOperator -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include //[operator struct point { int x; int y; }; +BOOST_TYPEOF_REGISTER_TYPE(point) // Register for `NAME` below. -BOOST_AUTO_TEST_CASE( test_operator ) { +int main(void) { bool BOOST_LOCAL_FUNCTION(const point& p, const point& q) { return p.x == q.x && p.y == q.y; - } BOOST_LOCAL_FUNCTION_NAME(equal) // OK: not using `operator...`. + } BOOST_LOCAL_FUNCTION_NAME(equal) // OK: not using `operator==`. point a; a.x = 1; a.y = 2; point b = a; - BOOST_CHECK( equal(a, b) ); + BOOST_TEST(equal(a, b)); + return boost::report_errors(); } //] +#endif // VARIADIC_MACROS + diff --git a/test/operator_err.cpp b/test/operator_error.cpp similarity index 56% rename from test/operator_err.cpp rename to test/operator_error.cpp index dac986a..295fc1d 100644 --- a/test/operator_err.cpp +++ b/test/operator_error.cpp @@ -5,24 +5,34 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function -#include -#define BOOST_TEST_MODULE TestOperatorErr -#include +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include -//[operator_err struct point { int x; int y; }; +BOOST_TYPEOF_REGISTER_TYPE(point) // Register for `NAME` below. -BOOST_AUTO_TEST_CASE( test_operator_err ) { +int main(void) { + //[operator_error bool BOOST_LOCAL_FUNCTION(const point& p, const point& q) { return p.x == q.x && p.y == q.y; } BOOST_LOCAL_FUNCTION_NAME(operator==) // Error: Cannot use `operator...`. + //] point a; a.x = 1; a.y = 2; point b = a; - BOOST_CHECK( a == b ); + BOOST_TEST(a == b); + return boost::report_errors(); } -//] + +#endif // VARIADIC_MACROS diff --git a/test/operator_error_seq.cpp b/test/operator_error_seq.cpp new file mode 100644 index 0000000..08c21f2 --- /dev/null +++ b/test/operator_error_seq.cpp @@ -0,0 +1,29 @@ + +// 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/local_function + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +struct point { + int x; + int y; +}; +BOOST_TYPEOF_REGISTER_TYPE(point) // Register for `NAME` below. + +int main(void) { + bool BOOST_LOCAL_FUNCTION( (const point& p) (const point& q) ) { + return p.x == q.x && p.y == q.y; + } BOOST_LOCAL_FUNCTION_NAME(operator==) + + point a; a.x = 1; a.y = 2; + point b = a; + BOOST_TEST(a == b); + return boost::report_errors(); +} + diff --git a/test/operator_error_seq_nova.cpp b/test/operator_error_seq_nova.cpp new file mode 100644 index 0000000..6df7178 --- /dev/null +++ b/test/operator_error_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "operator_error_seq.cpp" + diff --git a/test/operator_seq.cpp b/test/operator_seq.cpp new file mode 100644 index 0000000..d4f70f4 --- /dev/null +++ b/test/operator_seq.cpp @@ -0,0 +1,29 @@ + +// 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/local_function + +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +struct point { + int x; + int y; +}; +BOOST_TYPEOF_REGISTER_TYPE(point) // Register for `NAME` below. + +int main(void) { + bool BOOST_LOCAL_FUNCTION( (const point& p) (const point& q) ) { + return p.x == q.x && p.y == q.y; + } BOOST_LOCAL_FUNCTION_NAME(equal) + + point a; a.x = 1; a.y = 2; + point b = a; + BOOST_TEST(equal(a, b)); + return boost::report_errors(); +} + diff --git a/test/operator_seq_nova.cpp b/test/operator_seq_nova.cpp new file mode 100644 index 0000000..e6f6246 --- /dev/null +++ b/test/operator_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "operator_seq.cpp" + diff --git a/test/overload.cpp b/test/overload.cpp index 43bdd4d..b2321bf 100644 --- a/test/overload.cpp +++ b/test/overload.cpp @@ -5,17 +5,23 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include // For overloading. -#define BOOST_TEST_MODULE TestOverload -#include +#include +#include #include -#include -//[overload +//[overload_decl int add_i(int x, int y) { return x + y; } +//] -BOOST_AUTO_TEST_CASE( test_overload ) { +int main(void) { + //[overload std::string s = "abc"; std::string BOOST_LOCAL_FUNCTION( const bind& s, const std::string& x) { @@ -34,10 +40,13 @@ BOOST_AUTO_TEST_CASE( test_overload ) { , int (int, int) > add(add_s, add_d, add_d, add_i); // Overloaded function object. - BOOST_CHECK( add("xyz") == "abcxyz" ); // Call `add_s`. - BOOST_CHECK( fabs(add(3.21) - 4.44) < 0.001 ); // Call `add_d` (no default). - BOOST_CHECK( fabs(add(3.21, 40.0) - 44.44) < 0.001); // Call `add_d`. - BOOST_CHECK( add(1, 2) == 3 ); // Call `add_i`. + BOOST_TEST(add("xyz") == "abcxyz"); // Call `add_s`. + BOOST_TEST((4.44 - add(3.21)) <= 0.001); // Call `add_d` (no default). + BOOST_TEST((44.44 - add(3.21, 40.0)) <= 0.001); // Call `add_d`. + BOOST_TEST(add(1, 2) == 3); // Call `add_i`. + //] + return boost::report_errors(); } -//] + +#endif // VARIADIC_MACROS diff --git a/test/overload_seq.cpp b/test/overload_seq.cpp new file mode 100644 index 0000000..5bb0dab --- /dev/null +++ b/test/overload_seq.cpp @@ -0,0 +1,42 @@ + +// 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/local_function + +#include +#include +#include +#include +#include + +int add_i(int x, int y) { return x + y; } + +int main(void) { + std::string s = "abc"; + std::string BOOST_LOCAL_FUNCTION( + (const bind& s) (const std::string& x) ) { + return s + x; + } BOOST_LOCAL_FUNCTION_NAME(add_s) + + double d = 1.23; + double BOOST_LOCAL_FUNCTION( (const bind d) (double x) + (double y)(default 0) ) { + return d + x + y; + } BOOST_LOCAL_FUNCTION_NAME(add_d) + + boost::overloaded_function< + std::string (const std::string&) + , double (double) + , double (double, double) + , int (int, int) + > add(add_s, add_d, add_d, add_i); + + BOOST_TEST(add("xyz") == "abcxyz"); + BOOST_TEST((4.44 - add(3.21)) <= 0.001); // Equal within precision. + BOOST_TEST((44.44 - add(3.21, 40.0)) <= 0.001); // Equal within precision. + BOOST_TEST(add(1, 2) == 3); + return boost::report_errors(); +} + diff --git a/test/overload_seq_nova.cpp b/test/overload_seq_nova.cpp new file mode 100644 index 0000000..e72b63b --- /dev/null +++ b/test/overload_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "overload_seq.cpp" + diff --git a/test/return_assign.cpp b/test/return_assign.cpp index 9d01067..4bde550 100644 --- a/test/return_assign.cpp +++ b/test/return_assign.cpp @@ -5,15 +5,19 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#define BOOST_TEST_MODULE TestReturnAssign -#include +#include #include //[return_assign -void call1(boost::function f) { BOOST_CHECK( f(1) == 5 ); } -void call0(boost::function f) { BOOST_CHECK( f() == 5 ); } +void call1(boost::function f) { BOOST_TEST(f(1) == 5); } +void call0(boost::function f) { BOOST_TEST(f() == 5); } boost::function linear(const int& slope) { int BOOST_LOCAL_FUNCTION(const bind& slope, @@ -22,7 +26,7 @@ boost::function linear(const int& slope) { } BOOST_LOCAL_FUNCTION_NAME(lin) boost::function f = lin; // Assign to local variable. - BOOST_CHECK( f(1, 2) == 5 ); + BOOST_TEST(f(1, 2) == 5); call1(lin); // Pass to other functions. call0(lin); @@ -32,11 +36,14 @@ boost::function linear(const int& slope) { void call(void) { boost::function f = linear(2); - BOOST_CHECK( f(1, 2) == 5 ); + BOOST_TEST(f(1, 2) == 5); } //] -BOOST_AUTO_TEST_CASE( test_return_assign ) { +int main(void) { call(); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/return_assign_seq.cpp b/test/return_assign_seq.cpp new file mode 100644 index 0000000..95c6bf1 --- /dev/null +++ b/test/return_assign_seq.cpp @@ -0,0 +1,40 @@ + +// 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/local_function + +#include +#include +#include +#include + +void call1(boost::function f) { BOOST_TEST(f(1) == 5); } +void call0(boost::function f) { BOOST_TEST(f() == 5); } + +boost::function linear(const int& slope) { + int BOOST_LOCAL_FUNCTION( (const bind& slope) + (int x)(default 1) (int y)(default 2) ) { + return x + slope * y; + } BOOST_LOCAL_FUNCTION_NAME(lin) + + boost::function f = lin; + BOOST_TEST(f(1, 2) == 5); + + call1(lin); + call0(lin); + + return lin; +} + +void call(void) { + boost::function f = linear(2); + BOOST_TEST(f(1, 2) == 5); +} + +int main(void) { + call(); + return boost::report_errors(); +} + diff --git a/test/return_assign_seq_nova.cpp b/test/return_assign_seq_nova.cpp new file mode 100644 index 0000000..12de8da --- /dev/null +++ b/test/return_assign_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "return_assign_seq.cpp" + diff --git a/test/return_derivative.cpp b/test/return_derivative.cpp index 6f7eb26..60dea24 100644 --- a/test/return_derivative.cpp +++ b/test/return_derivative.cpp @@ -5,25 +5,37 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#define BOOST_TEST_MODULE TestReturnDerivative -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, 1) boost::function derivative(boost::function& f, int dx) { int BOOST_LOCAL_FUNCTION(bind& f, const bind dx, int x) { return (f(x + dx) - f(x)) / dx; } BOOST_LOCAL_FUNCTION_NAME(deriv) + return deriv; } -BOOST_AUTO_TEST_CASE( test_return_derivative ) { +int main(void) { int BOOST_LOCAL_FUNCTION(int x) { return x + 4; } BOOST_LOCAL_FUNCTION_NAME(add2) + boost::function a2 = add2; // Reference valid where closure used. - boost::function d2 = derivative(a2, 2); - BOOST_CHECK( d2(6) == 1 ); + BOOST_TEST(d2(6) == 1); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/return_derivative_seq.cpp b/test/return_derivative_seq.cpp new file mode 100644 index 0000000..72c2074 --- /dev/null +++ b/test/return_derivative_seq.cpp @@ -0,0 +1,34 @@ + +// 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/local_function + +#include +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, 1) + +boost::function derivative(boost::function& f, int dx) { + int BOOST_LOCAL_FUNCTION( (bind& f) (const bind dx) (int x) ) { + return (f(x + dx) - f(x)) / dx; + } BOOST_LOCAL_FUNCTION_NAME(deriv) + + return deriv; +} + +int main(void) { + int BOOST_LOCAL_FUNCTION( (int x) ) { + return x + 4; + } BOOST_LOCAL_FUNCTION_NAME(add2) + + boost::function a2 = add2; + boost::function d2 = derivative(a2, 2); + BOOST_TEST(d2(6) == 1); + return boost::report_errors(); +} + diff --git a/test/return_derivative_seq_nova.cpp b/test/return_derivative_seq_nova.cpp new file mode 100644 index 0000000..49bccdd --- /dev/null +++ b/test/return_derivative_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "return_derivative_seq.cpp" + diff --git a/test/return_inc.cpp b/test/return_inc.cpp index 6216c67..4be2d01 100644 --- a/test/return_inc.cpp +++ b/test/return_inc.cpp @@ -5,10 +5,14 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#define BOOST_TEST_MODULE TestReturnInc -#include +#include boost::function inc(int& value) { int BOOST_LOCAL_FUNCTION(bind& value) { @@ -17,15 +21,18 @@ boost::function inc(int& value) { return i; } -BOOST_AUTO_TEST_CASE( test_return_inc ) { +int main(void) { int value1 = 0; // Reference valid in scope where closure is used. boost::function inc1 = inc(value1); int value2 = 0; boost::function inc2 = inc(value2); - BOOST_CHECK( inc1() == 1 ); - BOOST_CHECK( inc1() == 2 ); - BOOST_CHECK( inc2() == 1 ); - BOOST_CHECK( inc1() == 3 ); + BOOST_TEST(inc1() == 1); + BOOST_TEST(inc1() == 2); + BOOST_TEST(inc2() == 1); + BOOST_TEST(inc1() == 3); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/return_inc_seq.cpp b/test/return_inc_seq.cpp new file mode 100644 index 0000000..6116ea9 --- /dev/null +++ b/test/return_inc_seq.cpp @@ -0,0 +1,31 @@ + +// 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/local_function + +#include +#include +#include + +boost::function inc(int& value) { + int BOOST_LOCAL_FUNCTION( (bind& value) ) { + return ++value; + } BOOST_LOCAL_FUNCTION_NAME(i) + return i; +} + +int main(void) { + int value1 = 0; + boost::function inc1 = inc(value1); + int value2 = 0; + boost::function inc2 = inc(value2); + + BOOST_TEST(inc1() == 1); + BOOST_TEST(inc1() == 2); + BOOST_TEST(inc2() == 1); + BOOST_TEST(inc1() == 3); + return boost::report_errors(); +} + diff --git a/test/return_inc_seq_nova.cpp b/test/return_inc_seq_nova.cpp new file mode 100644 index 0000000..c55ade6 --- /dev/null +++ b/test/return_inc_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "return_inc_seq.cpp" + diff --git a/test/return_setget.cpp b/test/return_setget.cpp index 47ac199..37cc84a 100644 --- a/test/return_setget.cpp +++ b/test/return_setget.cpp @@ -5,10 +5,15 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#define BOOST_TEST_MODULE TestReturnSetGet -#include +#include +#include #include boost::function set; @@ -16,12 +21,12 @@ boost::function get; void action(void) { // State `message` hidden behind access functions from here. - BOOST_CHECK( get() == "abc" ); + BOOST_TEST(get() == "abc"); set("xyz"); - BOOST_CHECK( get() == "xyz" ); + BOOST_TEST(get() == "xyz"); } -BOOST_AUTO_TEST_CASE( test_return_setget ) { +int main(void) { std::string message = "abc"; // Reference valid where closure used. void BOOST_LOCAL_FUNCTION(bind& message, const std::string& text) { @@ -35,5 +40,8 @@ BOOST_AUTO_TEST_CASE( test_return_setget ) { get = g; action(); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/return_setget_seq.cpp b/test/return_setget_seq.cpp new file mode 100644 index 0000000..33b1c35 --- /dev/null +++ b/test/return_setget_seq.cpp @@ -0,0 +1,39 @@ + +// 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/local_function + +#include +#include +#include +#include +#include + +boost::function set; +boost::function get; + +void action(void) { + BOOST_TEST(get() == "abc"); + set("xyz"); + BOOST_TEST(get() == "xyz"); +} + +int main(void) { + std::string message = "abc"; + + void BOOST_LOCAL_FUNCTION( (bind& message) (const std::string& text) ) { + message = text; + } BOOST_LOCAL_FUNCTION_NAME(s) + set = s; + + const std::string& BOOST_LOCAL_FUNCTION( (const bind& message) ) { + return message; + } BOOST_LOCAL_FUNCTION_NAME(g) + get = g; + + action(); + return boost::report_errors(); +} + diff --git a/test/return_setget_seq_nova.cpp b/test/return_setget_seq_nova.cpp new file mode 100644 index 0000000..87e2bde --- /dev/null +++ b/test/return_setget_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "return_setget_seq.cpp" + diff --git a/test/return_this.cpp b/test/return_this.cpp index 99fb220..9bbc8bc 100644 --- a/test/return_this.cpp +++ b/test/return_this.cpp @@ -5,10 +5,19 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include #include -#define BOOST_TEST_MODULE TestReturnThis -#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +struct number; +BOOST_TYPEOF_REGISTER_TYPE(number) // Register before `bind this_` below. struct number { number(int value) : value_(value) {} @@ -24,15 +33,18 @@ private: int value_; }; -BOOST_AUTO_TEST_CASE( test_return_this ) { +int main(void) { number n1 = 0; // Object valid in scope where closure is used. boost::function inc1 = n1.inc(); number n2 = 0; boost::function inc2 = n2.inc(); - BOOST_CHECK( inc1() == 1 ); - BOOST_CHECK( inc1() == 2 ); - BOOST_CHECK( inc2() == 1 ); - BOOST_CHECK( inc1() == 3 ); + BOOST_TEST(inc1() == 1); + BOOST_TEST(inc1() == 2); + BOOST_TEST(inc2() == 1); + BOOST_TEST(inc1() == 3); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/return_this_seq.cpp b/test/return_this_seq.cpp new file mode 100644 index 0000000..551d3e1 --- /dev/null +++ b/test/return_this_seq.cpp @@ -0,0 +1,43 @@ + +// 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/local_function + +#include +#include +#include +#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() +#include + +struct number; +BOOST_TYPEOF_REGISTER_TYPE(number) // Register before `bind this_` below. + +struct number { + number(int value) : value_(value) {} + + boost::function inc(void) { + int BOOST_LOCAL_FUNCTION( (bind this_) ) { + return ++this_->value_; + } BOOST_LOCAL_FUNCTION_NAME(i) + return i; + } + +private: + int value_; +}; + +int main(void) { + number n1 = 0; // Object valid in scope where closure is used. + boost::function inc1 = n1.inc(); + number n2 = 0; + boost::function inc2 = n2.inc(); + + BOOST_TEST(inc1() == 1); + BOOST_TEST(inc1() == 2); + BOOST_TEST(inc2() == 1); + BOOST_TEST(inc1() == 3); + return boost::report_errors(); +} + diff --git a/test/return_this_seq_nova.cpp b/test/return_this_seq_nova.cpp new file mode 100644 index 0000000..1f0cfc2 --- /dev/null +++ b/test/return_this_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "return_this_seq.cpp" + diff --git a/test/same_line.cpp b/test/same_line.cpp new file mode 100644 index 0000000..18b0cc7 --- /dev/null +++ b/test/same_line.cpp @@ -0,0 +1,57 @@ + +// 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/local_function + +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + +#include +#include +#include +#include + +//[same_line +#define LOCAL_INC_DEC(offset) \ + int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(inc, __LINE__), /* unique ID */ \ + const bind offset, const int x) { \ + return x + offset; \ + } BOOST_LOCAL_FUNCTION_NAME(inc) \ + \ + int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(dec, __LINE__), \ + const bind offset, const int x) { \ + return x - offset; \ + } BOOST_LOCAL_FUNCTION_NAME(dec) + +#define LOCAL_INC_DEC_TPL(offset) \ + T BOOST_LOCAL_FUNCTION_ID_TPL(BOOST_PP_CAT(inc, __LINE__), \ + const bind offset, const T x) { \ + return x + offset; \ + } BOOST_LOCAL_FUNCTION_NAME_TPL(inc) \ + \ + T BOOST_LOCAL_FUNCTION_ID_TPL(BOOST_PP_CAT(dec, __LINE__), \ + const bind offset, const T x) { \ + return x - offset; \ + } BOOST_LOCAL_FUNCTION_NAME_TPL(dec) + +template +void f(T& delta) { + LOCAL_INC_DEC_TPL(delta) // Multiple local functions on same line. + BOOST_TEST(dec(inc(123)) == 123); +} + +int main(void) { + int delta = 10; + LOCAL_INC_DEC(delta) // Multiple local functions on same line. + BOOST_TEST(dec(inc(123)) == 123); + f(delta); + return boost::report_errors(); +} +//] + +#endif // VARIADIC_MACROS + diff --git a/test/same_line_seq.cpp b/test/same_line_seq.cpp new file mode 100644 index 0000000..2113f47 --- /dev/null +++ b/test/same_line_seq.cpp @@ -0,0 +1,48 @@ + +// 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/local_function + +#include +#include +#include +#include + +#define LOCAL_INC_DEC(offset) \ + int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(inc, __LINE__), /* unique ID */ \ + (const bind offset) (const int x) ) { \ + return x + offset; \ + } BOOST_LOCAL_FUNCTION_NAME(inc) \ + \ + int BOOST_LOCAL_FUNCTION_ID(BOOST_PP_CAT(dec, __LINE__), \ + (const bind offset) (const int x) ) { \ + return x - offset; \ + } BOOST_LOCAL_FUNCTION_NAME(dec) + +#define LOCAL_INC_DEC_TPL(offset) \ + T BOOST_LOCAL_FUNCTION_ID_TPL(BOOST_PP_CAT(inc, __LINE__), \ + (const bind offset) (const T x) ) { \ + return x + offset; \ + } BOOST_LOCAL_FUNCTION_NAME_TPL(inc) \ + \ + T BOOST_LOCAL_FUNCTION_ID_TPL(BOOST_PP_CAT(dec, __LINE__), \ + (const bind offset) (const T x) ) { \ + return x - offset; \ + } BOOST_LOCAL_FUNCTION_NAME_TPL(dec) + +template +void f(T& delta) { + LOCAL_INC_DEC_TPL(delta) // Multiple local functions on same line. + BOOST_TEST(dec(inc(123)) == 123); +} + +int main(void) { + int delta = 10; + LOCAL_INC_DEC(delta) // Declare local functions on same line using `_ID`. + BOOST_TEST(dec(inc(123)) == 123); + f(delta); + return boost::report_errors(); +} + diff --git a/test/same_line_seq_nova.cpp b/test/same_line_seq_nova.cpp new file mode 100644 index 0000000..fb5cc17 --- /dev/null +++ b/test/same_line_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "same_line_seq.cpp" + diff --git a/test/ten_void.cpp b/test/ten_void.cpp index 8235ee8..99bf1bf 100644 --- a/test/ten_void.cpp +++ b/test/ten_void.cpp @@ -6,17 +6,16 @@ // Home at http://www.boost.org/libs/local_function #include -#define BOOST_TEST_MODULE TestTenVoid -#include -#include +#include -BOOST_AUTO_TEST_CASE( test_ten_void ) { +int main(void) { //[ten_void int BOOST_LOCAL_FUNCTION(void) { // No parameter. return 10; } BOOST_LOCAL_FUNCTION_NAME(ten) - BOOST_CHECK( ten() == 10 ); + BOOST_TEST(ten() == 10); //] + return boost::report_errors(); } diff --git a/test/ten_void_nova.cpp b/test/ten_void_nova.cpp new file mode 100644 index 0000000..64b01c5 --- /dev/null +++ b/test/ten_void_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "ten_void.cpp" + diff --git a/test/transform.cpp b/test/transform.cpp index bf473b5..f72cf73 100644 --- a/test/transform.cpp +++ b/test/transform.cpp @@ -5,20 +5,24 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include -#define BOOST_TEST_MODULE TestTranform -#include +#include #include #include -BOOST_AUTO_TEST_CASE( test_transform ) { +int main(void) { //[transform int offset = 5; std::vector v; std::vector w; for(int i = 1; i <= 2; ++i) v.push_back(i * 10); - BOOST_CHECK( v[0] == 10 ); BOOST_CHECK( v[1] == 20 ); + BOOST_TEST(v[0] == 10); BOOST_TEST(v[1] == 20); w.resize(v.size()); int BOOST_LOCAL_FUNCTION(const bind& offset, int i) { @@ -26,7 +30,7 @@ BOOST_AUTO_TEST_CASE( test_transform ) { } BOOST_LOCAL_FUNCTION_NAME(inc) std::transform(v.begin(), v.end(), w.begin(), inc); - BOOST_CHECK( w[0] == 16 ); BOOST_CHECK( w[1] == 26 ); + BOOST_TEST(w[0] == 16); BOOST_TEST(w[1] == 26); int BOOST_LOCAL_FUNCTION(bind& inc, int i, int j) { return inc(i + j); // Call the other bound local function. @@ -34,7 +38,10 @@ BOOST_AUTO_TEST_CASE( test_transform ) { offset = 0; std::transform(v.begin(), v.end(), w.begin(), v.begin(), inc_sum); - BOOST_CHECK( v[0] == 27 ); BOOST_CHECK( v[1] == 47 ); + BOOST_TEST(v[0] == 27); BOOST_TEST(v[1] == 47); //] + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/transform_seq.cpp b/test/transform_seq.cpp new file mode 100644 index 0000000..b29514c --- /dev/null +++ b/test/transform_seq.cpp @@ -0,0 +1,39 @@ + +// 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/local_function + +#include +#include +#include +#include + +int main(void) { + int offset = 5; + std::vector v; + std::vector w; + + for(int i = 1; i <= 2; ++i) v.push_back(i * 10); + BOOST_TEST(v[0] == 10); BOOST_TEST(v[1] == 20); + w.resize(v.size()); + + int BOOST_LOCAL_FUNCTION( (const bind& offset) (int i) ) { + return ++i + offset; + } BOOST_LOCAL_FUNCTION_NAME(inc) + + std::transform(v.begin(), v.end(), w.begin(), inc); + BOOST_TEST(w[0] == 16); BOOST_TEST(w[1] == 26); + + int BOOST_LOCAL_FUNCTION( (bind& inc) (int i) (int j) ) { + return inc(i + j); + } BOOST_LOCAL_FUNCTION_NAME(inc_sum) + + offset = 0; + std::transform(v.begin(), v.end(), w.begin(), v.begin(), inc_sum); + BOOST_TEST(v[0] == 27); BOOST_TEST(v[1] == 47); + + return boost::report_errors(); +} + diff --git a/test/transform_seq_nova.cpp b/test/transform_seq_nova.cpp new file mode 100644 index 0000000..9f06e4f --- /dev/null +++ b/test/transform_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "transform_seq.cpp" + diff --git a/test/typeof.cpp b/test/typeof.cpp index c92b4d6..0b50120 100644 --- a/test/typeof.cpp +++ b/test/typeof.cpp @@ -5,23 +5,27 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include "addable.hpp" #include #include #include -#define BOOST_TEST_MODULE TestTypeof -#include +#include #include -BOOST_AUTO_TEST_CASE( test_typeof ) { +int main(void) { //[typeof int sum = 0, factor = 10; void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { - // Typeof for concept checking. + // Type-of for concept checking. BOOST_CONCEPT_ASSERT((Addable::type>)); - // Typeof for declarations. + // Type-of for declarations. boost::remove_reference::type mult = factor * num; sum += mult; @@ -29,6 +33,9 @@ BOOST_AUTO_TEST_CASE( test_typeof ) { add(6); //] - BOOST_CHECK( sum == 60 ); + BOOST_TEST(sum == 60); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/typeof_seq.cpp b/test/typeof_seq.cpp new file mode 100644 index 0000000..01dd463 --- /dev/null +++ b/test/typeof_seq.cpp @@ -0,0 +1,30 @@ + +// 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/local_function + +#include "addable.hpp" +#include +#include +#include +#include +#include + +int main(void) { + int sum = 0, factor = 10; + + void BOOST_LOCAL_FUNCTION( (const bind factor) (bind& sum) (int num) ) { + BOOST_CONCEPT_ASSERT((Addable::type>)); + boost::remove_reference::type mult = factor * num; + sum += mult; + } BOOST_LOCAL_FUNCTION_NAME(add) + + add(6); + BOOST_TEST(sum == 60); + return boost::report_errors(); +} + diff --git a/test/typeof_seq_nova.cpp b/test/typeof_seq_nova.cpp new file mode 100644 index 0000000..bf8b982 --- /dev/null +++ b/test/typeof_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "typeof_seq.cpp" + diff --git a/test/typeof_template.cpp b/test/typeof_template.cpp index 70cea1e..e514c98 100644 --- a/test/typeof_template.cpp +++ b/test/typeof_template.cpp @@ -5,12 +5,16 @@ // http://www.boost.org/LICENSE_1_0.txt) // Home at http://www.boost.org/libs/local_function +#include +#ifdef BOOST_NO_VARIADIC_MACROS +# error "variadic macros required" +#else + #include "addable.hpp" #include #include #include -#define BOOST_TEST_MODULE TestTypeofTemplate -#include +#include #include //[typeof_template @@ -23,14 +27,17 @@ T calculate(const T& factor) { BOOST_CONCEPT_ASSERT((Addable::type>)); sum += factor * num; - } BOOST_LOCAL_FUNCTION_NAME(add) + } BOOST_LOCAL_FUNCTION_NAME_TPL(add) add(6); return sum; } //] -BOOST_AUTO_TEST_CASE( test_typeof_template ) { - BOOST_CHECK( calculate(10) == 60 ); +int main(void) { + BOOST_TEST(calculate(10) == 60); + return boost::report_errors(); } +#endif // VARIADIC_MACROS + diff --git a/test/typeof_template_seq.cpp b/test/typeof_template_seq.cpp new file mode 100644 index 0000000..60028e9 --- /dev/null +++ b/test/typeof_template_seq.cpp @@ -0,0 +1,33 @@ + +// 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/local_function + +#include "addable.hpp" +#include +#include +#include +#include +#include + +template +T calculate(const T& factor) { + T sum = 0; + + void BOOST_LOCAL_FUNCTION_TPL( (const bind factor) (bind& sum) (T num) ) { + BOOST_CONCEPT_ASSERT((Addable::type>)); + sum += factor * num; + } BOOST_LOCAL_FUNCTION_NAME_TPL(add) + + add(6); + return sum; +} + +int main(void) { + BOOST_TEST(calculate(10) == 60); + return boost::report_errors(); +} + diff --git a/test/typeof_template_seq_nova.cpp b/test/typeof_template_seq_nova.cpp new file mode 100644 index 0000000..48df4d4 --- /dev/null +++ b/test/typeof_template_seq_nova.cpp @@ -0,0 +1,10 @@ + +// 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/local_function + +#include "nova.hpp" +#include "typeof_template_seq.cpp" +