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 #if !BOOST_PP_IS_ITERATING
0009 #   ifndef BOOST_LOCAL_FUNCTION_AUX_FUNCTION_HPP_
0010 #       define BOOST_LOCAL_FUNCTION_AUX_FUNCTION_HPP_
0011 
0012 #       include <boost/local_function/config.hpp>
0013 #       include <boost/local_function/aux_/member.hpp>
0014 #       include <boost/call_traits.hpp>
0015 #       include <boost/typeof/typeof.hpp>
0016 #       include <boost/config.hpp>
0017 #       include <boost/preprocessor/iteration/iterate.hpp>
0018 #       include <boost/preprocessor/repetition/repeat.hpp>
0019 #       include <boost/preprocessor/repetition/enum.hpp>
0020 #       include <boost/preprocessor/punctuation/comma_if.hpp>
0021 #       include <boost/preprocessor/arithmetic/add.hpp>
0022 #       include <boost/preprocessor/arithmetic/sub.hpp>
0023 #       include <boost/preprocessor/arithmetic/inc.hpp>
0024 #       include <boost/preprocessor/control/iif.hpp>
0025 #       include <boost/preprocessor/cat.hpp>
0026 
0027 // PRIVATE //
0028 
0029 #define BOOST_LOCAL_FUNCTION_AUX_FUNCTION_THIS_FILE_ \
0030     "boost/local_function/aux_/function.hpp"
0031 
0032 // PUBLIC //
0033 
0034 #define BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC \
0035     BOOST_LOCAL_FUNCTION_AUX_SYMBOL( (init_call) )
0036 
0037 #define BOOST_LOCAL_FUNCTION_AUX_typename_seq(z, n, unused) \
0038     (typename)
0039 
0040 #define BOOST_LOCAL_FUNCTION_AUX_arg_type(z, arg_n, unused) \
0041     BOOST_PP_CAT(Arg, arg_n)
0042 
0043 #define BOOST_LOCAL_FUNCTION_AUX_arg_typedef(z, arg_n, unused) \
0044     typedef \
0045         BOOST_LOCAL_FUNCTION_AUX_arg_type(z, arg_n, ~) \
0046         /* name must follow Boost.FunctionTraits arg1_type, arg2_type, ... */ \
0047         BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(arg_n)), _type) \
0048     ;
0049 
0050 #define BOOST_LOCAL_FUNCTION_AUX_comma_arg_tparam(z, arg_n, unused) \
0051     , typename BOOST_LOCAL_FUNCTION_AUX_arg_type(z, arg_n, ~)
0052 
0053 #define BOOST_LOCAL_FUNCTION_AUX_arg_param_type(z, arg_n, comma01) \
0054     BOOST_PP_COMMA_IF(comma01) \
0055     typename ::boost::call_traits< \
0056         BOOST_LOCAL_FUNCTION_AUX_arg_type(z, arg_n, ~) \
0057     >::param_type
0058 
0059 #define BOOST_LOCAL_FUNCTION_AUX_arg_name(z, arg_n, comma01) \
0060     BOOST_PP_COMMA_IF(comma01) \
0061     BOOST_PP_CAT(arg, arg_n)
0062 
0063 #define BOOST_LOCAL_FUNCTION_AUX_arg_param_decl(z, arg_n, unused) \
0064     BOOST_LOCAL_FUNCTION_AUX_arg_param_type(z, arg_n, 0 /* no leading comma */)\
0065     BOOST_LOCAL_FUNCTION_AUX_arg_name(z, arg_n, 0 /* no leading comma */)
0066 
0067 #define BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, unused) \
0068     BOOST_PP_CAT(Bind, bind_n)
0069 
0070 #define BOOST_LOCAL_FUNCTION_AUX_comma_bind_type(z, bind_n, unused) \
0071     , BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~)
0072 
0073 #define BOOST_LOCAL_FUNCTION_AUX_comma_bind_ref(z, bind_n, unused) \
0074     , BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~) &
0075 
0076 #define BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam(z, bind_n, unused) \
0077     , typename BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~)
0078 
0079 #define BOOST_LOCAL_FUNCTION_AUX_bind_name(z, bind_n, unused) \
0080     BOOST_PP_CAT(bing, bind_n)
0081 
0082 #define BOOST_LOCAL_FUNCTION_AUX_comma_bind_param_decl(z, bind_n, unused) \
0083     , \
0084     BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~) & \
0085     BOOST_LOCAL_FUNCTION_AUX_bind_name(z, bind_n, ~)
0086     
0087 #define BOOST_LOCAL_FUNCTION_AUX_bind_member(z, bind_n, unsued) \
0088     BOOST_PP_CAT(BOOST_LOCAL_FUNCTION_AUX_bind_name(z, bind_n, ~), _)
0089 
0090 #define BOOST_LOCAL_FUNCTION_AUX_comma_bind_member_deref(z, bind_n, unsued) \
0091     , member_deref< BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~) >( \
0092             BOOST_LOCAL_FUNCTION_AUX_bind_member(z, bind_n, ~))
0093 
0094 #define BOOST_LOCAL_FUNCTION_AUX_bind_member_init(z, bind_n, unused) \
0095     BOOST_LOCAL_FUNCTION_AUX_bind_member(z, bind_n, ~) = member_addr( \
0096             BOOST_LOCAL_FUNCTION_AUX_bind_name(z, bind_n, ~));
0097 
0098 #define BOOST_LOCAL_FUNCTION_AUX_bind_member_decl(z, bind_n, unused) \
0099     /* must be ptr (not ref) so can use default constr */ \
0100     typename member_type< \
0101         BOOST_LOCAL_FUNCTION_AUX_bind_type(z, bind_n, ~) \
0102     >::pointer BOOST_LOCAL_FUNCTION_AUX_bind_member(z, bind_n, ~) ;
0103 
0104 #define BOOST_LOCAL_FUNCTION_AUX_call_ptr(z, n, unused) \
0105     BOOST_PP_CAT(call_ptr, n)
0106 
0107 #define BOOST_LOCAL_FUNCTION_AUX_call_name(z, n, unused) \
0108     BOOST_PP_CAT(call, n)
0109 
0110 #define BOOST_LOCAL_FUNCTION_AUX_call_member(z, n, unused) \
0111     BOOST_PP_CAT(BOOST_LOCAL_FUNCTION_AUX_call_name(z, n, unused), _)
0112 
0113 #define BOOST_LOCAL_FUNCTION_AUX_call_typedef(z, n, arity) \
0114     typedef R (*BOOST_LOCAL_FUNCTION_AUX_call_ptr(z, n, ~))( \
0115         object_ptr \
0116         BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS, \
0117             BOOST_PP_TUPLE_EAT(3) \
0118         , \
0119             BOOST_PP_REPEAT_ ## z \
0120         )(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, \
0121                 BOOST_LOCAL_FUNCTION_AUX_comma_bind_ref, ~) \
0122         BOOST_PP_REPEAT_ ## z(BOOST_PP_SUB(arity, n), \
0123                 BOOST_LOCAL_FUNCTION_AUX_arg_param_type, 1 /* leading comma */)\
0124     );
0125 
0126 #define BOOST_LOCAL_FUNCTION_AUX_comma_call_param_decl(z, n, unused) \
0127     , \
0128     BOOST_LOCAL_FUNCTION_AUX_call_ptr(z, n, ~) \
0129     BOOST_LOCAL_FUNCTION_AUX_call_name(z, n, ~)
0130 
0131 #define BOOST_LOCAL_FUNCTION_AUX_call_decl(z, n, unused) \
0132     BOOST_LOCAL_FUNCTION_AUX_call_ptr(z, n, ~) \
0133     BOOST_LOCAL_FUNCTION_AUX_call_member(z, n, ~);
0134 
0135 #define BOOST_LOCAL_FUNCTION_AUX_call_init(z, n, unused) \
0136     BOOST_LOCAL_FUNCTION_AUX_call_member(z, n, ~) = \
0137             BOOST_LOCAL_FUNCTION_AUX_call_name(z, n, ~);
0138                 
0139 #define BOOST_LOCAL_FUNCTION_AUX_operator_call(z, defaults_n, arity) \
0140     /* precondition: object_ && call_function_ */ \
0141     inline R operator()( \
0142         BOOST_PP_ENUM_ ## z(BOOST_PP_SUB(arity, defaults_n), \
0143                 BOOST_LOCAL_FUNCTION_AUX_arg_param_decl, ~) \
0144     ) /* cannot be const because of binds (same as for local ftor) */ { \
0145         /* run-time: do not assert preconditions here for efficiency */ \
0146         /* run-time: this function call is done via a function pointer */ \
0147         /* so unfortunately does not allow for compiler inlining */ \
0148         /* optimizations (an alternative using virtual function was also */ \
0149         /* investigated but also virtual functions cannot be optimized */ \
0150         /* plus they require virtual table lookups to the alternative */ \
0151         /* performed worst) */ \
0152         return BOOST_LOCAL_FUNCTION_AUX_call_member(z, defaults_n, ~)( \
0153             object_ \
0154             BOOST_PP_IIF( \
0155                     BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,\
0156                 BOOST_PP_TUPLE_EAT(3) \
0157             , \
0158                 BOOST_PP_REPEAT_ ## z \
0159             )(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX, \
0160                     BOOST_LOCAL_FUNCTION_AUX_comma_bind_member_deref, ~) \
0161             BOOST_PP_REPEAT_ ## z(BOOST_PP_SUB(arity, defaults_n), \
0162                     BOOST_LOCAL_FUNCTION_AUX_arg_name, 1 /* leading comma */) \
0163         ); \
0164     }
0165 
0166 namespace boost { namespace local_function { namespace aux {
0167 
0168 template<
0169       typename F
0170     , size_t defaults
0171 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0172     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0173             BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam, ~)
0174 #endif
0175 >
0176 class function {}; // Empty template, only use its specializations.
0177 
0178 // Iterate within namespace.
0179 #       define BOOST_PP_ITERATION_PARAMS_1 \
0180                 (3, (0, BOOST_LOCAL_FUNCTION_CONFIG_FUNCTION_ARITY_MAX, \
0181                 BOOST_LOCAL_FUNCTION_AUX_FUNCTION_THIS_FILE_))
0182 #       include BOOST_PP_ITERATE() // Iterate over function arity.
0183 
0184 } } } // namespace
0185 
0186 // Register type for type-of emu (NAME use TYPEOF to deduce this fctor type).
0187 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
0188 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::local_function::aux::function,
0189     (typename) // For `F` tparam.
0190     (size_t) // For `defaults` tparam.
0191     // MSVC error if using #if instead of PP_IIF here.
0192     BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS,
0193         BOOST_PP_TUPLE_EAT(3) // Nothing.
0194     ,
0195         BOOST_PP_REPEAT // For bind tparams.
0196     )(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0197             BOOST_LOCAL_FUNCTION_AUX_typename_seq, ~)
0198 )
0199 
0200 #undef BOOST_LOCAL_FUNCTION_AUX_typename_seq
0201 #undef BOOST_LOCAL_FUNCTION_AUX_arg_type
0202 #undef BOOST_LOCAL_FUNCTION_AUX_arg_typedef
0203 #undef BOOST_LOCAL_FUNCTION_AUX_comma_arg_tparam
0204 #undef BOOST_LOCAL_FUNCTION_AUX_arg_param_type
0205 #undef BOOST_LOCAL_FUNCTION_AUX_arg_name
0206 #undef BOOST_LOCAL_FUNCTION_AUX_arg_param_decl
0207 #undef BOOST_LOCAL_FUNCTION_AUX_bind_type
0208 #undef BOOST_LOCAL_FUNCTION_AUX_comma_bind_type
0209 #undef BOOST_LOCAL_FUNCTION_AUX_comma_bind_ref
0210 #undef BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam
0211 #undef BOOST_LOCAL_FUNCTION_AUX_bind_name
0212 #undef BOOST_LOCAL_FUNCTION_AUX_comma_bind_param_decl
0213 #undef BOOST_LOCAL_FUNCTION_AUX_bind_member
0214 #undef BOOST_LOCAL_FUNCTION_AUX_comma_bind_member_deref
0215 #undef BOOST_LOCAL_FUNCTION_AUX_bind_member_init
0216 #undef BOOST_LOCAL_FUNCTION_AUX_bind_member_decl
0217 #undef BOOST_LOCAL_FUNCTION_AUX_call_ptr
0218 #undef BOOST_LOCAL_FUNCTION_AUX_call_name
0219 #undef BOOST_LOCAL_FUNCTION_AUX_call_member
0220 #undef BOOST_LOCAL_FUNCTION_AUX_call_typedef
0221 #undef BOOST_LOCAL_FUNCTION_AUX_comma_call_param_decl
0222 #undef BOOST_LOCAL_FUNCTION_AUX_call_decl
0223 #undef BOOST_LOCAL_FUNCTION_AUX_call_init
0224 #undef BOOST_LOCAL_FUNCTION_AUX_operator_call
0225 
0226 #   endif // #include guard
0227 
0228 #elif BOOST_PP_ITERATION_DEPTH() == 1
0229 #   define BOOST_LOCAL_FUNCTION_AUX_arity BOOST_PP_FRAME_ITERATION(1)
0230 #   define BOOST_PP_ITERATION_PARAMS_2 \
0231             (3, (0, BOOST_LOCAL_FUNCTION_AUX_arity, \
0232             BOOST_LOCAL_FUNCTION_AUX_FUNCTION_THIS_FILE_))
0233 #   include BOOST_PP_ITERATE() // Iterate over default params count.
0234 #   undef BOOST_LOCAL_FUNCTION_AUX_arity
0235 
0236 #elif BOOST_PP_ITERATION_DEPTH() == 2
0237 #   define BOOST_LOCAL_FUNCTION_AUX_defaults BOOST_PP_FRAME_ITERATION(2)
0238 
0239 template<
0240     typename R
0241     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_AUX_arity,
0242             BOOST_LOCAL_FUNCTION_AUX_comma_arg_tparam, ~)
0243 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0244     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0245             BOOST_LOCAL_FUNCTION_AUX_comma_bind_tparam, ~)
0246 #endif
0247 >
0248 class function<
0249       R (
0250         BOOST_PP_ENUM(BOOST_LOCAL_FUNCTION_AUX_arity,
0251                 BOOST_LOCAL_FUNCTION_AUX_arg_type, ~)
0252       )
0253     , BOOST_LOCAL_FUNCTION_AUX_defaults
0254 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0255     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0256             BOOST_LOCAL_FUNCTION_AUX_comma_bind_type, ~)
0257 #endif
0258 > {
0259     // The object type will actually be a local class which cannot be passed as
0260     // a template parameter so a generic `void*` pointer is used to hold the
0261     // object (this pointer will then be cased by the call-function implemented
0262     // by the local class itself). This is the trick used to pass a local
0263     // function as a template parameter. This trick uses function pointers for
0264     // the call-functions and function pointers cannot always be optimized by
0265     // the compiler (they cannot be inlined) thus this trick increased run-time
0266     // (another trick using virtual functions for the local class was also
0267     // investigated but also virtual functions cannot be inlined plus they
0268     // require virtual tables lookups so the virtual functions trick measured
0269     // worst run-time performance than the function pointer trick).
0270     typedef void* object_ptr;
0271     BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_LOCAL_FUNCTION_AUX_defaults),
0272             BOOST_LOCAL_FUNCTION_AUX_call_typedef, // INC for no defaults.
0273             BOOST_LOCAL_FUNCTION_AUX_arity)
0274 
0275 public:
0276     // Provide public type interface following Boost.Function names
0277     // (traits must be defined in both this and the local functor).
0278     BOOST_STATIC_CONSTANT(size_t, arity = BOOST_LOCAL_FUNCTION_AUX_arity);
0279     typedef R result_type;
0280     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_AUX_arity,
0281             BOOST_LOCAL_FUNCTION_AUX_arg_typedef, ~)
0282 
0283     // NOTE: Must have default constructor for init without function name in
0284     // function macro expansion.
0285 
0286     // Cannot be private but it should never be used by programmers directly
0287     // so used internal symbol.
0288     inline void BOOST_LOCAL_FUNCTION_AUX_FUNCTION_INIT_CALL_FUNC(
0289         object_ptr object
0290 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0291         BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0292                 BOOST_LOCAL_FUNCTION_AUX_comma_bind_param_decl, ~)
0293 #endif
0294         BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_LOCAL_FUNCTION_AUX_defaults),
0295                 BOOST_LOCAL_FUNCTION_AUX_comma_call_param_decl, ~)
0296     ) {
0297         object_ = object;
0298 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0299         BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0300                 BOOST_LOCAL_FUNCTION_AUX_bind_member_init, ~)
0301 #endif
0302         BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_LOCAL_FUNCTION_AUX_defaults),
0303                 BOOST_LOCAL_FUNCTION_AUX_call_init, ~) // INC for no defaults.
0304         unused_ = 0; // To avoid a GCC uninitialized warning.
0305     }
0306     
0307     // Result operator(Arg1, ..., ArgN-1, ArgN) -- iff defaults >= 0
0308     // Result operator(Arg1, ..., ArgN-1)       -- iff defaults >= 1
0309     // ...                                      -- etc
0310     BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_LOCAL_FUNCTION_AUX_defaults),
0311             BOOST_LOCAL_FUNCTION_AUX_operator_call, // INC for no defaults.
0312             BOOST_LOCAL_FUNCTION_AUX_arity)
0313 
0314 private:
0315     object_ptr object_;
0316 #if !BOOST_LOCAL_FUNCTION_CONFIG_LOCALS_AS_TPARAMS
0317     BOOST_PP_REPEAT(BOOST_LOCAL_FUNCTION_CONFIG_BIND_MAX,
0318             BOOST_LOCAL_FUNCTION_AUX_bind_member_decl, ~)
0319 #endif
0320     BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_LOCAL_FUNCTION_AUX_defaults),
0321             BOOST_LOCAL_FUNCTION_AUX_call_decl, ~) // INC for no defaults.
0322 
0323     // run-time: this unused void* member variable allows for compiler
0324     // optimizations (at least on MSVC it reduces invocation time of about 50%)
0325     void* unused_;
0326 };
0327 
0328 #   undef BOOST_LOCAL_FUNCTION_AUX_defaults
0329 #endif // iteration
0330