• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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