Boost logo

Boost :

From: John Maddock (john_at_[hidden])
Date: 2005-06-18 07:00:52


>> 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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk