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