
Larry Evans <cppljevans <at> suddenlink.net> writes:
The test driver code:
http://preview.tinyurl.com/2a9dlun
tests something similar; however, it doesn't use fusion::vector to store the argument references. Instead it uses:
template<typename... ArgTypes> struct void_ptr_array { void* my_ptrs[sizeof...(ArgTypes>; ... };
The void* are cast to whatever the ArgTypes indicate the actual variables types happen to be.
Ok, I think I got the idea. In the current implementation, I wanted the types qualified and avoiding "void*". So I can also perform compile-time checks on the consistency of the convertors available.
However, I'm not sure that's completely portable. OTOH, one advantage, at least I think, is that the abstract args and their corresponding concrete values can be stored (or at least pointers to them) in the same memory locations by just changing the ArgTypes... .
If possible, reference to initial objects are stored. If not, a holder creates an appropriate temporary type during the call. This temporary is then reconverted to the interface type at the end of the call, if the interface type is a non-const ref, or the convertor tells that the matching needs a back-conversion. So similar types (trivial conversion) for instance will not be copied or dereferenced at all. Same for the conversion from a base class to a daughter class.
FWIW, I did try using a fusion container; however, I was using one container for the abstract args, and another for the concrete args, and pop_front'ing from the abstract arg container while push_backing to the concrete arg container, which I thought was a bit of a waste.
In fact, there is a bit of indirection in my implementation. The fusion container I use stores the interface parameters. The other container is an mpl sequence since there is no value associated to it before the call to the function. In fact, I create a fusion sequence of "convertor_wrapper", each having an implicit conversion to the template argument type and a special destructor. The implicit conversion calls the underlying convertor. These conversions are made if and only if all the convertor_wrapper in the chain of conversion are able to return a value corresponding to the template argument, otherwise no conversion is performed. I use for that "fusion::invoke", with the sequence of convertor_wrappers. I think this is quite ok for the portability, since it only involves the implicit cast operators of each convertor_wrapper (I tested it on MSVC 2008Expr, GCC 4.01 & GCC 4.4.1).
Anyway, the dispatching code in reify_apply.hpp:
http://preview.tinyurl.com/2ah2kpx
can be used for either a variant type structure (like that in:
variadic_templates/boost/composite_storage/pack/container_one_of_maybe.hpp ) by using reifier_switch.hpp,
or one with virtual functions to do the dispatching, like in the visitor pattern, as done with reifier_visitor.hpp.
I will have a look at this code soon !
The test driver uses either one based on the value of the REIFIER_VISITOR macro.
It differs from the apply_visitor in that it can be used for any number of arguments, since sizeof...(ArgTypes) can be any number.
What maybe different from your method, I think, is suggested by:
The dispatch_object tests for the convertibility of each instance ui of the arguments Ui of the interface function, with the corresponding argument Ti of the template function.
I think that job is done by the:
apply_ftor_check_args
in apply_unpack.hpp.
Almost, but not exactly. For instance line 83 of apply_unpack.hpp: typename function_types:: can_be_called<Functor(Args const&...)>::type is_ftor_args_callable; The fact is that the Functor itself is not always directly callable with the Args, and there is two sequences of Args that should be considered: the one for the interface and the other for the arguments of the template function. So the level of indirection induced by the convertors mentioned earlier should be considered. For instance a base class pointer to a derived class reference (again... :) ). All these logics are embedded in the convertors, defined for each pair of types (interface, concrete), which make it very easy to extend to new types.
I think mabye what you mean by:
It also includes a "back conversion" for Ui's that are non-const reference or pointers.
is done by the:
arg_type*ap=static_cast<arg_type*>(vp); return *ap;
in void_ptr_array::project in replace_source_with_target_ptr.hpp.
-regards, Larry
So here again, I think there is a need for an indirection level. The conversion is not always static (std::map& to variant& for instance). But maybe I missed some point ? Thanks for your feedback ! Regards, Raffi