views:

317

answers:

3

§3.10 section 9 says "non-class rvalues always have cv-unqualified types". That made me wonder...

int foo()
{
    return 5;
}

const int bar()
{
    return 5;
}

void pass_int(int&& i)
{
    std::cout << "rvalue\n";
}

void pass_int(const int&& i)
{
    std::cout << "const rvalue\n";
}

int main()
{
    pass_int(foo()); // prints "rvalue"
    pass_int(bar()); // prints "const rvalue"
}

According to the standard, there is no such thing as a const rvalue for non-class types, yet bar() prefers to bind to const int&&. Is this a compiler bug?

EDIT: Apparently, this is also a const rvalue :)

EDIT: This issue seems to be fixed in g++ 4.5.0, both lines print "rvalue" now

+2  A: 

Good point. I guess there are two things to look at: 1) as you pointed out the non-class rvalue thingsy and 2) how overload resolution works:

The selection criteria for the best function are the number of arguments, how well the arguments match the parameter-type-list of the candidate function, [...]

I haven't seen anything in the standard that tells me non-class rvalues are treated specially during overload resolution.

Your question is covered in the draft of the standard I have though (N-4411) somewhat:

What does come into play is however a parallel reading of reference binding, implicit conversion sequences, references, and overload resolution in general:

13.3.3.1.4 Reference binding

2 When a parameter of reference type is not bound directly to an argument expression, the conversion sequence is the one required to convert the argument expression to the underlying type of the reference according to 13.3.3.1.

and

13.3.3.2 Ranking implicit conversion sequences

3 Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

— Standard conversion sequence S1 is a better conversion sequence than standard
conversion sequence S2 if

— S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a nonstatic member function declared without a ref-qualifier, and either S1 binds an lvalue reference to an lvalue and S2 binds an rvalue reference or S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.

[ Example:

int i;
int f();
int g(const int&);
int g(const int&&);
int j = g(i); // calls g(const int&)
int k = g(f()); // calls g(const int&&)
dirkgently
+8  A: 

The committee already seems to be aware that there's a problem in this part of the standard. CWG issue 690 talks about a somewhat similar problem with exactly the same part of the standard (in the "additional note" from September, 2009). I'd guess new language will be drafted for that part of the standard soon.

Edit: I've just submitted a post on comp.std.c++, noting the problem and suggesting new wording for the relevant piece of the standard. Unfortunately, being a moderated newsgroup, nearly everybody will probably have forgotten this question by the time it makes it through the approval queue there.

Jerry Coffin
Just edit new info in later, the question should then come up in the *active* tab.
Georg Fritzsche
So, has the message been approved yet?
Omnifarious
The message has been approved and posted, but nobody's replied/followed up to it (yet?)
Jerry Coffin
@Jerry: Any luck yet, or is it dead?
GMan
@GMan: It seems to be dead -- nobody ever followed up to it at all.
Jerry Coffin
@Jerry: That's too bad. :[
GMan
A: 

incredible ,maybe that's really a compiler bug