Boost logo

Boost :

Subject: Re: [boost] [result_of] Usage guidelines
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2012-09-04 02:59:56


On Monday 03 September 2012 13:53:18 Jeffrey Lee Hellrung, Jr. wrote:
> On Mon, Sep 3, 2012 at 12:08 AM, Andrey Semashev
>
> <andrey.semashev_at_[hidden]>wrote:
> > Hi,
> >
> > I wonder what is the correct way of declaring polymorphic function
> > object result types and how to use result_of template with regard to
> > argument types. If a function object receives arguments by reference,
> > should its member result<> template be specialized for reference types
> > as well?
>
> Not necessarily. I believe it is sufficient to sprinkle some
> remove_reference's and remove_const's around if the cv and reference
> qualifiers of the arguments don't matter.

[snip]

> > // Or is this correct?
> > template< typename ArgT >
> > struct result< my_foo(ArgT const&) >
> > {
> >
> > typedef ArgT type;
> >
> > };
>
> Not quite (based on your overload of operator() below). Use the former
> signature, with a "typedef typename remove_cv< typename remove_reference<
> ArgT >::type >::type". The latter composition of metafunctions occurs so
> frequently that I just use a remove_qualifiers that is equivalent to
> remove_cv< remove_reference<T>::type >::type.

Yes, this seem to simplify things a lot, thanks for the hint. It gives the
correct result type for most cases except when argument type is a non-const
lvalue reference. In this case incorrect result_of instantiations will also
work, which may not be expected. I suppose, in such cases additional
specializations are still needed:

  struct my_foo
  {
    template< typename >
    struct result;

    template< typename ArgT >
    struct result< my_foo(ArgT const&) >;

    template< typename ArgT >
    struct result< my_foo(ArgT&) >
    {
      typedef ArgT type;
    };

    template< typename ArgT >
    ArgT operator() (ArgT& arg) const
    {
      return arg;
    }
  };

> Another question I have is how to use result_of<> when my_foo is
>
> > external (i.e. provided by a third party library)?
> >
> > // Which one is the right way?
> > typedef result_of< my_foo(int) >::type result_type1;
> > typedef result_of< my_foo(int const&) >::type result_type2;
>
> Again, depends on if you call it like
>
> int x = 0;
> my_foo(x); // result_of< my_foo( int & ) >::type
>
> or
>
> int const x = 0;
> my_foo(x); // result_of< my_foo( int const & ) >::type
>
> or
>
> my_foo(0); // result_of< my_foo( int ) >::type

Ok, so the rule of thumb is to always instantiate result_of on the exact
(reference) types of arguments you have and let the result<> specializations
deal with references. Makes sense, thank you.


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