Converting an array to a pointer is considered an exact match when ranking conversion sequences during overload resolution (C ++ 11 13.3.3.1.1 / 1 Table 12). Unlike your intuition, this means that (3) and (5) are equally good for A<5> a("0123456789"); . The tie is broken - as Xeo says in his comment - in favor of a non-template (3). You might think to trick the compiler by turning (3) into a template:
template <typename=void> A(const char * const) : b{} {}
but it will only lead to ambiguity in the design . There is actually no easy way to eliminate the overloads of const char (&)[] and const char* : a better solution would be to change (3) to accept a pointer and length:
A(const char * const, std::size_t) : b{} { std::cout << "size: " << SIZE << " ctor 3\n"; }
I will try to note that adding the size_t argument to the const char* const constructor also removes the ambiguity of the A("five") case .
EDIT: There is one sensible way to decouple the char* constructor from the array constructor , to take pointer arguments by reference:
template <typename T, typename=typename std::enable_if< std::is_same<typename std::remove_cv<T>::type, char>{} >::type> A(T* const&) : b{} { std::cout << "size: " << SIZE << " ctor 3\n"; }
[Credit for this trick goes dyp , and possibly Johannes Schaub or Jakka or me (I'm sure it was not me).
This template is effectively fixed to the actual type by reference - until the array is converted to a pointer, and then restrains references to types without pointers.
Casey Apr 25 '14 at 14:25 2014-04-25 14:25
source share