2015-08-15 21 views
10

compilando il seguente codice diForza `const char []` letterali stringa in clang

void f(char *, const char *, ...) {} 
void f(const char *, ...) {} 

int main() 
{ 
    f("a", "b"); 
} 

con clangore mi da questo errore:

prog.cpp:6:2: error: call to 'f' is ambiguous 
     f("a", "b"); 
     ^
prog.cpp:1:6: note: candidate function 
void f(char *, const char *, ...) {} 
    ^
prog.cpp:2:6: note: candidate function 
void f(const char *, ...) {} 
    ^

stringhe letterali AFAIK sono costanti in C++, e così la le regole di sovraccarico dovrebbero eliminare la prima variante dalla considerazione, risolvendo così inequivocabilmente la seconda variante. Ma immagino che Clang li renda non-const per ragioni di compatibilità (so che anche MSVC lo fa).

Quali flag del compilatore utilizzare per risolvere questo problema? Sto già compilando con -std=c++11.

EDIT: esplicita cast const char* risolve questo:

f((const char*)"a", "b"); 

Ma se sono corrette sul che il comportamento del compilatore osservato non è standard, voglio correggere il comportamento del compilatore, piuttosto che lo standard codice conforme

+1

@ Jarod42: perché Mi piace il nome. Se il codice non è rotto, non penso che "aggiustarlo" sia la soluzione giusta. – ybungalobill

+0

Definire il primo parametro fittizio, ad es. 'char' type. Aiuterà C++ a differenziare lo 'sprintf 'originale e la tua versione. Metterai 0 come primo parametro. – i486

+1

Ho cercato qualche tempo fa un commutatore per disattivare questa orribile conversione in 'char *', ma non ne ho trovato nessuno. Almeno, non documentato. Tempo di aggiungerne uno, immagino? MSVC ha alcuni switch "string string" btw. – dyp

risposta

5

Penso che questo sia un bug. La conversione di stringhe letterali a char * è stata rimossa in C++ 11 e non sono a conoscenza di alcuna disposizione nella risoluzione di sovraccarico per una sequenza di conversione che la coinvolga.

Come una soluzione che non comporta cambiando ogni singola chiamata a f, è possibile scrivere un altro overload che cattura in modo esplicito ogni chiamata con una stringa letterale, catturando la matrice per il riferimento:

template<size_t N, typename ...F> 
void f(char const (&a)[N], F&&... args) 
{ 
    f((char const *)a, std::forward<F>(args)...); 
} 
+0

Cattivo che ora '[[gnu :: format (printf, 1, 2)]]' non funziona :( – ybungalobill

+0

Questa è la risposta corretta! Secondo lo standard: una stringa stretta letterale ha tipo "array of n const char ". –

+0

@ybungalobill Argh, forse c'è un altro modo che ti permette di continuare ad usarlo. –