Search code examples
c++language-lawyertemplate-argument-deduction

How template argument deduction is performed in this example?


Consider the following example:

template <class T> 
void f(const T&&) { std::cout << __PRETTY_FUNCTION__; };

int main(void){

       const int *cptr = nullptr;
       f(std::move(cptr));
}

Per [temp.deduct.call]/1:

Template argument deduction is done by comparing each function template parameter type (call it P) that contains template-parameters that participate in template argument deduction with the type of the corresponding argument of the call (call it A) [..]

and [temp.deduct.call]/3:

If P is a cv-qualified type, the top-level cv-qualifiers of P's type are ignored for type deduction. If P is a reference type, the type referred to by P is used for type deduction.

Considering the given paragraphs, I'm deducing the template argument for T to be int* as follows:

P = const T&&, A = const int*; // replacing 'const T&&' with 'const T'
P = const T, A = const int*
T = int*

// what's wrong with these steps?

But when I compile this code with gcc and clang, it shows that the deduced T is const int*

My Question: Why the deduced template argument is const int* and not int* as I expect?


Solution

  • Why the deduced template argument is const int* and not int* as I expect?

    The const in P = const T is a top level const and applies to T while the const in A = const int* is a low-level const meaning it does not apply to the pointer. This in turn means that you can't directly compare const T with const int* the way you have done.

    Therefore, T will be deduced as the simplest argument type const int* and the function parameter will be of type const int *const &&.