| |
| // 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_HPP_ |
| #define BOOST_LOCAL_FUNCTION_HPP_ |
| |
| #ifndef DOXYGEN |
| |
| #include <boost/local_function/aux_/macro/decl.hpp> |
| #include <boost/local_function/aux_/macro/name.hpp> |
| #include <boost/local_function/aux_/macro/typeof.hpp> |
| #include <boost/local_function/aux_/preprocessor/traits/decl.hpp> |
| #include <boost/local_function/detail/preprocessor/line_counter.hpp> |
| #include <boost/local_function/detail/preprocessor/void_list.hpp> |
| #include <boost/config.hpp> |
| |
| // PUBLIC // |
| |
| #ifdef BOOST_NO_CXX11_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_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_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_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_ID_TPL( \ |
| BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER, __VA_ARGS__) |
| #endif // VARIADIC |
| |
| #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) |
| |
| // DOCUMENTATION // |
| |
| #else // DOXYGEN |
| |
| /** @file |
| @brief Local functions allow to program functions locally, within other |
| functions, and directly within the scope where they are needed. |
| */ |
| |
| /** |
| @brief This macro is used to start a local function declaration. |
| |
| 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, 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_name) |
| ... |
| } |
| @endcode |
| |
| As usual, exceptions specifications can be optionally programmed just after the |
| macro and before the body code block <c>{ ... }</c> (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 |
| @RefSect{advanced_topics, Advanced Topics} section). |
| |
| Within templates, the special macros @RefMacro{BOOST_LOCAL_FUNCTION_TPL} |
| and @RefMacro{BOOST_LOCAL_FUNCTION_NAME_TPL} must be used. |
| |
| @Params |
| @Param{declarations, |
| On compilers that support variadic macros\, the parameter declarations are |
| defined by the following grammar: |
| @code |
| declarations: |
| void | declaration_tuple | declaration_sequence |
| declaration_tuple: |
| declaration\, declaration\, ... |
| declaration_sequence: |
| (declaration) (declaration) ... |
| declaration: |
| bound_variable | parameter | default_value | result_type |
| bound_variable: |
| [const] bind [(variable_type)] [&] variable_name |
| parameter: |
| [auto | register] parameter_type parameter_name |
| default_value: |
| default parameter_default_value |
| result_type: |
| return function_result_type |
| @endcode |
| On compilers that do not support variadic macros\, <c>declaration_tuple</c> |
| cannot be used: |
| @code |
| declarations: |
| void | declaration_sequence |
| @endcode |
| |
| (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or |
| <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing; |
| <c>{expression}</c> 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). |
| 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 <c>()</c>. |
| |
| When binding the object <c>this</c>, the special symbol <c>this_</c> needs to |
| be used instead of <c>this</c> as the name of the variable to bind and also |
| within the local function body to access the object. |
| (Mistakenly using <c>this</c> instead of <c>this_</c> 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 <c>return</c> (but not in both places). |
| |
| Within the local function body it possible to access the result type using <c>result_type</c>, the type of the first parameter using <c>arg1_type</c>, the type of the second parameter using <c>arg2_type</c>, 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 <c>boost::function</c> (see Boost.Function). |
| |
| @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_LOCALS_AS_TPARAMS}. |
| */ |
| #define BOOST_LOCAL_FUNCTION(declarations) |
| |
| /** |
| @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 a |
| @RefMacro{BOOST_LOCAL_FUNCTION} (see @RefMacro{BOOST_LOCAL_FUNCTION} 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_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 <c>typename</c> outside templates. |
| This library internally manipulates types, these operations require |
| <c>typename</c> 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 <c>typename</c>. |
| |
| @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 <c>id</c> 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 |
| (<c>__LINE__</c>\, <c>local_function_number_1_on_line_123</c>\, etc). |
| } |
| @Param{declarations, |
| Same as the <c>declarations</c> 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 |
| <c>__COUNTER__</c> 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 <c>__LINE__</c> 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 |
| (<c>__LINE__</c>\, <c>local_function_number_1_on_line_123</c>\, etc). |
| } |
| @Param{declarations, |
| Same as the <c>declarations</c> 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 |
| <c>__COUNTER__</c> 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 <c>__LINE__</c> 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. |
| |
| This macro must follow the local function body code block <c>{ ... }</c>: |
| @code |
| { // Some declarative context. |
| ... |
| result_type BOOST_LOCAL_FUNCTION(declarations) { |
| ... // Body code. |
| } 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_name, |
| The name of the local function optionally qualified as follow: |
| @code |
| name: |
| [inline] [recursive] local_function_name |
| @endcode |
| (Lexical conventions: <c>token1 | token2</c> means either <c>token1</c> or |
| <c>token2</c>; <c>[token]</c> means either <c>token</c> or nothing; |
| <c>{expression}</c> means the token resulting from the expression.) |
| } |
| @EndParams |
| |
| The local function name can be qualified by prefixing it with the keyword |
| <c>inline</c> (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, inline local functions cannot be passed as template parameters (e.g., to <c>std::for_each</c>) or assigned to other functors (e.g., to |
| <c>boost::function</c>). |
| 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 |
| <c>BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS</c> 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" <c>recursive</c> (see the |
| @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, 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 |
| <c>operator...</c> and it cannot be the same name of another local function |
| declared within the same enclosing scope (but <c>boost::overloaded_function</c> |
| can be used to overload local functions, see |
| Boost.Functional/OverloadedFunction and the |
| @RefSect{advanced_topics, Advanced Topics} section). |
| |
| @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_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 <c>typename</c> outside templates. |
| This library internally manipulates types, these operations require |
| <c>typename</c> 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 <c>typename</c>. |
| |
| @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 @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 |
| the type of a bound variable changes in the enclosing scope, the local function |
| code does not have to change). |
| |
| @Params |
| @Param{bound_variable_name, |
| The name of one of the local function's bound variables. |
| } |
| @EndParams |
| |
| The type returned by the macro is fully qualified in that it contains the extra |
| constant and reference qualifiers when the specified variable is bound by |
| constant and by reference. |
| For example, if a variable named <c>t</c> of type <c>T</c> is: |
| @li Bound by value using <c>bind t</c> then |
| <c>BOOST_LOCAL_FUNCTION_TYPEOF(t)</c> is <c>T</c>. |
| @li Bound by constant value using <c>const bind t</c> then |
| <c>BOOST_LOCAL_FUNCTION_TYPEOF(t)</c> is <c>const T</c>. |
| @li Bound by reference using <c>bind& t</c> then |
| <c>BOOST_LOCAL_FUNCTION_TYPEOF(t)</c> is <c>T&</c>. |
| @li Bound by constant reference using <c>const bind& t</c> then |
| <c>BOOST_LOCAL_FUNCTION_TYPEOF(t)</c> is <c>const T&</c>. |
| |
| This macro must be prefixed by <c>typename</c> 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 |
| @RefSect{advanced_topics, Advanced Topics} section). |
| |
| @See @RefSect{advanced_topics, Advanced Topics} section, |
| @RefMacro{BOOST_LOCAL_FUNCTION}. |
| */ |
| #define BOOST_LOCAL_FUNCTION_TYPEOF(bound_variable_name) |
| |
| #endif // DOXYGEN |
| |
| #endif // #include guard |
| |