Re: [C++-sig] [Implementation] Calling wrapped functions, converters, policies
David Abrahams <[email protected]>
| Newsgroups | gmane.comp.lib.boost.langbinding |
|---|---|
| Message-ID | <[email protected]> |
Daniel Wallin <[email protected]> writes: > Sounds good. I actually wrote something like this yesterday morning, except > I used the ConverterGenerator type instead of a nested type and I didn't > think about passing the entire state tuple to the converters. > > typename context_type<Policies>::type context(policies); > > typedef typename find_converter_generator<Policies, 1>::type c1_gt; > typename c1_gt::template apply<T0, xxx_to_cpp>::type c1; > > typedef typename find_converter_generator<Policies, 2>::type c2_gt; > typename c2_gt::template apply<T1, xxx_to_cpp>::type c2; > > context.precall(params); > > c1.convert(params[0], context.get((c1_gt*)0)); > c2.convert(params[1], context.get((c2_gt*)0)); > ^^^^^^^^^^^^^^^^^ > context.postcall(params); I've been thinking of something a little bit different. See below. > Anyway, this seems great. Perhaps the requirements on > ConverterGenerators/CallPolicies > can be quite loose too; > > May or may not contain a 'state' typedef. > - has_xxx > > The state typedef may or may not be a mpl sequence. > - is_sequence Bad idea, IMO. Not all compilers support has_xxx, defaults (e.g. typedef mpl::vector0 state) are easy to come by through inheritance, and every metafunction invocation has a cost in compile time. I'd rather just establish a simple set of requirements. Now, I know you've been thinking about things from the level of policy composition by putting together things like adopt(_1,_2) + release(_4) or whatever syntax it is that you use. I support using that sort of construct, but I want to look at things from the low-level implementation perspective of the invocation of the wrapped entity for a moment. One thing I discovered in trying to wrap factory functions as constructors is that converters need access to the whole incoming argument list, because the converter for parameter N of the called function really needs to operate on parameter N+1 of the input (the initial "self" argument is dropped). I believe this is also the way per-argument (or rather, per-converter) precall actions should be handled - converters can just do the precall action in their convert() functions. The only capability lost from the current precall protocol is the ability to fail overload resolution at that point, but I've only ever used precall for one thing, and it never needed to fail overload resolution so I don't believe it's important. I'd like to see a templated protocol to access the actual argument list, e.g.: get<1>(args) -> "argument 1" we'd define a get<> which operates on PyObject* (argument tuples) but we could also wrap the argument tuple in a kind of mapping to drop the first argument (or inject a faux argument, in the case of an out parameter which doesn't actually appear in the incoming argument list). For handling lone conversions (like extract<T>(obj)) we could wrap a single PyObject* (argument) in a class for which only get<0>(x) (but not get<1>, get<2>,...) was defined. There may yet be reasons to include in the argument package the ability to access a keyword dictionary. So at the lowest level, we have: - an invocable entity (a function pointer/reference, function object, member function pointer, or possibly data member pointer, for getters/setters) - a tuple of argument/result converters - a shared, per-call state object - an argument package. - as a matter of implementation detail, for dispatching to the right calling overload, I believe we'll need: - a tag which describes how to do the invocation (function call syntax, member function syntax, data member access/assignment) - a tag which says whether the invocable entity's return type is void - a tag which describes the arity of the tuple of converters These can probably be combined into a single integral constant wrapper for efficiency. Above that level, we need: - a way to deduce the signature of some callable objects like function pointers - a way to combine the signature of the callable object (either deduced or supplied explicitly) with the CallPolicies to produce the tuple type of argument/result converters - a way to combine the CallPolicies with the ArgumentPackage to produce a shared, per-call state type/object - a way to initialize an object of the arg/result converter tuple type with the shared, per-call state object and argument package (or we could combine the argument package into the shared, per-call state). At the top level, we need: - A way to get the ArgumentPackage from the actual arguments passed. Anything I'm missing? Your thoughts? -- Dave Abrahams Boost Consulting www.boost-consulting.com ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf