diff options
Diffstat (limited to 'boost/local_function/aux_/macro/name.hpp')
-rw-r--r-- | boost/local_function/aux_/macro/name.hpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/boost/local_function/aux_/macro/name.hpp b/boost/local_function/aux_/macro/name.hpp new file mode 100644 index 0000000000..7f6dc6a55d --- /dev/null +++ b/boost/local_function/aux_/macro/name.hpp @@ -0,0 +1,201 @@ + +// 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_NAME_HPP_ +#define BOOST_LOCAL_FUNCTION_AUX_NAME_HPP_ + +#include <boost/local_function/config.hpp> +#include <boost/local_function/aux_/macro/decl.hpp> +#include <boost/local_function/aux_/macro/code_/functor.hpp> +#include <boost/local_function/detail/preprocessor/keyword/recursive.hpp> +#include <boost/local_function/detail/preprocessor/keyword/inline.hpp> +#include <boost/local_function/aux_/function.hpp> +#include <boost/local_function/aux_/symbol.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/preprocessor/control/expr_iif.hpp> +#include <boost/preprocessor/logical/bitor.hpp> +#include <boost/preprocessor/tuple/eat.hpp> + +// 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) ) + +#define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_FUNC_( \ + is_recursive, local_function_name) \ + BOOST_PP_IIF(is_recursive, \ + local_function_name \ + , \ + BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (nonrecursive_local_function_name) ) \ + ) + +#define BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \ + local_function_name, is_recursive, \ + local_functor_name, nonlocal_functor_name) \ + /* 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); \ + /* 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) */ \ + 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_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 */ \ + local_functor_name.BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC( \ + &local_functor_name, nonlocal_functor_name); \ + BOOST_PP_EXPR_IIF(is_recursive, \ + /* init recursion causes MSVC to not optimize local function not */ \ + /* even when local functor is used as template parameter so no */ \ + /* recursion unless all inlining optimizations are specified off */ \ + local_functor_name.BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_( \ + nonlocal_functor_name); \ + ) + +#define BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(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_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, */ \ + /* so this allows optimization at least on C++11) */ \ + 0 /* not recursive */ , \ + /* local functor */ \ + BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(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_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)*/ \ + 0 /* not recursive */ , \ + /* 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_NAME_FUNCTOR_(local_function_name)) + +// 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_( \ + 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 */ , \ + /* local functor */ \ + BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(local_function_name), \ + /* local function declared as non-local functor -- but it can */ \ + /* be inlined only by C++11 */ \ + local_function_name) + +// 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_NAME_PARSE_INLINE_( \ + typename01, qualified_name) \ + BOOST_PP_IIF(BOOST_PP_BITOR( \ + 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 */ \ + /* it to be faster and it can also be passed as tparam */ \ + BOOST_LOCAL_FUNCTION_AUX_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_NAME_ \ + )(typename01, BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ + qualified_name)) + +// Expand to 1 iff `recursive name` or `recursive inline name` or +// `inline recursive name`. +#define BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name) \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_RECURSIVE_FRONT( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ + qualified_name \ + )) + +// Revmoes `recursive`, `inline recursive`, and `recursive inline` from front. +#define BOOST_LOCAL_FUNCTION_AUX_NAME_REMOVE_RECURSIVE_AND_INLINE_( \ + qualified_name) \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RECURSIVE_REMOVE_FRONT( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \ + BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RECURSIVE_REMOVE_FRONT( \ + qualified_name \ + ))) + +#define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name) \ + BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name), \ + BOOST_LOCAL_FUNCTION_AUX_NAME_REMOVE_RECURSIVE_AND_INLINE_ \ + , \ + qualified_name /* might be `name` or `inline name` */ \ + BOOST_PP_TUPLE_EAT(1) \ + )(qualified_name) + +// 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_( \ + 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_ \ + )(typename01, \ + BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name)) + +// PUBLIC // + +#define BOOST_LOCAL_FUNCTION_AUX_NAME(typename01, qualified_name) \ + BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_(typename01, qualified_name) + +#endif // #include guard + |