3

Snippet:

#include <iostream>

template<typename T>
struct Printer{};

template<typename T>
void test(T&&)
{
    std::cout << "Primary template called\n";
}

template<typename T>
void test(Printer<T>&&)
{
    std::cout << "Specialized template called\n";
}

int main()
{
    auto t = Printer<int>{};
    test(0);
    test(t);
}

Here is the demo

Why is two times Primary template called printed?

If one removes the forward reference from the second template, then the Printer overload is chosen.

Why is it not chosen with &&?

Juergen
  • 3,489
  • 6
  • 35
  • 59
  • 4
    `&&` don't bind to lvalues, and `t` is an lvalue. `&&` is not a forwarding reference in your example, it is just an rvalue reference. – Evg Dec 05 '20 at 08:31
  • @Evg: Why does it bind to the first template then? – Juergen Dec 05 '20 at 08:33
  • 3
    Because in `T&&`, `&&` is a forwarding reference, but in `Printer&&`, `&&` is an rvalue reference. The only way to get a forwarding one is to write `T&&`. Even `const T&&` is no longer a forwarding reference. – Evg Dec 05 '20 at 08:34
  • Ok, I see...what is Printer then? – Juergen Dec 05 '20 at 08:38
  • 1
    `Printer` with `T` substituted with `T&&`. No magic's here. Only `T&&` are magical. – Evg Dec 05 '20 at 08:55

1 Answers1

3

Forwarding reference only works for T&&, not C<T>&& nor const T&&.

test(0); // Call test(T&&) with T=int
test(t); // Call test(T&&) with T=Printer<int>&
Jarod42
  • 203,559
  • 14
  • 181
  • 302