Né la stringa letterale né s
sono puntatori (sono array), quindi la relativa sezione della norma è [conv.array]:
Un Ivalue o rvalue di tipo "vettore di N
T
" o "matrice di limite sconosciuto di T
" può essere convertita in in un valore di tipo "puntatore su T
". Il risultato è un puntatore al primo elemento dell'array.
Nota che
char const *p = s;
f(p);
stampe "lvalue," per dimostrare che questo funziona come ci si aspetta per i puntatori.
addendum re: commento: Nel caso di
char *p = s;
f(p);
che stampa "rvalue" se il sovraccarico rvalue esiste ma non causa un errore di compilazione se viene rimosso, altre due sezioni della norma entrare in gioco - uno dei quali sembra proibire il binding di char*
a char const *const &
del tutto, e l'altro riaprire una finestra.
Il primo è [dcl.init.ref]/4, dove si afferma che
tipi dato "CV1T1
" e "CV2T2
", "CV1T1
" è riferimento relativi a "cv2T2
" se T1
è lo stesso tipo T2
, o T1
è una classe base di T2
. "CV1T1
" è compatibile riferimento con "cv2T2
" se T1
è riferimento relativi a T2
e CV1 è lo stesso cv-qualifica, o maggiore cv-qualificazione che, cv2. (...)
Si va avanti a lungo su regole precise per l'inizializzazione del riferimento, tutte rilevanti ma purtroppo troppo lunghe per una risposta SO.La lunga storia breve è che un riferimento a cv1T1
può essere inizializzato con un oggetto di cv2T2
se i due sono compatibili con riferimento.
Significato Legalese per il nostro caso è che char*
e char const *
non sono riferimento compatibile (anche se char*
e char *const
sarebbe), perché non è char*
char const *
né è una classe base dell'altro. Questa limitazione ha un senso se si considera il seguente pezzo illegale di codice che sarebbe legale altrimenti:
const char c = 'c';
char *pc;
const char*& pcc = pc; // #1: not allowed
pcc = &c;
*pc = 'C'; // #2: modifies a const object
Questa è adattato da un esempio simile in [conv.qual]/4 che utilizza un puntatore a puntatore a dimostrare la stesso problema.
[conv.qual] è anche l'altra relativa sezione che si apre la finestra posteriore in Si dice nel [conv.qual]/1:.
Un prvalue di tipo "puntatore a CV1T
"può essere convertito in un prvalue di tipo "puntatore a cv2T
" se" cv2T
"è più cv-qualificato di" CV1T
"
Da tutto ciò che char*
può essere convertito char const *
(che è di riferimento compatibile con char const *const
), motivo per cui il codice viene compilato ancora se il sovraccarico rvalue di f
viene rimosso. Tuttavia, il risultato di questa conversione è un valore di provalutazione, quindi se è presente, il sovraccarico di rvalue è preferito nella risoluzione di sovraccarico.
char*
glvalue ->char*
prvalue (da [conv.lval]) ->char const *
prvalue)
non dovrebbe 'char * p = s; f (p); 'anche essere" lvalue "? Perché è "rvalore"? – alice
Poiché un 'char *' non può essere associato con riferimento a un 'char const *' (ti permetterebbe di rompere la correttezza const). [conv.qual] si applica, che richiede prima la conversione da lvalue a rvalue e di conseguenza produce valori di prvalore. – Wintermute
Non sono sicuro di quale correttezza si stia riferendo. 'Tipo &' si lega solo agli lvalue modificabili, ma 'const Type &' si lega a tutto. Ad esempio, 'string s1 (" abc "); const string & s2 = s1; 'compila bene. – alice