Search code examples
c++rvalue-referencefunction-templates

C++: Template Function taking rvalue reference overloads non-template function


Trying to run a non-generic function but it is overloaded by a template function.

The problem is that they take rvalue references as arguments.


Here's what it kinda looks like:

#include <iostream>
using namespace std;

template <typename T> void bar(T &b)  { cout << "bar <template> called\n" ; }
template <typename T> void foo(T &&b) { cout << "foo <template> called\n" ; }
void bar(string &b)                   { cout << "bar <string> called\n"   ; }
void foo(string &&b)                  { cout << "foo <string> called\n"   ; }

int main() {

    string msg_a = "hello a";
    string msg_b = "hello b";
    int a = 1;
    int b = 2;

    bar(a);
    bar(msg_a);

    bar(b);
    bar(msg_b);

    cout << "\n";

    foo(a);
    foo(msg_a); // <-- I want this to call the 'void foo(string &&b)' but it doesn't

    foo(b);
    foo(msg_b); // <-- I want this to call the 'void foo(string &&b)' but it doesn't

    return (0);
}
Output:

bar <template> called
bar <string> called
bar <template> called
bar <string> called

foo <template> called
foo <template> called
foo <template> called
foo <template> called

When I call foo() with a type string I would like it to call the void foo(string &&b) function but instead it calls the template <typename T> void foo(T &&b) function.

Whereas as you can see with the functions that take an lvalue reference this is not a problem and the priority is held as normal.


Does anyone know a fix or work around for this ?


Solution

  • foo(msg_a) cannot ever call void foo(string &&b) as that particular overload only accepts rvalues of type string, while msg_a is an lvalue expression. The only viable fallback is therefore template <typename T> void foo(T &&b), which accepts a forwarding reference. Forwarding references bind to both lvalues and rvalues.

    If you invoke foo with an rvalue (e.g. foo(std::string{})), then it will call the aforementioned overload.