2012-04-05 12 views
12

Se si esegue l'overload di una funzione e poi chiama con un argomento che si abbina perfettamente uno dei sovraccarichiRegole di conversione implicita di argomenti di template

int f(int){return 3;} 
int f(bool){return 4;} 
...  //inside main() 
f(1);  //Calls f(int) 

il compilatore sceglie semplicemente questo (perfetto) partita prima di tentare qualsiasi conversioni implicite . Comunque ho cercato di sovraccaricare una funzione template come in

template <bool veracity> 
int f(){return 1;} 

template <int amount> 
int f(){return 2;} 

...  //inside main() 
f<1>(); 

ma il compilatore di continuo complainning su chiamata ambigua alla f sovraccarico(), affermando che potrebbe essere o f<true>() o f<1>(). Il compilatore non dovrebbe semplicemente scegliere la corrispondenza perfetta, invece di provare a convertire in true?

Avevo l'impressione che la conversione implicita per gli argomenti del modello fosse effettivamente più restrittiva della conversione implicita degli argomenti di funzione. C'è un modo per aggirare questo problema?

risposta

8

L'argomento che si fornisce non è un tipo, è un valore, quindi le regole sono leggermente diverse: è necessario applicare le regole per argomenti non di tipo. Per gli argomenti non di tipo, sono consentite le conversioni implicite. §14.3.2/5:

Le seguenti conversioni vengono eseguite su ogni espressione utilizzata come argomento modello non di tipo. Se un argomento modello non di tipo non può essere convertito nel tipo del parametro modello corrispondente, allora il programma è mal formato.

- Per un parametro modello non di tipo di tipo integrale o di enumerazione, vengono applicate le conversioni consentite in un'espressione costante convertita (5.19).

In C++ 03, la formulazione è leggermente differente, ma l'effetto sostanzialmente identico (anche §14.3.2/5):

- per un non-modello di tipo-parametro integrale o tipo di enumerazione, vengono applicate le promozioni integrali (4.5) e le conversioni integrali (4.7).

Ad ogni modo, dal momento che è sia un 1int e implicitamente convertibile in un bool, la chiamata è ambigua.

+0

vedo. Sai se esiste una ragione specifica per cui le regole sono così? Voglio dire, c'è qualche difficoltà tecnica o qualcosa che renderebbe impraticabile per i compilatori l'applicazione della logica "esatto-prima-partita/implicita-conversione-secondo" (utilizzata negli argomenti della funzione) agli argomenti del modello? – Malabarba

+0

No, non lo so per certo. La mia ipotesi sarebbe che è soprattutto perché le regole sono già complesse e l'aggiunta di un insieme di regole per il "ranking" come fa per il sovraccarico le renderebbe ancora più importanti. Non ne sono sicuro, ma suppongo che a causa dell'interazione con le altre regole per i modelli, le regole di classificazione risulterebbero almeno un po 'diverse da quelle per i sovraccarichi, quindi non sarebbe solo questione di dire "le funzioni candidate formeranno un set di sovraccarico da risolvere in conformità con §13.3." –

+0

Ha senso.Grazie. =) – Malabarba

5

Poiché non si tratta di un errore del compilatore ma di una funzionalità del linguaggio (vedere this answer), è necessario trovare un lavoro.

o avete rinominare le funzioni oppure si può usare questo hack:

template <typename T> struct F; 

template<> struct F<bool> { 
    template <bool veracity> 
    static int f(){return 1;} 
}; 

template<> struct F<int> { 
    template <int amount> 
    static int f(){return 2;} 
}; 

template <typename T, T value> 
int f() { return F<T>::template f<value>(); } 

// inside main(): 
std::cout << f<int, 2>() << '\n'; // prints 2 
std::cout << f<bool, 2>() << '\n'; // prints 1 
Problemi correlati