name.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright (C) 2009-2012 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0
  3. // (see accompanying file LICENSE_1_0.txt or a copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Home at http://www.boost.org/libs/local_function
  6. #ifndef BOOST_LOCAL_FUNCTION_AUX_NAME_HPP_
  7. #define BOOST_LOCAL_FUNCTION_AUX_NAME_HPP_
  8. #include <boost/local_function/config.hpp>
  9. #include <boost/local_function/aux_/macro/decl.hpp>
  10. #include <boost/local_function/aux_/macro/code_/functor.hpp>
  11. #include <boost/local_function/detail/preprocessor/keyword/recursive.hpp>
  12. #include <boost/local_function/detail/preprocessor/keyword/inline.hpp>
  13. #include <boost/local_function/aux_/function.hpp>
  14. #include <boost/local_function/aux_/symbol.hpp>
  15. #include <boost/preprocessor/control/iif.hpp>
  16. #include <boost/preprocessor/control/expr_iif.hpp>
  17. #include <boost/preprocessor/logical/bitor.hpp>
  18. #include <boost/preprocessor/tuple/eat.hpp>
  19. // PRIVATE //
  20. #define BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name) \
  21. BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (local_type)(local_function_name) )
  22. #define BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_ \
  23. BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (init_recursion) )
  24. #define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_FUNC_( \
  25. is_recursive, local_function_name) \
  26. BOOST_PP_IIF(is_recursive, \
  27. local_function_name \
  28. , \
  29. BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (nonrecursive_local_function_name) ) \
  30. )
  31. #define BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \
  32. local_function_name, is_recursive, \
  33. local_functor_name, nonlocal_functor_name) \
  34. /* FUNCTION macro expanded to: typedef class functor ## __LINE__ { ... */ \
  35. BOOST_PP_EXPR_IIF(is_recursive, \
  36. /* member var with function name for recursive calls; it cannot be */ \
  37. /* `const` because it is init after construction (because */ \
  38. /* constructor doesn't know local function name) */ \
  39. /* run-time: even when optimizing, recursive calls cannot be */ \
  40. /* optimized (i.e., they must be via the non-local functor) */ \
  41. /* because this cannot be a mem ref because its name is not known */ \
  42. /* by the constructor so it cannot be set by the mem init list */ \
  43. private: \
  44. BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE \
  45. BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_FUNC_(is_recursive, \
  46. local_function_name); \
  47. /* run-time: the `init_recursion()` function cannot be called */ \
  48. /* by the constructor to allow for compiler optimization */ \
  49. /* (inlining) so it must be public to be called (see below) */ \
  50. public: \
  51. inline void BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_( \
  52. BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE& functor) { \
  53. local_function_name = functor; \
  54. } \
  55. ) \
  56. } BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name); \
  57. /* local functor can be passed as tparam only on C++11 (faster) */ \
  58. BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name) \
  59. local_functor_name(BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR.value); \
  60. /* non-local functor can always be passed as tparam (but slower) */ \
  61. BOOST_PP_EXPR_IIF(typename01, typename) \
  62. BOOST_LOCAL_FUNCTION_AUX_NAME_LOCAL_TYPE_(local_function_name):: \
  63. BOOST_LOCAL_FUNCTION_AUX_CODE_FUNCTOR_TYPE \
  64. nonlocal_functor_name; /* functor variable */ \
  65. /* the order of the following 2 function calls cannot be changed */ \
  66. /* because init_recursion uses the local_functor so the local_functor */ \
  67. /* must be init first */ \
  68. local_functor_name.BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC( \
  69. &local_functor_name, nonlocal_functor_name); \
  70. BOOST_PP_EXPR_IIF(is_recursive, \
  71. /* init recursion causes MSVC to not optimize local function not */ \
  72. /* even when local functor is used as template parameter so no */ \
  73. /* recursion unless all inlining optimizations are specified off */ \
  74. local_functor_name.BOOST_LOCAL_FUNCTION_AUX_NAME_INIT_RECURSION_FUNC_( \
  75. nonlocal_functor_name); \
  76. )
  77. #define BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(local_function_name) \
  78. BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (local_function_name) )
  79. // This can always be passed as a template parameters (on all compilers).
  80. // However, it is slower because it cannot be inlined.
  81. // Passed at tparam: Yes (on all C++). Inlineable: No. Recursive: No.
  82. #define BOOST_LOCAL_FUNCTION_AUX_NAME_(typename01, local_function_name) \
  83. BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \
  84. local_function_name, \
  85. /* local function is not recursive (because recursion and its */ \
  86. /* initialization cannot be inlined even on C++11, */ \
  87. /* so this allows optimization at least on C++11) */ \
  88. 0 /* not recursive */ , \
  89. /* local functor */ \
  90. BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(local_function_name), \
  91. /* local function declared as non-local functor -- but it can */ \
  92. /* be inlined only by C++11 and it cannot be recursive */ \
  93. local_function_name)
  94. // This is faster on some compilers but not all (e.g., it is faster on GCC
  95. // because its optimization inlines it but not on MSVC). However, it cannot be
  96. // passed as a template parameter on non C++11 compilers.
  97. // Passed at tparam: Only on C++11. Inlineable: Yes. Recursive: No.
  98. #define BOOST_LOCAL_FUNCTION_AUX_NAME_INLINE_(typename01, local_function_name) \
  99. BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \
  100. local_function_name, \
  101. /* inlined local function is never recursive (because recursion */ \
  102. /* and its initialization cannot be inlined)*/ \
  103. 0 /* not recursive */ , \
  104. /* inlined local function declared as local functor (maybe */ \
  105. /* inlined even by non C++11 -- but it can be passed as */ \
  106. /* template parameter only on C++11 */ \
  107. local_function_name, \
  108. /* non-local functor */ \
  109. BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(local_function_name))
  110. // This is slower on all compilers (C++11 and non) because recursion and its
  111. // initialization can never be inlined.
  112. // Passed at tparam: Yes. Inlineable: No. Recursive: Yes.
  113. #define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_( \
  114. typename01, local_function_name) \
  115. BOOST_LOCAL_FUNCTION_AUX_NAME_END_LOCAL_FUNCTOR_(typename01, \
  116. local_function_name, \
  117. /* recursive local function -- but it cannot be inlined */ \
  118. 1 /* recursive */ , \
  119. /* local functor */ \
  120. BOOST_LOCAL_FUNCTION_AUX_NAME_FUNCTOR_(local_function_name), \
  121. /* local function declared as non-local functor -- but it can */ \
  122. /* be inlined only by C++11 */ \
  123. local_function_name)
  124. // Inlined local functions are specified by `..._NAME(inline name)`.
  125. // They have more chances to be inlined for faster run-times by some compilers
  126. // (for example by GCC but not by MSVC). C++11 compilers can always inline
  127. // local functions even if they are not explicitly specified inline.
  128. #define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_INLINE_( \
  129. typename01, qualified_name) \
  130. BOOST_PP_IIF(BOOST_PP_BITOR( \
  131. BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, \
  132. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_INLINE_FRONT( \
  133. qualified_name)), \
  134. /* on C++11 always use inlining because compilers might optimize */ \
  135. /* it to be faster and it can also be passed as tparam */ \
  136. BOOST_LOCAL_FUNCTION_AUX_NAME_INLINE_ \
  137. , \
  138. /* on non C++11 don't use liniling unless explicitly specified by */ \
  139. /* programmers `inline name` the inlined local function cannot be */ \
  140. /* passed as tparam */ \
  141. BOOST_LOCAL_FUNCTION_AUX_NAME_ \
  142. )(typename01, BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \
  143. qualified_name))
  144. // Expand to 1 iff `recursive name` or `recursive inline name` or
  145. // `inline recursive name`.
  146. #define BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name) \
  147. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_RECURSIVE_FRONT( \
  148. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \
  149. qualified_name \
  150. ))
  151. // Revmoes `recursive`, `inline recursive`, and `recursive inline` from front.
  152. #define BOOST_LOCAL_FUNCTION_AUX_NAME_REMOVE_RECURSIVE_AND_INLINE_( \
  153. qualified_name) \
  154. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RECURSIVE_REMOVE_FRONT( \
  155. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_INLINE_REMOVE_FRONT( \
  156. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RECURSIVE_REMOVE_FRONT( \
  157. qualified_name \
  158. )))
  159. #define BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name) \
  160. BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name), \
  161. BOOST_LOCAL_FUNCTION_AUX_NAME_REMOVE_RECURSIVE_AND_INLINE_ \
  162. , \
  163. qualified_name /* might be `name` or `inline name` */ \
  164. BOOST_PP_TUPLE_EAT(1) \
  165. )(qualified_name)
  166. // Recursive local function are specified by `..._NAME(recursive name)`.
  167. // They can never be inlined for faster run-time (not even by C++11 compilers).
  168. #define BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_( \
  169. typename01, qualified_name) \
  170. BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_AUX_NAME_IS_RECURSIVE_(qualified_name), \
  171. /* recursion can never be inlined (not even on C++11) */ \
  172. BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_ \
  173. , \
  174. BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_INLINE_ \
  175. )(typename01, \
  176. BOOST_LOCAL_FUNCTION_AUX_NAME_RECURSIVE_REMOVE_(qualified_name))
  177. // PUBLIC //
  178. #define BOOST_LOCAL_FUNCTION_AUX_NAME(typename01, qualified_name) \
  179. BOOST_LOCAL_FUNCTION_AUX_NAME_PARSE_RECURSIVE_(typename01, qualified_name)
  180. #endif // #include guard