From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2006-11-20 02:29:36
Richard Smith wrote:
> Tobias Schwinger wrote:
>>Further: none of the reviewers (except Doug Gregor, who
>>was talking about the issue in the very specific context
>>of merger with another library) did answer the following
>> What's wrong with the tag types (other than personal
>>taste) in the first place?
> Having just read your other email, I think I now better
> understand why you want tags -- and why you don't want to go
> the traits route that I suggested.
> What I don't like about the current interface is that it
> seems to use an odd mixture of traits and tags. Let me try
> to explain.
> The library is supplying an interface to manipulate function
> types (and function pointer, function reference and member
> function pointer types). The two most obvious parts of a
> function type are the return type and the parameter types.
> These are queried via traits:
> result_type< Fn >::type
> mpl::at_c< parameter_types< Fn >, N >::type
> However, on top of this, there are other aspects: calling
> convention and variadic-ness (both of which are probably
> relatively rarely required), and cv-quals for member
> functions (which might be more frequently needed).
Yeah. But cv-qualification for member functions is usually dealt with in form of a qualified class type. The tags are just needed to overide the default -- and for cv-qualified function types (which by the current standard make a program ill-formed).
> are all handled by the tags mechanism.
> is_callable_builtin< Fn, variadic >::value
> (I'm assuming that is_callable_builtin returns true for
> functions, references, pointers and members.)
> Finally, there's exactly what sort of function type we're
> dealing with -- function, reference, pointer or member.
> These are handled by separate traits:
> is_function_reference< Fn >::value
> is_member_function_pointer< Fn >::value
> That's three (or four if you include the at_c usage to get
> the nth parameter, but let's not go there again) subtly
> different interfaces. I'm not concerned about the
> difference between ::type and ::value -- as I can put ::type
> in both cases and get a true_type or false_type.
> But that still leaves two different interfaces, which IMO is
> one too many. My traits suggestion removed one interface by
> ditching the tags, but it wasn't the tag interface that I
> disliked /per se/ -- it was the inconsistency.
> What if you went the other way and used an exclusively
> tag-based interface:
> namespace bft = boost::function_types;
> bft::get< int (), result_type >::type
> // int
> bft::get< int (), parameter_types >::type
> // an empty MPL sequence
> bft::get< void (int*, float), parameter_types >::type
> // an MPL sequence containing (int*, float)
> bft::get< void (int*, float), parameter_type<0> >::type
> // int* -- optional syntactic sugar
> bft::get< void (...), is_variadic >::type
> // true_type
> bft::get< void (...), is_variadic >::value
> // true
> bft::get< void (), is_default_cc >::type
> // true_type
> bft::get< void (*)(), is_pointer >::type
> // true_type
> etc... This is not very dissimilar to the existing
> is_callable_scalar metafunction, but with addition
> is_pointer, is_reference, etc... tags folded in.
I've been there. It's very close to the interface of the previous version.
The descisions towards the current design and against consistency were a matter of practicability:
<cite from yesterday's post>
I came to the conclusion that simple and straightforward client code is more important -- and it really did cost me quite an effort to let go of the nagging perfectionism about consistency for consistency's sake.
</cite from yesterday's post>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk