0

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 ?

AymenTM
  • 529
  • 2
  • 5
  • 17

1 Answers1

4

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.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • In other words i need to make `foo(std::string &b)` instead of `foo(std::string &&b)` and forget trying to get rvalues, basically forcing me to strictly only get lvalues ? – AymenTM Aug 10 '19 at 00:22
  • @AymenTM: possibly. I am not sure what your real use case is and what you're trying to achieve. But technically that would work. – Vittorio Romeo Aug 10 '19 at 00:23
  • Trying to have a template function do something for all types except for `std::string`s, I want it to do something specific. Ik about specializations but isn't this like the most specific ? – AymenTM Aug 10 '19 at 00:30
  • @AymenTM: you could use if constexpr + a type trait instead of relying on overloading. – Vittorio Romeo Aug 10 '19 at 01:18