$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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