4

My question is simple

#include <iostream>

using namespace std;

template <typename T>
void f(T&& i) {
        cout << i << endl;
}

void g(int&& i) {
        cout << i << endl;
}

int main() {
        int i = 0;
        f(i); // works fine
        g(i); // candidate function not viable: no known conversion from 'int' to 'int &&'
              // for 1st argument void g(int&& i)

}

Why can I pass an lvalue to templated function f() but not non templated function g()

  • 1
    You'd need to move it, the template works because you get typededuction to `void f(int& i)`. The term for the first parameter is universal reference, where as the second is exclusively an r value reference. – George Sep 22 '19 at 09:06

2 Answers2

7

Your f() function does not expect a rvalue but a forwarding reference.
Despite the fact that f() and g() look very similar (due to the && symbol), they are very different.
(see for example Is there a difference between universal references and forwarding references?)

If you really want to pass i to g(), you have two options:

  • provide a temporary object which is a copy of i (then considered as a rvalue)
    g(int{i})
  • force the conversion to rvalue reference with std::move(); then the original i must not be used afterwards.
    g(std::move(i))
    (https://en.cppreference.com/w/cpp/utility/move)
prog-fh
  • 13,492
  • 1
  • 15
  • 30
  • Thanks for the perfect answer. This is the best written answer I have ever seen in SO. I wish everyone on SO would write well written answers like this. – Ankit Rohilla Sep 11 '22 at 19:57
1

R-value references is defined since c++ 11, You should change your compiler version to c++ 11.

Please check out this link