2016-06-05 11 views
14

ho seguito la funzione (solo per riprodurre il problema):Template argomento detrazione per 'char *'

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

Vorrei chiamare questo con una stringa letterale, come di seguito:

func<char*>("literal"); 

Ma, mi finisce per ottenere sotto avvertimento:

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

ho un bisogno specifico da utilizzare char* come il mio tipo chiave ed ero ex pecting TAD prendere in considerazione il param type come const char* nel suo complesso come non sto prendendo per riferimento.

L'avviso viene fornito con entrambi i compilatori clang e g++.

Come viene dedotto il param type qui?

Grazie in anticipo.

+6

'cptr' finisce per essere un puntatore-a-carattere const (' char * const'), non un puntatore a const char. – melpomene

+0

@melpomene Come è finita così? – Arunmu

+0

La vostra dichiarazione dice 'cptr' deve essere' const', e istanziate 'KeyT' con' char * '. Quindi 'cptr' è una const KeyT (con KeyT = pointer-to-char). – melpomene

risposta

12

mi aspettavo TAD considerare il tipo parametro come const char * ...
Come è il tipo di parametro viene dedotta qui?

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

noti che const è la qualificazione su KeyT stessa, significa che se KeyT è un puntatore, allora cptr sarà un puntatore const, non un puntatore const.

"literal" è in tensione letterale con tipo const char[8], che potrebbe decadere a const char*. Quindi KeyT potrebbe essere dedotto come const char*, quindi il tipo di cptr sarà const char* const.

Si sta specificando il tipo di argomento modello come char*, quindi rende cptr a char* const. Ma da C++ 11, la conversione di una stringa letterale in char* implicitamente non è consentita poiché i valori letterali sono const.

Perché è necessario il tipo di parametro modello da char*? Per modificarlo all'interno della funzione? Nota che la modifica di una stringa letterale porterà a UB. Si potrebbe passare un array di caratteri ad esso, come:

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

'Perché il tipo di parametro template deve essere char *? Per modificarlo all'interno della funzione? '. No, questo è solo un esempio che ho mostrato. In realtà sto usando 'char *' come tipo di chiave per un contenitore self made che copierà il letterale fornito nella struttura dei dati dei contenitori. Volevo provare senza usare i tratti 'remove_const' /' decay'. – Arunmu

+0

@Arunmu Se non lo modificherete, usare 'const char *' andrà bene (specificare l'argomento template come 'const char *' o non specificare affatto). In caso contrario, devi fare qualcosa di più come la mia risposta ha mostrato. – songyuanyao

+0

sì, questo è quello che sembra. Devo forse ripensare alla mia interfaccia. – Arunmu

8

Non c'è deduzione qui: si è esplicitamente dichiarato che il parametro modello è char*.

Quello che ti manca è che la sostituzione dei parametri non è una ricerca e sostituzione del testo: in realtà segue le regole logiche per il sistema di tipi. const KeyT cptr dichiara un'istanza const del tipo KeyT — quando KeyT è char*, la dichiarazione dei parametri diventa char *const cptr.