Re: [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: > David Abrahams wrote: > >> [Aleksey, please see below w.r.t. lambda exprs] >> Daniel Wallin <[email protected]> writes: >> >>>David Abrahams wrote: >>> >>>>Daniel Wallin <[email protected]> writes: >>>> >>>>What does the first element of the vector mean? Oh, looking back at >>>>your previous message that's a *very* strange ordering! Why would you >>>>put the return type *second*?! >>> >>>The ordering was arbitrary. Well, sort of at least. The reason was to >>>keep the indexing consistent. A member function signature is the same as >>>a function signature, except it has the self-type at index 0. So the >>>index to some type in the signature is just offset one step. I don't >>>know if it matters though. :) >> Errf. I think of these two as equivalent: >> A f(B*, C, D, E) >> A B::f(C, D, E) >> And they *are* equivalent as far as Boost.Python is concerned, >> except >> at the last second when the C++ function is invoked and we have to do >> some syntactic adjustment to account for the difference between >> member and non-member functions. I don't see any reason to drag the >> B* to the beginning of the signature. > > Good point. > >>>>I'm not sure whether what you're suggesting above actually does the >>>>right thing. In fact, I'm almost certain it doesn't. You need the >>>>most_derived hook used in signature.hpp. The idea is, "downcast if >>>>you can, otherwise leave it alone". >>> >>>I had a look in signature.hpp. I'm not sure I understand this though; >>>Target is not more derived than T => Target == T, no? Or is Target >>>something else than the current WrappedClass type? >> Well, this should probably be done for non-member functions as well, >> but... >> suppose someone does this: >> [snip code] >> That should show why the most_derived thing is there. > > OK, I had no idea you could do that. I can see why you would need > most_derived there. I'm not sure I can see why anyone would do > something like that though, but I haven't given it much thought. :) Run the following: #include <typeinfo> #include <stdio.h> struct B { void f() {} }; struct D : B {}; int main() { printf(typeid(&D::f).name()); return 0; } "Like what?" Did you mean, why anyone would want to use a member function on some non-base class as a staticmethod? It doesn't really matter; they could be free functions: struct Base // not wrapped { }; void f(Base*); struct Baz // wrapped { }; void g(Baz*); struct Derived : Base // wrapped {}; class_<Derived>("Derived") .def("f", &Base::f) .def("g", &Baz::g) .staticmethod("g") ; >>> d = Derived() >>> d.f() >>> d.g(Baz()) >>>>I have no problem in principle (I think) with bidirectional >>>>converter *generators*, but bidirectional converters won't work. They >>>>need completely different data members, and from-XXX converters need >>>>to be 2-phase for overloading, while to-XXX converters are one >>>>phase. In other words, I have no problem with: >>>>[snip] >>> >>>OK agreed. So, should the nested member be a metafunction class? >>> >>> some_generator >>> { >>> typedef /* to converter */ to; >>> typedef /* from converter */ from; >>> }; >> Well, it can be more efficient than using any generalized lambda >> expr, >> but it's also more work for the user. AFAIK MPL is going to change so >> that apply<...> uses lambda<...> internally, but I guess there would >> always be a lower-level apply_metafunction_class<...> for efficiency. >> Even though we've written about that in our book, it's not implemented >> yet. Aleksey, care to comment? > > OK. How would you apply<> to a nested metafunction? By turning them into > lambda-types? Yep. > Or is it safe (portable) to do > > typedef typename generator::template to<T, Index>::type cv_t; > > I know I've had a lot of problems with that syntax on VC before. Yep, not very portable. That's why to use apply<...>. >>>How could the converter_tuple_generator know which types should be >>> "to" and which should be "from"? >> If you use a consistent signature ordering as I'm suggesting, it's >> easy. To for the first and from for the rest. > > Yeah, that would work fine. But I'm not sure I like it. How does it > apply to explicit conversions? (object_cast<> / extract<>). I had > thought that we'd handle these cases by just supplying a vector1<T> > signature sequence.. vector2<T,object> // from-XXX or vector2<object,T> // to-XXX Simple ;-) > But we could tell the policy to generate the converter explicitly > instead of using generate_converter_tuple<>.. I'm not sure what I > think about this. Not sure what you're driving at here. >>>No I think the children are CallPolicies as well - they should have >>>precall/postcall actions. >>> >>>I'm not sure what you mean by index-agnostic. >> >> I think I'm just forgetting stuff you already convinced me of, but >> what I meant was that the others are only really concerned with >> converting a single argument and so don't need an index, while the >> CallPolicies are concerned with the whole argument tuple. But I >> think we agreed they all need the index. > > Yeah I think we did. I guess most of "the others" will likely just > ignore the index though, provided that the index is passed to the > converter later. > > struct my_cv; > my_cv cv; > cv.from(..., mpl::int<2>()); > > vs > > template<int N> > struct my_cv; > my_cv<2> cv; > cv.from(...); Do we want to pass the index into the converter later? I don't think we do. Seems to me that you might want some converters to, ultimately, work on several indices. Maybe I'm wrong. >>>BTW, if you implement the composite CallPolicies like you have in BPL >>>there is no reason why offset_arg couldn't store it's Base. That's of >>>course a perfectly fine model of CallPolicies as well. >>>composite_call_policies is just an example of how it can be done without >>>explicit inheritance from your "Base policy". >> I think you can also get there by having the names that the user >> handles >> some_policyA(_1) >> ^^^^^^^^^^^^ >> refer to instances of some concept other than CallPolicies which can >> generate CallPolicies. Not sure what's best yet. > > I think it's best to allow both approaches. It strikes me that the user isn't handling call policy names anyway, because, 1. In "policyA(_1)", policyA can't be type name. 2. policyA(_1) and policyA(_2) have to generate different types. -- Dave Abrahams Boost Consulting www.boost-consulting.com ------------------------------------------------------- This SF. Net email is sponsored by: GoToMyPC GoToMyPC is the fast, easy and secure way to access your computer from any Web browser or wireless device. Click here to Try it Free! https://www.gotomypc.com/tr/OSDN/AW/Q4_2003/t/g22lp?Target=mm/g22lp.tmpl