12

I have simple question about the c++ function match priority. Suppose I have such code:

#include <iostream>

void func(const char*)
{
    std::cout << "const char*" << std::endl;
}

template<int N>
void func(const char (&) [N])
{
    std::cout << "const char (&) [N]" << std::endl;
}

int main(int argc, char* argv[])
{
    func("Hello world");
    return 0;
}

The result of the code is (with Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn)):

const char*

I think the literal type of the "Hello world" should be const char[]. Why the const char* version has a higher priority than the const char (&)[] version?

sepp2k
  • 363,768
  • 54
  • 674
  • 675
jayatubi
  • 1,972
  • 1
  • 21
  • 51

2 Answers2

6

Overload resolution attempts to find the best conversion. The following paragraph lists the relevant bullet points that could distinguish both conversions:

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

  • S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that,

  • the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that,

  • […]

While the specialization of the function template yields a parameter with an identity conversion, the non-template overload with char const* requires an Array-to-pointer conversion. Intuitively, we'd say that the former is a better match and should thus be selected. However, the array-to-pointer conversion is an Lvalue Transformation, excluded from the first bullet point. And since it has Exact Match Rank, the rank of the conversion isn't different than the rank of the conversion for char const (&)[N], which also has Exact Match Rank. "The rules in the paragraph below" cannot distinguish the conversions either, as they solely address derived-to-base conversions and such, but not array-to-pointer.

In fact, the conversion to char const (&)[N] is not better in any way. But overload resolution discriminates templates:

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then

  • for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that,

  • […]

  • F1 is not a function template specialization and F2 is a function template specialization, or, if not that,

Hence the non-template overload is selected.

Columbo
  • 60,038
  • 8
  • 155
  • 203
3

In your particular case the relevant part of the resolution rules applied is that non-template functions have precedence over template functions, that's why you see a pointer and not an array reference.

bobah
  • 18,364
  • 2
  • 37
  • 70
  • It is considerably more complicated than this, in so much that 25+ pages of the standard a dedicated solely to the subject of overload resolution (and no, I didn't down-vote this). – WhozCraig Apr 30 '15 at 07:21
  • 1
    @WhozCraig - but in the subject case the relevant part of those 25+ pages is exactly what I gave in my answer. Everyone can quote the standard, but not everyone can give a _specific_ answer. Hope downvoters enjoyed themselves. – bobah Apr 30 '15 at 07:58
  • 1
    I at-least-partially concur, and thus why I did *not* down-vote your answer. – WhozCraig Apr 30 '15 at 08:03