2017-01-03 64 views
7
#include <iostream> 
using namespace std; 

void f(const char* arg) 
{ 
    cout << "arg is a pointer" << endl; 
} 

template<size_t N> 
void f(const char (&arg)[N]) 
{ 
    cout << "arg is an array." << endl; 
} 

int main() 
{ 
    f(""); 
} 

Mój kompilator jest clang 3.8.Dlaczego clang przyjmuje literał łańcuchowy jako wskaźnik, a nie tablicę?

wyjście jest:

Arg to wskaźnik

Jednak według cppreference.com,

Rodzaj bez prefiksu łańcuch znaków jest char [] .

Dlaczego rozdzielczość przeciążenia nie działa zgodnie z oczekiwaniami?

+2

Równoważny przykład, ale abstrakcja szablonu: http://melpon.org/wandbox/permlink/0nGenu5Ysj40wS8u –

+0

[ściśle powiązane] (https://stackoverflow.com/questions/16708307/is-it-possible-to -legło-przeciążanie-a-string-literal-and-const-char), możliwe dupe. Co myślisz? –

Odpowiedz

8

To nie zachowują się zgodnie z oczekiwaniami, po prostu trzeba dostosować swoje oczekiwania ;-)

const char[1] i const char (&)[1] są różne typy.

Konwersje na const char* (konwersja tablicy na wskaźnik) i const (&char)[1] (konwersja tożsamości) są uważane za dokładne dopasowania, ale szablon inny niż szablon lepiej pasuje do szablonu.

Jeśli piszesz rozmiar specyficzne przeciążenie non-szablonu

void f(const char (&arg)[1]) 

dostaniesz błąd, że wywołanie funkcji jest niejednoznaczna.

+2

Zbyt wolno. :(Dla odniesienia, odpowiedni standardese jest w Tabeli 12 w N4141 –

1

@ Odpowiedź molbdnilo jest poprawna. Aby dodać jeden szczegół: Twoja intuicja byłaby poprawna, a kompilator wolałby uniknąć konwersji między tablicami i wskaźnikami, wywołując szablon. Ale transformacje l-wartości (l-wartość-r-wartość, tablica-do-wskaźnika oraz-funkcja-do-wskaźnika) są specyficznie ignorowane w rankingu przeciążenia, zgodnie z [over.ics.rank] §13.3.3.2/3.2.1.

Istnieje workaround: dodaj fałszywego volatile, aby przywrócić równowagę preferencji przeciążenia. Przed użyciem parametru należy go usunąć przed numerem const_cast.