|
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
<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.
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;
> };
>
No.
>
> // 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
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
> 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 acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk