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