0

I found the below link which said "lvalue and rvalue reference interface can combine in one". Pass lvalue to rvalue

but when I take it for example. compile error appeared cannot bind ‘std::string {aka std::basic_string}’ lvalue to ‘std::string&& {aka std::basic_string&&}’. Below is my implementation.

#include <iostream>
#include <string>

using namespace std;

void g(string &&b) {
    cout << b << endl;
}

void g(const string &b) {
    cout << b << endl;
}

void f(string &&a) {
    g(std::forward<string>(a));
}

int main()
{
    f("1122");
    string a("222");
    f(a);
    return 0;
}

I mean "void f(string &&a)" and "void f(const string &a)" can combine in one. Then we just need to call "void f(string &&a)", which can both receive rvalue reference and lvalue by preface forward.

--------- Add description

this may be call universal reference

daohu527
  • 452
  • 4
  • 15
  • Which answer to the linked question are you trying to follow? The one that uses a template (unlike your code) or the one that directs execution *to* a unified function (your code goes *from* a unified function)? Neither is a perfect match to what you've done, and you linked to the question instead of to a specific answer... – JaMiT Dec 13 '20 at 02:23

1 Answers1

1

To combine an r-value reference and l-value reference into a single reference, you need to use a so called universal reference. These are defined in C++ via auto && or a template with a && reference. See for example What is move semantics? , though, quite exceptionally, I guess you'll find more approachable explanations outside of stackoverflow. Search for "universal reference C++".

Now, back to your code. All you need is this:

template <typename T>
void f(T &&a) 
{
    g(std::forward<string>(a));
}

That's it. A universal reference defined via a template plus a &&-reference. Notice that I had to replace string with T.

However, simplicity is our best friend. If you don't need a template, why not go for the old, good const reference?

void f(const string & a) 
{
  g(a);
}

To me, it is the preferable solution.

zkoza
  • 2,644
  • 3
  • 16
  • 24
  • thx for you clearly answer! but I have an queue class already use the `A universal reference defined via a template plus a &&-reference` but it can success pass rvalue but can not pass lvalue. what can be the problem? it's a class member function with template. – daohu527 Dec 13 '20 at 08:04
  • @dahohu527, my guess: you have a class template `template class my_class { ... };` with a member function `void foo(T&&)`. In this case `T&&` is not a universal reference, but just an rvalue reference, and rvalue references can't bind to lvalues. If you had `template foo(S&&)`, `S&&` would be a universal reference. – Evg Dec 13 '20 at 09:02
  • @Evg Yes you're right, It is really difficult to understand. This article helps a lot. https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers – daohu527 Dec 13 '20 at 09:26