1

I have this example from C++ primer 5th ed:

template <typename T>
int compare(T const& x, T const& y) // in the book const T&
{
    cout << "primary template\n"; // I've added print statements
    if(std::less<T>()(x, y))
        return -1;
    if(std::less<T>()(y, x))
        return 1;
    return 0;
}

template <unsigned N, unsigned M>
int compare(char const(&rArr1)[N], char const(&rArr2)[M])
{
    cout << "overload for arrays\n";
    return strcmp(rArr1, rArr2);
}

template <>
int compare(char const* const &p1, char const* const &p2)
{
    cout << "specilization for char* const\n";
    return strcmp(p1, p2);
}


int main()
{
    std::cout << compare("Hi", "Mom") << '\n';
}

"Whether we define a particular function as a specialization or as an independent, non-template function can impact function matching. For example, we have defined two versions of our compare function template, one that takes references to array parameters and the other that takes const T&. The fact that we also have a specialization for character pointers has no impact on function matching. When we call compare on a string literal:

compare("hi", "mom");

both function templates are viable and provide an equally good (i.e., exact) match to the call. However, the version with character array parameters is more specialized (§ 16.3, p. 695) and is chosen for this call."

  • I think the it is incorrect: "compare("hi", "mom"); both templates are viable" because as I see the first version that takes T const&, T const& is not viable because it is instantiated as:

      compare(char const(&rArra1)[3], char const(&rArr2)[4]);
    

In which case sizes are different and as we know the size of an array is a part of its type thus here the two literal strings have two different types thus the Template Argument Deduction will fail thus this instantiation is rejected. it is as if we wrote: compare(5, 0.); // int, double so the compiler cannot deduce a unique type as it is required here.

  • To confirm what I am saying if I comment out the version taking array types then the code won't compile for that call with two literal strings with different sizes.

  • What confuses me too is that if I comment out the arrays-type version the code doesn't compile even if I have the third version (taking pointer to character strings)! Is this because of the fact that a Specialization doesn't affect function matching? and what was rejected by a primary template is rejected by all of its specializations?

Please clarify. Thank you!

Maestro
  • 2,512
  • 9
  • 24
  • 1
    Indeed, the first template is not viable. It's easy to demonstrate: if one comments out the second template together with the specialization, the program no longer compiles, and the error message explains exactly what makes the first (and now only) template non-viable. – Igor Tandetnik Dec 25 '20 at 18:03
  • @IgorTandetnik: If I comment out the second version(arrays) only the code doesn't compile! even if I leave the third version (pointers) un-commented. Does this mean what is rejected for a primary is rejected for any specialization? after all in the book it is said that a specialization doesn't affect function matching? – Maestro Dec 25 '20 at 18:06
  • 1
    That's correct. Only primary templates participate in template parameter deduction and overload resolution. Once the primary template is chosen, then the compiler further checks whether it should use the specialization of that template in place of the primary. – Igor Tandetnik Dec 25 '20 at 18:10
  • @IgorTandetnik: Please add it as an answer. – Maestro Dec 25 '20 at 18:20

0 Answers0