Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:14

0001 
0002 // Copyright (C) 2009-2012 Lorenzo Caminiti
0003 // Distributed under the Boost Software License, Version 1.0
0004 // (see accompanying file LICENSE_1_0.txt or a copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 // Home at http://www.boost.org/libs/local_function
0007 
0008 #ifndef BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_HPP_
0009 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_HPP_
0010 
0011 #include <boost/local_function/aux_/symbol.hpp>
0012 #include <boost/local_function/aux_/macro/decl.hpp>
0013 #include <boost/local_function/aux_/preprocessor/traits/bind.hpp>
0014 #include <boost/local_function/aux_/preprocessor/traits/decl_binds.hpp>
0015 #include <boost/local_function/aux_/preprocessor/traits/decl_const_binds.hpp>
0016 #include <boost/utility/identity_type.hpp>
0017 #include <boost/scope_exit.hpp>
0018 #include <boost/type_traits/remove_reference.hpp>
0019 #include <boost/type_traits/function_traits.hpp>
0020 #include <boost/preprocessor/control/expr_iif.hpp>
0021 #include <boost/preprocessor/control/iif.hpp>
0022 #include <boost/preprocessor/facilities/empty.hpp>
0023 #include <boost/preprocessor/facilities/is_empty.hpp>
0024 #include <boost/preprocessor/facilities/identity.hpp>
0025 #include <boost/preprocessor/logical/bitand.hpp>
0026 #include <boost/preprocessor/punctuation/comma_if.hpp>
0027 #include <boost/preprocessor/tuple/elem.hpp>
0028 #include <boost/preprocessor/tuple/eat.hpp>
0029 #include <boost/preprocessor/list/adt.hpp>
0030 #include <boost/preprocessor/list/for_each_i.hpp>
0031 #include <boost/preprocessor/list/append.hpp>
0032 
0033 // PRIVATE //
0034 
0035 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAMS_VAR_(id) \
0036     BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (params)(id) )
0037 
0038 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_TAG_DECL_(r, id, i, bind_traits) \
0039     BOOST_SCOPE_EXIT_DETAIL_TAG_DECL(r, id, i, \
0040             BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0041                     bind_traits))
0042 
0043 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_TYPED_( \
0044         r, id, typename01, i, bind_traits) \
0045     typedef BOOST_PP_EXPR_IIF(typename01, typename) \
0046         /* remove ref because typed var can have & prefix */ \
0047         ::boost::remove_reference< BOOST_PP_EXPR_IIF(typename01, typename) \
0048             ::boost::function_traits< \
0049                 /* instead of using Boost.Typeof, get bind type as 1st */ \
0050                 /* argument type of func type `void (type_ [&] var_)` */ \
0051                 void ( BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITH_TYPE( \
0052                         bind_traits) ) \
0053             >::arg1_type \
0054         >::type \
0055         BOOST_SCOPE_EXIT_DETAIL_CAPTURE_T(id, i, \
0056                 BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0057                         bind_traits)) \
0058     ; /* close typedef */
0059 
0060 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_DEDUCED_( \
0061         r, id, typename01, i, bind_traits) \
0062     BOOST_SCOPE_EXIT_DETAIL_CAPTURE_DECL(r, \
0063             ( \
0064                 id \
0065             , \
0066                 /* ScopeExit expects typename or EMPTY() here */ \
0067                 BOOST_PP_EXPR_IIF(typename01, typename) \
0068             ), \
0069             i, BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0070                     bind_traits))
0071 
0072 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_( \
0073         r, id_typename, i, bind_traits) \
0074     BOOST_PP_IIF(BOOST_PP_IS_EMPTY( \
0075   BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITH_TYPE(bind_traits)), \
0076         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_DEDUCED_ \
0077     , \
0078         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_TYPED_ \
0079     )(r, BOOST_PP_TUPLE_ELEM(2, 0, id_typename), \
0080             BOOST_PP_TUPLE_ELEM(2, 1, id_typename), i, bind_traits)
0081 
0082 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAM_DECL_( \
0083         r, id_typename, i, bind_traits) \
0084     BOOST_SCOPE_EXIT_DETAIL_PARAM_DECL(r, \
0085             ( \
0086                 BOOST_PP_TUPLE_ELEM(2, 0, id_typename) \
0087             , \
0088                 /* ScopeExit expects typename or EMPTY() here */ \
0089                 BOOST_PP_EXPR_IIF(BOOST_PP_TUPLE_ELEM(2, 1, id_typename), \
0090                     typename \
0091                 ) \
0092             ), \
0093             i, BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0094                     bind_traits))
0095 
0096 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_MEMBER_DECL_VAR_( \
0097         r, id, typename01, i, var) \
0098     BOOST_PP_EXPR_IIF(typename01, typename) \
0099     BOOST_IDENTITY_TYPE(( /* must use IDENTITY because of tparam comma */ \
0100         ::boost::scope_exit::detail::member< \
0101               BOOST_SCOPE_EXIT_DETAIL_PARAM_T(id, i, var) \
0102             , BOOST_SCOPE_EXIT_DETAIL_TAG(id, i) \
0103         > \
0104     )) \
0105     BOOST_SCOPE_EXIT_DETAIL_PARAM(id, i, var);
0106 
0107 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_MEMBER_DECL_( \
0108         r, id_typename, i, bind_traits) \
0109     BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_MEMBER_DECL_VAR_(r, \
0110             BOOST_PP_TUPLE_ELEM(2, 0, id_typename), \
0111             BOOST_PP_TUPLE_ELEM(2, 1, id_typename), \
0112             i, BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0113                     bind_traits))
0114 
0115 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAM_INIT_(r, id, i, bind_traits) \
0116     BOOST_SCOPE_EXIT_DETAIL_PARAM_INIT(r, id, i, \
0117             BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_VAR_WITHOUT_TYPE( \
0118                     bind_traits))
0119 
0120 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \
0121     BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_capture_type)(id) )
0122 
0123 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) \
0124     BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_type)(id) )
0125 
0126 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_DEDUCED_( \
0127         id, typename01, all_bind_this_types) \
0128     BOOST_SCOPE_EXIT_DETAIL_TYPEDEF_TYPEOF_THIS(id, \
0129             BOOST_PP_EXPR_IIF(typename01, typename), /* otherwise EMPTY() */ \
0130             BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id))
0131 
0132 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_TYPED_( \
0133         id, typename01, all_bind_this_types) \
0134     typedef \
0135         BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_THIS_TYPE(BOOST_PP_LIST_FIRST( \
0136                 all_bind_this_types)) \
0137         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \
0138     ;
0139     
0140 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_( \
0141         id, typename01, all_bind_this_types) \
0142     /* typedef type_ */ \
0143     BOOST_PP_IIF(BOOST_PP_IS_EMPTY( \
0144             /* all_bind_this_type is list with 1 elem (possibly PP_EMPTY), */ \
0145             /* otherwise got a pp-parsing error before getting here */ \
0146             BOOST_LOCAL_FUNCTION_AUX_PP_BIND_TRAITS_THIS_TYPE( \
0147                     BOOST_PP_LIST_FIRST(all_bind_this_types))), \
0148         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_DEDUCED_ \
0149     , \
0150         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_TYPED_ \
0151     )(id, typename01, all_bind_this_types)
0152 
0153 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_ALL_( \
0154         all_binds, all_bind_this_types, id, typename01) \
0155     /* binding tags */ \
0156     BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \
0157         BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPEDEF_ \
0158     , \
0159         BOOST_PP_TUPLE_EAT(3) \
0160     )(id, typename01, all_bind_this_types) \
0161     BOOST_PP_LIST_FOR_EACH_I(BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_TAG_DECL_, id, \
0162             all_binds) \
0163     BOOST_PP_LIST_FOR_EACH_I(BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_CAPTURE_DECL_, \
0164             (id, typename01), all_binds) \
0165     /* binding class */ \
0166     struct BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id) { \
0167         /* interim capture types to workaround internal error on old GCC */ \
0168         BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \
0169             typedef BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_CAPTURE_TYPE_(id) \
0170                     BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) ; \
0171         ) \
0172         BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \
0173             BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id) \
0174             BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_VAR; \
0175         ) \
0176         BOOST_PP_LIST_FOR_EACH_I( \
0177                 BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAM_DECL_, \
0178                 (id, typename01), all_binds) \
0179         BOOST_PP_LIST_FOR_EACH_I( \
0180                 BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_MEMBER_DECL_, \
0181                 (id, typename01), all_binds) \
0182     } BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAMS_VAR_(id) = \
0183     /* NOTE: there is no way to wrap member initializer commas within */ \
0184     /* parenthesis so you must handle these commas manually if expanding */ \
0185     /* this macro within another macro */ \
0186     { \
0187         /* initialize the struct with param values to bind */ \
0188         BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(all_bind_this_types), \
0189                 this) /* here name `this` access object at enclosing scope */ \
0190         BOOST_PP_COMMA_IF(BOOST_PP_BITAND( \
0191               BOOST_PP_LIST_IS_CONS(all_bind_this_types) \
0192             , BOOST_PP_LIST_IS_CONS(all_binds) \
0193         )) \
0194         BOOST_PP_LIST_FOR_EACH_I( \
0195                 BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAM_INIT_, id, all_binds) \
0196     };
0197 
0198 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_(id, typename01, decl_traits) \
0199     /* IMPORTANT: the order of these appends is important, it must follow */ \
0200     /* the indexing order used by the functor code which starts */ \
0201     /* enumerating const binds and then non-const binds */ \
0202     BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_ALL_( \
0203             BOOST_PP_LIST_APPEND( \
0204                     BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_CONST_BINDS( \
0205                             decl_traits),\
0206                     BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_BINDS( \
0207                             decl_traits)), \
0208             BOOST_PP_LIST_APPEND( \
0209   BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_CONST_BIND_THIS_TYPES(decl_traits), \
0210                     BOOST_LOCAL_FUNCTION_AUX_PP_DECL_TRAITS_BIND_THIS_TYPES( \
0211                             decl_traits)), \
0212             id, typename01)
0213 
0214 // PUBLIC //
0215 
0216 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE(id, typename01) \
0217     BOOST_PP_EXPR_IIF(typename01, typename) \
0218     BOOST_SCOPE_EXIT_DETAIL_PARAMS_T(id):: \
0219             BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_TYPE_(id)
0220 
0221 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_THIS_VAR \
0222     BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (this_var) )
0223 
0224 #define BOOST_LOCAL_FUNCTION_AUX_CODE_BIND(id, typename01, decl_traits) \
0225     /* the binding data structures must be declared and initialized (to */ \
0226     /* empty structs, so hopefully the compiler will optimize away the */ \
0227     /* no-op code) even when there is no bound param because these structs */ \
0228     /* are used to init `...args.value` which is always used by the `END` */ \
0229     /* macro later because this macro does not know if there are bound */ \
0230     /* params or not */ \
0231     BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_(id, typename01, decl_traits) \
0232     /* this code takes advantage of the template argument list/comparison */ \
0233     /* operator ambiguity to declare a variable iff it hasn't already been */ \
0234     /* declared in that scope; the second occurrence is parsed as: */ \
0235     /*  (declared<(resolve<sizeof(boost_local_auxXargs)>::cmp1<0)>::cmp2> */ \
0236     /*      ...Xargs); */ \
0237     /* which is a no-op */ \
0238     ::boost::scope_exit::detail::declared< boost::scope_exit::detail::resolve< \
0239         /* cannot prefix with `::` as in `sizeof(:: ...` because the name */ \
0240         /* must refer to the local variable name to allow multiple local */ \
0241         /* functions (and exits) within the same scope (however this */ \
0242         /* does not allow for nesting because local variables cannot be */ \
0243         /* used in nested code blocks) */ \
0244         sizeof(BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR) \
0245     >::cmp1<0>::cmp2 > BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR; \
0246     /* stores bound types/values into `...args` variable (args variable */ \
0247     /* can be accessed by `NAME` macro because doesn't use __LINE__ id) */ \
0248     BOOST_LOCAL_FUNCTION_AUX_DECL_ARGS_VAR.value = \
0249             &BOOST_LOCAL_FUNCTION_AUX_CODE_BIND_PARAMS_VAR_(id);
0250 
0251 #endif // #include guard
0252