Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 765731
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T16:56:01+00:00 2026-05-14T16:56:01+00:00

(I asked a variation of this question on comp.std.c++ but didn’t get an answer.)

  • 0

(I asked a variation of this question on comp.std.c++ but didn’t get an answer.)

Why does the call to f(arg) in this code call the const ref overload of f?

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
     f(arg);
}

My intuition says that the f(string &&) overload should be chosen, because arg needs to be converted to a temporary no matter what, and the temporary matches the rvalue reference better than the lvalue reference.

This is not what happens in GCC and MSVC (edit: Thanks Sumant: it doesn’t happen in GCC 4.3-4.5). In at least G++ and MSVC, any lvalue does not bind to an rvalue reference argument, even if there is an intermediate temporary created. Indeed, if the const ref overload isn’t present, the compilers diagnose an error. However, writing f(arg + 0) or f(std::string(arg)) does choose the rvalue reference overload as you would expect.

From my reading of the C++0x standard, it seems like the implicit conversion of a const char * to a string should be considered when considering if f(string &&) is viable, just as when passing a const lvalue ref arguments. Section 13.3 (overload resolution) doesn’t differentiate between rvalue refs and const references in too many places. Also, it seems that the rule that prevents lvalues from binding to rvalue references (13.3.3.1.4/3) shouldn’t apply if there’s an intermediate temporary – after all, it’s perfectly safe to move from the temporary.

Is this:

  1. Me misreading/misunderstand the standard, where the implemented behavior is the intended behavior, and there’s some good reason why my example should behave the way it does?
  2. A mistake that the compiler vendors have somehow all made? Or a mistake based on common implementation strategies? Or a mistake in e.g. GCC (where this lvalue/rvalue reference binding rule was first implemented), that was copied by other vendors?
  3. A defect in the standard, or an unintended consequence, or something that should be clarified?

EDIT: I have a follow-on question that is related: C++0x rvalue references – lvalues-rvalue binding

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T16:56:02+00:00Added an answer on May 14, 2026 at 4:56 pm

    GCC is doing it wrong according the FCD. The FCD says at 8.5.3 about reference binding

    • If the reference is an lvalue reference and the initializer expression is an [lvalue / class type] …
    • Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference and the initializer expression shall be an rvalue or have a function type.

    Your case for the call to the std::string && matches none of them, because the initializer is an lvalue. It doesn’t get to the place to create a temporary rvalue, because that toplevel bullet already requires an rvalue.

    Now, overload resolution doesn’t directly use reference binding to see whether there exist an implicit conversion sequence. Instead, it says at 13.3.3.1.4/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.

    Thus, overload resolution figures out a winner, even though that winner may actually not be able to bind to that argument. For example:

    struct B { B(int) { /* ... */ } };
    struct A { int bits: 1; };
    
    void f(int&);
    void f(B);
    int main() { A a; f(a.bits); }
    

    Reference binding at 8.5 forbids bitfields to bind to lvalue references. But overload resolution says that the conversion sequence is the one converting to int, thus succeeding even though when the call is made later, the call is ill-formed. Thus my bitfields example is ill-formed. If it was to choose the B version, it would have succeeded, but needed a user defined conversion.

    However, there exist two exceptions for that rule. These are

    Except for an implicit object parameter, for which see 13.3.1, a standard conversion sequence cannot be formed if it requires binding an lvalue reference to non-const to an rvalue or binding an rvalue reference to an lvalue.

    Thus, the following call is valid:

    struct B { B(int) { /* ... */ } };
    struct A { int bits: 1; };
    
    void f(int&); /* binding an lvalue ref to non-const to rvalue! */
    void f(B);
    int main() { A a; f(1); }
    

    And thus, your example calls the const T& version

    void f(const std::string &);
    void f(std::string &&); // would bind to lvalue!
    
    void g(const char * arg) { f(arg); }
    

    However, if you say f(arg + 0), you create an rvalue, and thus the second function is viable.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've asked another related question to this here: casting dynamic to static problem I've
Some student asked this on another site, but got no answers. I had a
So I know there have been a number of similar posts, but I think
I was just looking for a todolist service over the net. I encountered this
My boss asked me to program a custom jQuery validation plugin. If <input />
I would like to use python for things I've been doing using bash. Is
I'm adding a password reset feature to my Rails application that uses Authlogic. I
I've got two models: Common and ARecord. ARecord has a ForeignKey relationship to Common.
I'm a webdeveloper with an emphasis on server-side programming. What little I've tinkered with
Possible Duplicate: Is there a performance difference between i++ and ++i in C++? In

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.