Chris@16: Chris@16: // Copyright (C) 2009-2012 Lorenzo Caminiti Chris@16: // Distributed under the Boost Software License, Version 1.0 Chris@16: // (see accompanying file LICENSE_1_0.txt or a copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Home at http://www.boost.org/libs/local_function Chris@16: Chris@16: #ifndef BOOST_LOCAL_FUNCTION_HPP_ Chris@16: #define BOOST_LOCAL_FUNCTION_HPP_ Chris@16: Chris@16: #ifndef DOXYGEN Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // PUBLIC // Chris@16: Chris@16: #ifdef BOOST_NO_CXX11_VARIADIC_MACROS Chris@16: # define BOOST_LOCAL_FUNCTION_ID(id, declarations) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_DECL(id, 0 /* not within template */, \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST( \ Chris@16: declarations))) Chris@16: # define BOOST_LOCAL_FUNCTION(declarations) \ Chris@16: BOOST_LOCAL_FUNCTION_ID( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, declarations) Chris@16: # define BOOST_LOCAL_FUNCTION_ID_TPL(id, declarations) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_DECL(id, 1 /* within template */, \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST( \ Chris@16: declarations))) Chris@16: # define BOOST_LOCAL_FUNCTION_TPL(declarations) \ Chris@16: BOOST_LOCAL_FUNCTION_ID_TPL( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, declarations) Chris@16: #else // VARIADIC Chris@16: # define BOOST_LOCAL_FUNCTION_ID(id, ...) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_DECL(id, 0 /* not within template */, \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__))) Chris@16: # define BOOST_LOCAL_FUNCTION(...) \ Chris@16: BOOST_LOCAL_FUNCTION_ID( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, __VA_ARGS__) Chris@16: # define BOOST_LOCAL_FUNCTION_ID_TPL(id, ...) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_DECL(id, 1 /* within template */, \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__))) Chris@16: # define BOOST_LOCAL_FUNCTION_TPL(...) \ Chris@16: BOOST_LOCAL_FUNCTION_ID_TPL( \ Chris@16: BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, __VA_ARGS__) Chris@16: #endif // VARIADIC Chris@16: Chris@16: #define BOOST_LOCAL_FUNCTION_NAME(qualified_name) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_NAME(0 /* not within template */, qualified_name) Chris@16: #define BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_NAME(1 /* within template */, qualified_name) Chris@16: Chris@16: #define BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name) \ Chris@16: BOOST_LOCAL_FUNCTION_AUX_TYPEOF_TYPE(bound_variable_name) Chris@16: Chris@16: // DOCUMENTATION // Chris@16: Chris@16: #else // DOXYGEN Chris@16: Chris@16: /** @file Chris@16: @brief Local functions allow to program functions locally, within other Chris@16: functions, and directly within the scope where they are needed. Chris@16: */ Chris@16: Chris@16: /** Chris@16: @brief This macro is used to start a local function declaration. Chris@16: Chris@16: This macro must be used within a declarative context, it must follow the local Chris@16: function result type, it must be followed by the local function body code, and Chris@16: then by the @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro (see the Chris@16: @RefSect{tutorial, Tutorial} and @RefSect{advanced_topics, Advanced Topics} Chris@16: sections): Chris@16: @code Chris@16: { // Some declarative context. Chris@16: ... Chris@16: result_type BOOST_LOCAL_FUNCTION(declarations) { Chris@16: ... // Body code. Chris@16: } BOOST_LOCAL_FUNCTION_NAME(qualified_name) Chris@16: ... Chris@16: } Chris@16: @endcode Chris@16: Chris@16: As usual, exceptions specifications can be optionally programmed just after the Chris@16: macro and before the body code block { ... } (but the exception Chris@16: specifications will only apply to the body code and not to the library code Chris@16: automatically generated by the macro expansion, see the Chris@16: @RefSect{advanced_topics, Advanced Topics} section). Chris@16: Chris@16: Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_TPL} Chris@16: and @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used. Chris@16: Chris@16: @Params Chris@16: @Param{declarations, Chris@16: On compilers that support variadic macros\, the parameter declarations are Chris@16: defined by the following grammar: Chris@16: @code Chris@16: declarations: Chris@16: void | declaration_tuple | declaration_sequence Chris@16: declaration_tuple: Chris@16: declaration\, declaration\, ... Chris@16: declaration_sequence: Chris@16: (declaration) (declaration) ... Chris@16: declaration: Chris@16: bound_variable | parameter | default_value | result_type Chris@16: bound_variable: Chris@16: [const] bind [(variable_type)] [&] variable_name Chris@16: parameter: Chris@16: [auto | register] parameter_type parameter_name Chris@16: default_value: Chris@16: default parameter_default_value Chris@16: result_type: Chris@16: return function_result_type Chris@16: @endcode Chris@16: On compilers that do not support variadic macros\, declaration_tuple Chris@16: cannot be used: Chris@16: @code Chris@16: declarations: Chris@16: void | declaration_sequence Chris@16: @endcode Chris@16: Chris@16: (Lexical conventions: token1 | token2 means either token1 or Chris@16: token2; [token] means either token or nothing; Chris@16: {expression} means the token resulting from the expression.) Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: Note that on compilers that support variadic macros, commas can be used to Chris@16: separate the declarations resembling more closely the usual C++ function Chris@16: declaration syntax (this is the preferred syntax). Chris@16: However, for portability, on all C++ compilers (with and without variadic Chris@16: macros) the same library macros also accept parameter declarations specified as Chris@16: a Boost.Preprocessor sequence separated by round parenthesis (). Chris@16: Chris@16: When binding the object this, the special symbol this_ needs to Chris@16: be used instead of this as the name of the variable to bind and also Chris@16: within the local function body to access the object. Chris@16: (Mistakenly using this instead of this_ might not always result in a compiler error and will in general result in undefined behaviour.) Chris@16: Chris@16: The result type must either be specified just before the macro or within the Chris@16: macro declarations prefixed by return (but not in both places). Chris@16: Chris@16: 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. Chris@16: The bound variable types can be accessed using @RefMacro{BOOST_LOCAL_FUNCTION_TYPEOF}. Chris@16: Chris@16: This macro cannot be portably expanded multiple times on the same line. Chris@16: In these cases, use the @RefMacro{BOOST_LOCAL_FUNCTION_ID} macro instead. Chris@16: Chris@16: The maximum number of local function parameters (excluding bound variables) is Chris@16: specified by the configuration macro Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}. Chris@16: The maximum number of bound variables is specified by the configuration macro Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}. Chris@16: The configuration macro Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS} can be used to force Chris@16: optimizations that reduce the local function call run-time overhead. Chris@16: Chris@16: @Note Local functions are functors so they can be assigned to other functors Chris@16: like boost::function (see Boost.Function). Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, Chris@16: @RefSect{advanced_topics, Advanced Topics} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, @RefMacro{BOOST_LOCAL_FUNCTION_TPL}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_TYPEOF}, @RefMacro{BOOST_LOCAL_FUNCTION_ID}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION(declarations) Chris@16: Chris@16: /** Chris@16: @brief This macro is used to start a local function declaration within Chris@16: templates. Chris@16: Chris@16: This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION} when Chris@16: declaring a local function within a template. Chris@16: A part from that, this macro has the exact same syntax a Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION} (see @RefMacro{BOOST_LOCAL_FUNCTION} for more Chris@16: information): Chris@16: @code Chris@16: { // Some declarative context within a template. Chris@16: ... Chris@16: result_type BOOST_LOCAL_FUNCTION_TPL(declarations) { Chris@16: ... // Body code. Chris@16: } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) Chris@16: ... Chris@16: } Chris@16: @endcode Chris@16: Chris@16: Note that @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used with this Chris@16: macro instead of @RefMacro{BOOST_LOCAL_FUNCTION_NAME}. Chris@16: Chris@16: This macro cannot be portably expanded multiple times on the same line. Chris@16: In these cases, use the @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL} macro instead. Chris@16: Chris@16: @Note C++03 does not allow to use typename outside templates. Chris@16: This library internally manipulates types, these operations require Chris@16: typename but only within templates. Chris@16: This macro is used to indicate to the library when the enclosing scope is a Chris@16: template so the library can correctly use typename. Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, @RefMacro{BOOST_LOCAL_FUNCTION}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_TPL(declarations) Chris@16: Chris@16: /** Chris@16: @brief This macro allows to declare multiple local functions on the same line. Chris@16: Chris@16: This macro is equivalent to @RefMacro{BOOST_LOCAL_FUNCTION} but it can be Chris@16: expanded multiple times on the same line if different identifiers id are Chris@16: provided for each expansion (see the Chris@16: @RefSect{advanced_topics, Advanced Topics} section). Chris@16: Chris@16: @Params Chris@16: @Param{id, Chris@16: A unique identifier token which can be concatenated by the preprocessor Chris@16: (__LINE__\, local_function_number_1_on_line_123\, etc). Chris@16: } Chris@16: @Param{declarations, Chris@16: Same as the declarations parameter of the Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION} macro. Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: The @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro should be used to end each one Chris@16: of the multiple local function declarations as usual (and it will specify a Chris@16: unique name for each local function). Chris@16: Chris@16: Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL} Chris@16: must be used. Chris@16: Chris@16: @Note This macro can be useful when the local function macros are expanded Chris@16: within user-defined macros (because macros all expand on the same line). Chris@16: On some compilers (e.g., MSVC which supports the non-standard Chris@16: __COUNTER__ macro) it might not be necessary to use this macro but Chris@16: the use of this macro when expanding multiple local function macros on the same Chris@16: line is always necessary to ensure portability (this is because this library Chris@16: can only portably use __LINE__ to internally generate unique Chris@16: identifiers). Chris@16: Chris@16: @See @RefSect{advanced_topics, Advanced Topics} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION}, @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_ID_TPL}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_ID(id, declarations) Chris@16: Chris@16: /** Chris@16: @brief This macro allows to declare multiple local functions on the same line Chris@16: within templates. Chris@16: Chris@16: This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION_TPL} when Chris@16: declaring multiple local functions on the same line within a template. Chris@16: A part from that, this macro has the exact same syntax as Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_TPL} (see @RefMacro{BOOST_LOCAL_FUNCTION_TPL} Chris@16: for more information). Chris@16: Chris@16: @Params Chris@16: @Param{id, Chris@16: A unique identifier token which can be concatenated by the preprocessor Chris@16: (__LINE__\, local_function_number_1_on_line_123\, etc). Chris@16: } Chris@16: @Param{declarations, Chris@16: Same as the declarations parameter of the Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_TPL} macro. Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: The @RefMacro{BOOST_LOCAL_FUNCTION_NAME} macro should be used to end each one Chris@16: of the multiple local function declarations as usual (and it will specify a Chris@16: unique name for each local function). Chris@16: Chris@16: Outside template, the macro @RefMacro{BOOST_LOCAL_FUNCTION_ID} should be used Chris@16: to declare multiple local functions on the same line. Chris@16: Chris@16: @Note This macro can be useful when the local function macros are expanded Chris@16: within user-defined macros (because macros all expand on the same line). Chris@16: On some compilers (e.g., MSVC which supports the non-standard Chris@16: __COUNTER__ macro) it might not be necessary to use this macro but Chris@16: the use of this macro when expanding multiple local function macros on the same Chris@16: line is always necessary to ensure portability (this is because this library Chris@16: can only portably use __LINE__ to internally generate unique Chris@16: identifiers). Chris@16: Chris@16: @See @RefSect{advanced_topics, Advanced Topics} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_TPL}, @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_ID}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_ID_TPL(id, declarations) Chris@16: Chris@16: /** Chris@16: @brief This macro is used to end a local function declaration specifying its Chris@16: name. Chris@16: Chris@16: This macro must follow the local function body code block { ... }: Chris@16: @code Chris@16: { // Some declarative context. Chris@16: ... Chris@16: result_type BOOST_LOCAL_FUNCTION(declarations) { Chris@16: ... // Body code. Chris@16: } BOOST_LOCAL_FUNCTION_NAME(qualified_name) Chris@16: ... Chris@16: } Chris@16: @endcode Chris@16: Chris@16: Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_TPL} and Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used. Chris@16: Chris@16: @Params Chris@16: @Param{qualified_name, Chris@16: The name of the local function optionally qualified as follow: Chris@16: @code Chris@16: name: Chris@16: [inline] [recursive] local_function_name Chris@16: @endcode Chris@16: (Lexical conventions: token1 | token2 means either token1 or Chris@16: token2; [token] means either token or nothing; Chris@16: {expression} means the token resulting from the expression.) Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: The local function name can be qualified by prefixing it with the keyword Chris@16: inline (see the @RefSect{advanced_topics, Advanced Topics} section): Chris@16: @code Chris@16: BOOST_LOCAL_FUNCTION_NAME(inline local_function_name) Chris@16: @endcode Chris@16: This increases the chances that the compiler will be able to inline the local Chris@16: function calls (thus reducing run-time). Chris@16: However, inline local functions cannot be passed as template parameters (e.g., to std::for_each) or assigned to other functors (e.g., to Chris@16: boost::function). Chris@16: That is true on C++03 compilers but inline local functions can instead be Chris@16: passed as template parameters on C++11 compilers. Chris@16: On C++11 compilers, there is no need to declare a local function lined because Chris@16: this library will automatically use C++11 specific features to inline the local Chris@16: function while always allowing to pass it as a template parameter. Chris@16: This optimization is automatically enabled when the Boost.Config macro Chris@16: BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS is not defined but it also be Chris@16: forced using @RefMacro{BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS}. Chris@16: Chris@16: The local function name can also be qualified by prefixing it with the Chris@16: "keyword" recursive (see the Chris@16: @RefSect{advanced_topics, Advanced Topics} section): Chris@16: @code Chris@16: BOOST_LOCAL_FUNCTION_NAME(recursive local_function_name) Chris@16: @endcode Chris@16: This allows the local function to recursively call itself from its body (as Chris@16: usual in C++). Chris@16: However, recursive local functions should only be called within their Chris@16: declaration scope (otherwise the result is undefined behaviour). Chris@16: Finally, compilers have not been observed to be able to inline recursive local Chris@16: function calls, not even when the recursive local function is also declared Chris@16: inline: Chris@16: @code Chris@16: BOOST_LOCAL_FUNCTION(inline recursive local_function_name) Chris@16: @endcode Chris@16: Chris@16: @Note The local function name cannot be the name of an operator Chris@16: operator... and it cannot be the same name of another local function Chris@16: declared within the same enclosing scope (but boost::overloaded_function Chris@16: can be used to overload local functions, see Chris@16: Boost.Functional/OverloadedFunction and the Chris@16: @RefSect{advanced_topics, Advanced Topics} section). Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, Chris@16: @RefSect{advanced_topics, Advanced Topics} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION}, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_NAME(qualified_name) Chris@16: Chris@16: /** Chris@16: @brief This macro is used to end a local function declaration specifying its Chris@16: name within templates. Chris@16: Chris@16: This macro must be used instead of @RefMacro{BOOST_LOCAL_FUNCTION_NAME} when Chris@16: declaring a local function within a template. Chris@16: A part from that, this macro has the exact same syntax a Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME} (see @RefMacro{BOOST_LOCAL_FUNCTION_NAME} Chris@16: for more information): Chris@16: @code Chris@16: { // Some declarative context within a template. Chris@16: ... Chris@16: result_type BOOST_LOCAL_FUNCTION_TPL(declarations) { Chris@16: ... // Body code. Chris@16: } BOOST_LOCAL_FUNCTION_NAME_TPL(qualified_name) Chris@16: ... Chris@16: } Chris@16: @endcode Chris@16: Chris@16: Note that @RefMacro{BOOST_LOCAL_FUNCTION_TPL} must be used with this macro Chris@16: instead of @RefMacro{BOOST_LOCAL_FUNCTION}. Chris@16: Chris@16: @Note C++03 does not allow to use typename outside templates. Chris@16: This library internally manipulates types, these operations require Chris@16: typename but only within templates. Chris@16: This macro is used to indicate to the library when the enclosing scope is a Chris@16: template so the library can correctly use typename. Chris@16: Chris@16: @See @RefSect{tutorial, Tutorial} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION_NAME}, @RefMacro{BOOST_LOCAL_FUNCTION_TPL}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_NAME_TPL(name) Chris@16: Chris@16: /** Chris@16: @brief This macro expands to the type of the specified bound variable. Chris@16: Chris@16: This macro can be used within the local functions body to refer to the bound Chris@16: variable types so to declare local variables, check concepts (using Chris@16: Boost.ConceptCheck), etc (see the @RefSect{advanced_topics, Advanced Topics} Chris@16: section). Chris@16: This way the local function can be programmed entirely without explicitly Chris@16: specifying the bound variable types thus facilitating maintenance (e.g., if Chris@16: the type of a bound variable changes in the enclosing scope, the local function Chris@16: code does not have to change). Chris@16: Chris@16: @Params Chris@16: @Param{bound_variable_name, Chris@16: The name of one of the local function's bound variables. Chris@16: } Chris@16: @EndParams Chris@16: Chris@16: The type returned by the macro is fully qualified in that it contains the extra Chris@16: constant and reference qualifiers when the specified variable is bound by Chris@16: constant and by reference. Chris@16: For example, if a variable named t of type T is: Chris@16: @li Bound by value using bind t then Chris@16: BOOST_LOCAL_FUNCTION_TYPEOF(t) is T. Chris@16: @li Bound by constant value using const bind t then Chris@16: BOOST_LOCAL_FUNCTION_TYPEOF(t) is const T. Chris@16: @li Bound by reference using bind& t then Chris@16: BOOST_LOCAL_FUNCTION_TYPEOF(t) is T&. Chris@16: @li Bound by constant reference using const bind& t then Chris@16: BOOST_LOCAL_FUNCTION_TYPEOF(t) is const T&. Chris@16: Chris@16: This macro must be prefixed by typename when used within templates. Chris@16: Chris@16: @Note It is best to use this macro instead of Boost.Typeof so to reduce the Chris@16: number of times Boost.Typeof is used to deduce types (see the Chris@16: @RefSect{advanced_topics, Advanced Topics} section). Chris@16: Chris@16: @See @RefSect{advanced_topics, Advanced Topics} section, Chris@16: @RefMacro{BOOST_LOCAL_FUNCTION}. Chris@16: */ Chris@16: #define BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name) Chris@16: Chris@16: #endif // DOXYGEN Chris@16: Chris@16: #endif // #include guard Chris@16: