2016-06-05 18 views
14

Mam poniżej funkcji (tylko do odtwarzania problemu):Szablon „char *”

template <typename KeyT> 
void func(const KeyT cptr) { 
    std::cout << typeid(KeyT).name() << std::endl; 
} 

chciałbym nazwać sznurkiem dosłowne, jak poniżej:

func<char*>("literal"); 

Ale ja w końcu się poniżej ostrzeżenia:

 
warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wc++11-compat-deprecated-writable-strings] 

mam konkretną potrzebę korzystania char* jak mój klucz typu i jestem ex pecting TAD, aby rozważyć param type jako całość, ponieważ nie biorę go przez odniesienie.

Ostrzeżenie dotyczy zarówno kompilatorów clang, jak i g++.

W jaki sposób wyprowadza się tutaj param type?

Z góry dziękuję.

+6

'cptr' kończy się być wskaźnikiem const-to-char (' char * const'), a nie wskaźnikiem na const char. – melpomene

+0

@melpomene Jak to się tak skończyło? – Arunmu

+0

Twoja deklaracja mówi, że 'cptr' musi być' const', i tworzysz 'KeyT' z' char * '. Więc 'cptr' jest const KeyT (z KeyT = wskaźnik do char). – melpomene

Odpowiedz

12

Spodziewałem TAD rozważyć rodzaj param jako const char * ...
jaki jest typ param wyprowadzona jest tutaj?

template <typename KeyT> 
void func(const KeyT cptr) 

Zauważ, że const jest kwalifikator na KeyT sama, to znaczy, jeśli KeyT jest wskaźnikiem, a następnie cptr będzie const wskaźnik, a nie wskaźnik do const.

"literal" jest literą dosłowną z typem const char[8], która może rozpaść się na const char*. Następnie można wydedukować KeyT jako const char*, wtedy typ cptr będzie const char* const.

Podajesz typ argumentu szablonu jako char*, a następnie tworzysz cptr a char* const. Ale z C++ 11 konwertowanie literału z ciągu znaków na char* niejawnie jest niedozwolone, ponieważ literały są const.

Dlaczego potrzebny jest typ parametru szablonu: char*? Aby zmodyfikować go wewnątrz funkcji? Zauważ, że modyfikowanie literału ciągu prowadzi do UB. Można przekazać tablicę char do niego, jak:

char my_chararray[] = "literal"; 
func<char*>(my_chararray); // or just func(my_chararray); 
+0

'Dlaczego potrzebujesz typu parametru szablonu, aby być char *? Aby zmodyfikować go w funkcji? '. Nie, to tylko przykład, który pokazałem. Używam 'char *' jako klucza do jakiegoś self-made-kontenera, który skopiowałby podany literał do struktury danych kontenerów. Chciałem go wypróbować bez użycia cech 'remove_const' /' decay'. – Arunmu

+0

@Arunmu Jeśli nie zmienisz go, użycie 'const char *' będzie w porządku (określ argument szablonu jako 'const char *' lub w ogóle nie określaj). Jeśli nie, musisz zrobić coś więcej, jak pokazała moja odpowiedź. – songyuanyao

+0

tak, to jak to wygląda. Muszę ewentualnie przemyśleć ponownie mój interfejs. – Arunmu

8

Nie ma odliczenie tutaj: trzeba wyraźnie stwierdzić, że parametr szablonu jest char*.

To, czego brakuje, to że podstawianie parametrów nie jest tekstowym wyszukiwaniem i zamianą: faktycznie jest zgodne z regułami logicznymi dla systemu typów. const KeyT cptr deklaruje instancję const typu KeyT —, gdy KeyT jest char*, deklaracja parametru staje się char *const cptr.