4

This is a followup to this question.

A 2002 paper on the function forwarding problem in C++ makes the following observation:

This is the method currently employed by Boost.Bind and Boost.Lambda:

template<class A1, class A2, class A3> void f(A1 & a1, A2 & a2, A3 & a3)
{
    return g(a1, a2, a3);
}

Its main deficiency is that it cannot forward a non-const rvalue. The argument deduction creates a non-const reference, and the reference cannot bind to the argument. This makes innocent examples as

int main()
{
    f(1, 2, 3);
}

fail (violates C1).

I see that the call fails, but is the explanation correct? Are not the literals 1, 2, 3 const rvalues?

Community
  • 1
  • 1
ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80
  • 1
    Calling `f(1,2,3)` would work ok. That's basically why they are referring to the rvalues as 'non-const' deducable. – Jonas Bötel Mar 08 '11 at 16:31
  • @LumpN, `f(1,2,3)` does indeed work. So is the problem that type deduction cannot deduce `const int` from a primitive literal? – ThomasMcLeod Mar 08 '11 at 16:47
  • If I recall correctly move semantics + variadic templates should now allow perfect forwarding (C++0x). – Matthieu M. Mar 08 '11 at 19:25

1 Answers1

6

Are not the literals 1, 2, 3 const rvalues?

No, they are just rvalues of type int. According to the C++ standard, rvalues of primitive types cannot be const-qualified.

The call fails because they are rvalues - non-const references cannot be bound to rvalues.

The call would be OK if the functions took const A1 &, const A2&, const A3&, but in this case the function wouldn't be able to modify the arguments.

Edit: Reference to my first statement from the C++ 2003 standard : (3.10.9)

Class rvalues can have cv-qualified types; non-class rvalues always have cv-unqualified types. Rvalues shall always have complete types or the void type; in addition to these types, lvalues can also have incomplete types.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • imho it much more practical to say `Ref(x)` when one needs modification, than to say `Value(x)` whenever one needs to supply value. i.e., formal arguments better be `T const&`. – Cheers and hth. - Alf Mar 08 '11 at 16:42
  • So when the author says "cannot forward a non-const rvalue" he means "rvalue of primitive type int"? – ThomasMcLeod Mar 08 '11 at 16:42
  • 1
    @ThomasMcLead: No, the author says what he means: "non-const rvalues". Rvalues of non-class types, including primitive types, are always non-const, so the rule applies to them too – Armen Tsirunyan Mar 08 '11 at 16:48