From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2005-06-19 14:39:01


Hi Dave,

David Abrahams wrote:
>
> I can only explain the reasons I chose a reference and not a pointer
> in the context of Boost.Python: pointers can be null, but references
> cannot, and you can never call a member function on a null pointer.
>

We have to start a "bit further above" ;-).

If we want to unify parameters and class type we have to either use a reference
or a pointer to it for things to make sense.
The by-value case (operator() member of a simple functor) is too unusual to make
sense in general.

I also agree, that a reference is the more reasonable default.

Further, it is attractive to have a reference (as opposed to a value) in the
sequence because (e.g):

     // Let t be a variable of type T and some
     // T be some (member) function pointer/reference type
     function< typename function_type<plain_function,T>::type > x = t;
     // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     // "rebinds" the subtypes of T to a plain_function

will just work.

I still don't think it is good to hard-wire this, though.

If I understand your case correctly, you want remove const qualification of the
class type (which are not there, currently - but planned):

     typename add_reference
     < typename remove_cv
        < typename remove_reference
           < typename function_type_class<T>::type
             // or typename at_c<sig,1>::type
>::type
>::type
>::type

Slightly better for those who want a pointer:

     typename add_pointer
     < typename remove_reference
       < typename function_type_class<T>::type
         // or typename at_c<sig,1>::type
>::type
>::type

So I believe it is perhaps best to parametrize the decoartion we want on the
class type:

Sidenote: I'm not entirely sure on the MPL-Lamda expression - we could also use
some kind of tag type or an enum, I guess. Or we use MPL-Lambda exressions, but
only evaluate them as a fallback when there is no optimized specialization, as
for add_reference<_>, add_pointer<_> and identity<_> (maybe even one to create
an unqualified reference for the Boost.Python case). Thoughts welcome.

     template<typename T, typename ClassDecoration = add_reference<_> >
     struct function_type_signature;

     template<typename T, typename ClassDecoration = add_reference<_> >
     struct function_type_class;

And if we want to add a unified one:

     template<typename T, typename ClassDecoartion = add_reference<_> >
     struct function_type_effective_parameters;

(Jonathan Turkanis has suggested adding one like this. He also came up with
"effective" for the name, which I happen to like).

And perhaps even:

     template<typename Tag, typename TypeOrTypes,
              typename ClassDecoartion = add_reference<_> >
     struct function_type;
     // ignores it, unless it specializes function_type_signature

Revisiting the example from above we could say:

     function< typename function_type<plain_function,T,add_pointer<_> >::type >

And easily even use our favourite proxy, e.g. a smart pointer...

Hoping to get a clear image on how the optimal synopsis of the library has to
look like, I'm looking forward to read your comments.

Thanks,

Tobias