From: Eric Niebler (eric_at_[hidden])
Date: 2008-04-05 17:41:48
Peter Dimov wrote:
> Eric Niebler:
>> Like a good citizen, I've written make_foo's function call operator to
>> recognize reference_wrapped and non-const-ref arguments as representing
>> lvalues and all others as rvalues.
> Const-ref arguments are lvalues. I'm not sure why do you need the
> reference_wrapper support.
Not so. make_foo()(1) -- 1 binds to the const-ref, but it is not an lvalue.
>> The strictly correct thing to do would be to wrap lvalues in
>> reference_wrappers before passing them to F. If I don't, make_foo will
>> do the wrong thing.
> I don't see why. Lvalues are lvalues. Wrapping them in a reference_wrapper
> won't make them any more lvaluish. I'm probably missing something.
>> struct blarg
>> template<typename This, typename Arg>
>> struct result< This( Arg ) >
>> // OK, if Arg is a reference, then it's an lvalue!
>> template<typename Arg>
>> typename result< make_foo( ??? ) >::type
>> operator()( Arg const & arg )
>> // whoops, I don't know here if arg is an lvalue or rvalue
> Write the return statement. Is it
> return make_foo()( arg );
I clearly should have fleshed this out a bit more. Consider something
like a fusion::make_tuple function object
template<typename Sig> struct result;
template<typename This, typename Arg>
struct result< This( Arg ) >
typedef tuple< Arg > type;
// This is wrong!
typename result< make_tuple( Arg const & ) >::type
operator ()( Arg const &arg )
return tuple< Arg const & >( arg );
This is wrong because make_tuple(1) will cause the resulting tuple to
hold on to a dangling reference. But had it been called as:
int const i = 0;
make_tuple( i );
... then it's correct. The problem here is that make_tuple::operator()
can't know whether it was passed an lvalue or an rvalue, so it doesn't
know how to compute the return type. In contrast, the result<> template
knows, because you can explicitly specify lvalue or rvalue as:
result_of< make_tuple( int const & ) >::type
result_of< make_tuple( int ) >::type
It is for this reason that Fusion's make_tuple() function (it doesn't
have a function object -- I consider that a defect) recognizes
reference_wrapped objects to be lvalues. There's no other way to
distinguish them in C++03.
-- Eric Niebler Boost Consulting www.boost-consulting.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk