9

In the code below, why do the two ways of invoking fun: fun(num) and fun<const int>(num), give a different result when compiling?

#include <iostream>
using namespace std;

template<typename T, typename = typename enable_if<!std::is_same<int, T>::value>::type>
void fun(T val)
{
    cout << val << endl;
}

int main(void)
{
    const int num = 42;
    fun(num);  //ERROR!

    fun<const int>(num);  //Right

    return 0;
}
Boann
  • 48,794
  • 16
  • 117
  • 146
Ryan
  • 158
  • 5

1 Answers1

20

The parameter is declared as pass-by-value; then in template argument deduction, the top-level const qualifier of the argument is ignored.

Before deduction begins, the following adjustments to P and A are made:

1) If P is not a reference type,

a) ...

b) ...

c) otherwise, if A is a cv-qualified type, the top-level cv-qualifiers are ignored for deduction:

So given fun(num), the template parameter T will be deduced as int, not const int.

If you change the parameter to pass-by-reference, the const part will be preserved. e.g.

template<typename T, typename = typename enable_if<!std::is_same<int, T>::value>::type>
void fun(T& val)

Then for fun(num), T will be deduced as const int.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    What's more, the type of `num` is `const int`, the type of the value of `num` is just `int`. There is no such thing a value (a prvalue, technically) of type `const int`. – curiousguy Jun 15 '18 at 09:45