Il seguente codice funziona correttamente in VS2015:Template Selezione Funzione Sulla base di tipo annidato
struct Foo
{
using Bar = int;
auto operator()() { return "Foo!"; }
};
template <typename Callable, typename CodeType> // <<< CodeType is a template param
void funky(CodeType code, Callable func)
{
cout << "Generic: " << code << ", " << func() << endl;
}
template <typename HasBar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
cout << "Has Bar: " << code << ", " << func() << endl;
}
int main()
{
Foo foo;
funky(3, []() { return "Lambda!"; });
funky(3, foo);
return 0;
}
stampa:
Generic: 3, Lambda!
Has Bar: 3, Foo!
Tuttavia, it does not compile su gcc/clang, lamentandosi:
In function 'int main()':
27:16: error: call of overloaded 'funky(int, Foo&)' is ambiguous
27:16: note: candidates are:
12:6: note: void funky(CodeType, Callable) [with Callable = Foo; CodeType = int]
18:6: note: void funky(typename HasBar::Bar, HasBar) [with HasBar = Foo; typename HasBar::Bar = int]
L'ambiguità viene risolta correttamente da VS2015 (che non significa che sia la cosa conforme a d o).
Come posso ottenere questo per compilare ed eseguire correttamente su Clang/gcc?
Ho pensato di utilizzare std::enable_if
ma non riuscivo a farlo fare quello che voglio (probabilmente l'ho usato in modo errato). Se questa è la strada da percorrere, come dovrebbe essere usato per risolvere questa ambiguità?
UPDATE:
Aggiunta typename HasBar :: Bar per il modello params ottiene gcc/Clang per costruire ed eseguire il codice correttamente:
template <typename HasBar, typename HasBar::Bar>
void funky(typename HasBar::Bar code, HasBar func) // <<< The code type is a nested type
{
cout << "Has Bar: " << code << ", " << func() << endl;
}
Questo sembra dire al compilatore che c'è un secondo , valore del parametro modello non di tipo (non utilizzato nel codice funzione) di tipo typename HasBar::Bar
. If typename HasBar::Bar
non esiste, SFINAE rimuoverà questa funzione dal set di sovraccarico e verrà selezionato il modulo generico.
Tuttavia, quando esiste, non so perché questa funzione avrà la precedenza sul primo. Immagino perché è più specializzato, anche se la specializzazione non è usata nel codice stesso. Tuttavia, in questo caso, era già più specializzato anche prima del nuovo param!
Tuttavia, in questo caso VS2015 sceglie sempre la forma generica dare la risposta sbagliata!
C'è qualche sintassi (e/o soluzione) che funzionerà in tutti i casi?
Come hai usato 'enable_if'? Lo hai usato per abilitare il secondo sovraccarico o * disabilitare * il primo sovraccarico? –
In realtà ho provato varie cose ma non sono sicuro che fossero corrette. Come * dovrebbe * essere usato qui? –
Mi sarei aspettato che la seconda funzione fosse più specializzata e quindi fosse il sovraccarico preferito quando applicabile (quindi VS avrebbe ragione). Qualcuno può commentarlo? – MikeMB