Boost logo

Boost :

Subject: Re: [boost] [result_of] Usage guidelines
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-09-03 16:53:18

[The following expresses the guidelines I've been using, which may or may
not be the official Boost.ResultOf guidelines. But they make the most sense
to me.]

On Mon, Sep 3, 2012 at 12:08 AM, Andrey Semashev

> 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.

Also, should result_of<> for this function be instantiated
> with reference argument types?

Depends if the arguments of the actual call expression you're interested in
are lvalues or rvalues.

  struct my_foo
> {
> template< typename > struct result;
> // Is this correct?
> template< typename ArgT >
> struct result< my_foo(ArgT) >
> {
> typedef ArgT type;
> };


> // 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.

> template< typename ArgT >
> ArgT operator() (ArgT const& arg) const
> {
> return arg;
> }
> };
> I realize that I can provide both result<> specializations and it will
> work either way. But when there are more than one argument the
> specializations begin to pile quickly. Consider also rvalue references
> and const and non-const qualified my_foo.

You typically only have to provide as many specializations of result<>
(directly and indirectly) as you have overloads of operator(), and quite
often fewer. A little metaprogramming regarding cv and reference qualifiers
might be necessary, though :)

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


int const x = 0;
my_foo(x); // result_of< my_foo( int const & ) >::type


my_foo(0); // result_of< my_foo( int ) >::type

> I cannot know what result<> specializations are provided by my_foo, so
> probably there isn't an ultimate answer.

True; you hope result<> specializations are done carefully and thoughtfully

> But perhaps there are some
> guidelines or best practices? I've looked at result_of docs but there
> are no recommendations on this.

Someone may chime in and refute my position on this :)

- Jeff

Boost list run by bdawes at, gregod at, cpdaniel at, john at