gcc_lambda.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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 GCC_LAMBDA_HPP_
  7. #define GCC_LAMBDA_HPP_
  8. #include <boost/local_function.hpp>
  9. #include <boost/local_function/detail/preprocessor/void_list.hpp>
  10. #include <boost/local_function/detail/preprocessor/line_counter.hpp>
  11. #include <boost/local_function/detail/preprocessor/keyword/return.hpp>
  12. #include <boost/local_function/detail/preprocessor/keyword/const_bind.hpp>
  13. #include <boost/local_function/detail/preprocessor/keyword/bind.hpp>
  14. #include <boost/preprocessor/list/for_each_i.hpp>
  15. #include <boost/preprocessor/list/fold_left.hpp>
  16. #include <boost/preprocessor/list/append.hpp>
  17. #include <boost/preprocessor/list/enum.hpp>
  18. #include <boost/preprocessor/list/adt.hpp>
  19. #include <boost/preprocessor/tuple/elem.hpp>
  20. #include <boost/preprocessor/tuple/eat.hpp>
  21. #include <boost/preprocessor/control/iif.hpp>
  22. #include <boost/preprocessor/punctuation/comma_if.hpp>
  23. #include <boost/preprocessor/facilities/expand.hpp>
  24. #include <boost/preprocessor/cat.hpp>
  25. #include <boost/config.hpp>
  26. // PRIVATE //
  27. #define GCC_LAMBDA_SPLIT_BIND_(elem, binds, params, results) \
  28. (BOOST_PP_LIST_APPEND(binds, (elem, BOOST_PP_NIL)), params, results)
  29. #define GCC_LAMBDA_SPLIT_PARAM_(elem, binds, params, results) \
  30. (binds, BOOST_PP_LIST_APPEND(params, (elem, BOOST_PP_NIL)), results)
  31. #define GCC_LAMBDA_SPLIT_RESULT_(elem, binds, params, results) \
  32. (binds, params, BOOST_PP_LIST_APPEND(results, (elem, BOOT_PP_NIL)))
  33. #define GCC_LAMBDA_SPLIT_DISPATCH_(d, binds_params_results, elem) \
  34. BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_RETURN_FRONT(elem), \
  35. GCC_LAMBDA_SPLIT_RESULT_ \
  36. , BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_BIND_FRONT(elem), \
  37. GCC_LAMBDA_SPLIT_BIND_ \
  38. , BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_CONST_BIND_FRONT( \
  39. elem), \
  40. GCC_LAMBDA_SPLIT_BIND_ \
  41. , /* no result, no bind, and no const bind so it's param */ \
  42. GCC_LAMBDA_SPLIT_PARAM_ \
  43. )))(elem, BOOST_PP_TUPLE_ELEM(3, 0, binds_params_results), \
  44. BOOST_PP_TUPLE_ELEM(3, 1, binds_params_results), \
  45. BOOST_PP_TUPLE_ELEM(3, 2, binds_params_results))
  46. #define GCC_LAMBDA_SPLIT_(list) \
  47. BOOST_PP_LIST_FOLD_LEFT(GCC_LAMBDA_SPLIT_DISPATCH_, \
  48. (BOOST_PP_NIL, BOOST_PP_NIL, BOOST_PP_NIL), list)
  49. #define GCC_LAMBDA_REMOVE_CONST_BIND_(r, unused, i, elem) \
  50. BOOST_PP_COMMA_IF(i) \
  51. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_CONST_BIND_REMOVE_FRONT(elem)
  52. #define GCC_LAMBDA_RESULT_TYPE_(results) \
  53. BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RETURN_REMOVE_FRONT( \
  54. BOOST_PP_LIST_FIRST(results))
  55. #ifdef BOOST_NO_CXX11_LAMBDAS
  56. //[gcc_lambda_macro
  57. # define GCC_LAMBDA_(binds, params, results) \
  58. ({ /* open statement expression (GCC extension only) */ \
  59. BOOST_LOCAL_FUNCTION( \
  60. BOOST_PP_LIST_ENUM(BOOST_PP_LIST_APPEND(binds, \
  61. BOOST_PP_LIST_APPEND(params, \
  62. BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(results), \
  63. (return void, BOOST_PP_NIL) /* default for lambdas */ \
  64. , \
  65. results \
  66. )\
  67. ) \
  68. )) \
  69. )
  70. //]
  71. #else
  72. # define GCC_LAMBDA_(binds, params, results) \
  73. /* ignore const binding because not supported by C++11 lambdas */ \
  74. [ BOOST_PP_LIST_FOR_EACH_I(GCC_LAMBDA_REMOVE_CONST_BIND_, ~, binds) ] \
  75. ( BOOST_PP_LIST_ENUM(params) ) \
  76. BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(results), \
  77. BOOST_PP_TUPLE_EAT(1) /* void result type (default) */ \
  78. , \
  79. -> GCC_LAMBDA_RESULT_TYPE_ \
  80. )(results)
  81. #endif
  82. #define GCC_LAMBDA_TUPLE_(binds_params_results) \
  83. GCC_LAMBDA_(BOOST_PP_TUPLE_ELEM(3, 0, binds_params_results), \
  84. BOOST_PP_TUPLE_ELEM(3, 1, binds_params_results), \
  85. BOOST_PP_TUPLE_ELEM(3, 2, binds_params_results))
  86. //[gcc_lambda_end_macro
  87. #define GCC_LAMBDA_END_(id) \
  88. BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(gcc_lambda_, id)) \
  89. BOOST_PP_CAT(gcc_lambda_, id); \
  90. }) /* close statement expression (GCC extension only) */
  91. //]
  92. // PUBLIC //
  93. // Same arguments as for local functions but respect to C++11 lambdas:
  94. // const bind v is =v, bind& v is &v, void if no return specified, no = or &.
  95. #ifdef BOOST_NO_CXX11_VARIADIC_MACROS
  96. # define GCC_LAMBDA(void_or_seq) \
  97. GCC_LAMBDA_TUPLE_(GCC_LAMBDA_SPLIT_( \
  98. BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(void_or_seq)))
  99. #else
  100. # define GCC_LAMBDA(...) \
  101. GCC_LAMBDA_TUPLE_(GCC_LAMBDA_SPLIT_( \
  102. BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__)))
  103. #endif
  104. #ifdef BOOST_NO_CXX11_LAMBDAS
  105. # define GCC_LAMBDA_END \
  106. GCC_LAMBDA_END_(BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER)
  107. #else
  108. # define GCC_LAMBDA_END /* nothing */
  109. #endif
  110. #endif // #include guard