
Surely you can always just declare your function type as a typedef in that case, without going through function_type?
Yeah, but only for fixed arity. It's not neccessarily the case in every context:
template<class F,class T> action make_action(F functor, T& tuple) { // takes address of templated and/or overloaded F::operator() }
OK I can see that.
For parameters only there is 'function_type_parameters<T>' ....
Missed that, thanks.
Let's try to use separate data sources, reduce the complexity and the number of mpl components needed:
( Sorry, I couldn't resist, the previous one was too bad to leave it alone ;-) )
template < typename FunctionType , typename ClassTypeTransform = add_reference<_1> > struct forward_signature : function_type < plain_function , mpl::joint_view < typename mpl::apply1 < mpl::if_ < is_function_type<member_function_pointer,_1> , mpl::vector2 < function_type_result<_1> , mpl::apply1 < typename mpl::lambda<ClassTypeTransform>::type , function_type_class<_1> > > , mpl::vector1< function_type_result<_1> > > , FunctionType >::type , mpl::transform_view < typename function_type_parameters<FunctionType>::type , param_type<_> > > > { };
OK, that one is more comprehensible now :-)
I can see that argument for decomposing the arity, I'm less sure about the others, I've got no imagination I guess ;-)
Let's try a simple example:
Writing a wrapper functor like 'boost::mem_fn' on top of this library we'ld use
template<typename MemFnPtr> mem_fn_functor<MemFnPtr> mem_fn(MemFnPtr member_function_pointer);
to let the library handle all the cv, cdecl, ellipsis stuff for us. This way deduction doesn't hand us all parameters. We'll need them to build up the operator() member in the functor, though.
Right, it's how you build up the operator() that I'm stuck on, I can see how you can generate the required signature, and you can use that to *declare* the right operator, but how do you then implement the body of the function when you don't know how many parameters there are? Sorry if I'm being dense!
One thing I've been meaning to look into, but haven't had the time yet: how do you handle __stdcall/__fastcall etc?
There is a configuration table that defines which ones to use (see below for an example).
Last time I tried to write partial specialisations that would select function types with specific calling
Because of ODR ?
No just couldn't get it to work reliably, maybe I didn't try hard enough, I was in a rush at the time...
Simple: in case custom calling conventions are configured, the default one is assumed (the first row in the table) to be among them (so there is no specialization without explicit attributation, then).
I saw the mention in the docs, but I suspect most users won't be familiar with the preprocessing library and how to set this up. An example would help a great deal (I suspect most folks will just cut and paste the example in any case). In fact if the code is robust enough (no idea if it is as I haven't had a chance to test it), I would favour enabling support for all the VC calling conventions by default for that compiler, and adding a separate preprocessed header for that one as well.
conventions I couldn't get it to work. There's also the horrible __thiscall thing: you can't explicitly declare a member function pointer type with __thiscall, but it is usually (but not always) the default, so whether or
Even worse:
int(X::*)(int) <=> int( "__thiscall" X::*)(int) int(X::*)(...) <=> int( __cdecl X::*)(...)
This is why you can configure, whether a calling convention should support variadic functions or not.
Yep, good.
So a suitable configuration would be to have an "explicit" thiscall calling convention with an empty attributation modifier, not allowing variadic functions.
[ ATTENTION: Not a valid configuration (see below) ]
#define BOOST_FT_CALLING_CONVENTIONS \ /*---------------------------------------*/ \ /* name | modifier \ allows '...' */ \ /*------------|------------\-------------*/ \ /* [ non-member or static function ] */ \ ( (( defaultcall, - , 1 )) \ /* [ member function pointers ] */ \ , (( defaultcall, - , 1 )) \ (( thiscall , , 0 )) \ (( cdecl , __cdecl , 1 )) )
The only problem left, is that the preprocessing code will need a minor adjustment, so a cell can be marked as explicitly empty (the table above can't be safely handled by the preprocessor)...
Right, but ideally you would also really need to be able to detect whether __thiscall is indeed the default, or if a command line switch has overridden it.
...and (this one won't go away unless Microsoft implements __thiscall in their frontend, too) that we may have to reconfigure the library when messing with the default calling convention.
Setting the default to '__cdecl' in this particular would cause an ODR violation.
I know, this whole area of that compiler is a real pain. Thanks for the response. John.