Boost logo

Boost :

Subject: Re: [boost] [result_of] Usage guidelines
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-09-08 11:31:36


On Sat, Sep 8, 2012 at 6:59 AM, Andrey Semashev
<andrey.semashev_at_[hidden]>wrote:

> On Tuesday 04 September 2012 11:07:39 you wrote:
> >
> > Jeffrey have suggested a good solution in his reply. I think it can be
> > described in the result_of docs to resolve the confusion in the future. I
> > can update the docs if noone objects.
>
> I've added a clarification note to the result_of docs in trunk. Here is the
> added section:
>
> <quote>
> The result template must be specialized for every valid calling signature
> of
> the function object. If the operator() accepts arguments by (possibly
> const)
> reference and/or is const qualified,

My first pass over this read the "const qualified" as applying to the
arguments to operator(), but it actually applied to operator() itself. That
indicates that it may be good to reword to clarify.

> the result specialization must take this
> into account. Type traits and more generic specializations may help to
> reduce
> the number of result specializations.

On a second reading through, I think something like the following may be a
bit clearer:

--------
The result template should be specialized to account for all possible valid
call signatures of the function object, including any const-qualification
of the function object itself as well as reference- or
reference-to-const-qualifications of the argument types. One may infer the
set of valid call signatures based on what combinations of (possibly
reference- or reference-to-const-qualified) arguments are accepted by the
set of operator() overloads. Type trait metafunctions (such as
Boost.TypeTraits' remove_const [linked(?)] and remove_reference
[linked(?)]) and appropriate specializations can often reduce the number of
result template specializations to a minimum while ensuring that all valid
call signatures are covered.
--------

Hmmm...actually, the more I'm reading your original paragraph, the more
it's really saying the same thing as above, just with more words, so I
don't know what was unclear to me before. Take from what I wrote above what
you think might be appropriate (if anything) without complicating things
too much.

This way result_of users will be able to
> specify argument types exactly according to the function object call
> expression. For example:
>
> struct functor {
> template<class> struct result;
>
> // Use template parameter F to match the function object. This will
> allow result deduction for both const and non-const functor.
> template<class F, class T>
> struct result<F(T)> {
> // When argument type is matched like above, remember that the
> type may be a (const-qualified) reference.
> // Use type traits to transform the argument type.
> typedef typename remove_cv<typename
> remove_reference<T>::type>::type argument_type;
> typedef argument_type type;
> };
>
> // The operator can be called on both const and non-const functor.
> The
> argument can be lvalue or rvalue.
> template<class T>
> T operator()(T const& x) const
> {
> return x;
> }
> };
>
> // All following result_of uses are valid and result in int
> typedef boost::result_of< functor(int) >::type type1; // the argument
> is
> rvalue
> functor f;
> type1 r1 = f(10);
>
> typedef boost::result_of< const functor(int) >::type type2; // the
> function object is const
> const functor cf;
> type2 r2 = cf(10);
>
> typedef boost::result_of< functor(int&) >::type type3; // the argument
> is
> lvalue
> int a = 10;
> type3 r3 = f(a);
>
> typedef boost::result_of< functor(int const&) >::type type4; // the
> argument is const lvalue
> const int ca = 10;
> type4 r4 = f(ca);
> </quote>
>
> You can find the complete page tere:
>
> http://svn.boost.org/svn/boost/trunk/libs/utility/utility.htm
>
> If noone objects I will merge it to release branch in a few days

- Jeff


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