1

Remove_reference is defined as follows:

template< class T > struct remove_reference      {typedef T type;};
template< class T > struct remove_reference<T&>  {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};   

When for a type T, remove_reference is instantiated, what is the algorithm for choosing the proper specialization of the template? I don't think this is template argument deduction. Other things that I found were even less relevant (ADL, overload resolution, etc.)

esam
  • 580
  • 3
  • 13
  • 2
    The selection process is called *Matching of class template partial specializations* and is based on *Partial ordering of class template specializations*. The latter are largely based on rules of *Partial ordering of function template specializations* – AnT stands with Russia Oct 06 '16 at 23:47
  • Thanks, this seems to be what I was looking for. – esam Oct 07 '16 at 10:34

1 Answers1

1

We:

  1. Pick the specializations that match the template arguments. If there is only one, you pick that one. If there are none, you use the primary. Else:

  2. Synthesize a function for each specialization and use the function template partial ordering rules.

In this case, we never have to get to step two. There are three types of types that are relevant: non-references, lvalue references, and rvalue references. So we can make a table:

+---------------------------+-------------+--------------+
|                           | Matches T&? | Matches T&&? |
+---------------------------+-------------+--------------+
| remove_reference<int>     | No          | No           |
| remove_reference<char&>   | Yes, T=char | No           |
| remove_reference<float&&> | No          | Yes, T=float |
+---------------------------+-------------+--------------+

Note that remove_reference<char&> does not match remove_reference<T&&>. The T&& here is simply rvalue reference to T, it is not a forwarding reference - a forwarding reference is only a function template argument whose type is an rvalue reference to a template parameter. This is a class template parameter. Even though conceptually with T=char&, T&& would be char& with reference collapsing rules, that will not happen.

In each of the three cases, we either match zero of the specializations - in which we use the primary template - or exactly one of the specializations - in which case we use that particular specialization.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Doesn't `remove_reference` also match the `T&&` specialization? – aschepler Oct 07 '16 at 00:20
  • @aschepler No it doesn't. – Barry Oct 07 '16 at 00:56
  • Is that because we check all specialization and find a better match? The question that aschepler asked was exactly why I asked this question. Given the notion of universal reference defined in the book "Effective Modern C++" I expect that T&& matches remove_reference. – esam Oct 07 '16 at 03:14
  • @esam No, the `T&&` specialization **does not match** `char&`. It's not that it matches and is a worse match. Added more wording to that effect to the answer. – Barry Oct 07 '16 at 11:30