Il codice seguente viene compilato con VS15 Community e stampa "Hello".Comportamento imprevisto con alias del tipo di modello in VS2015
#include <functional>
#include <iostream>
template<typename T>
using void_template_alias_t = void;
template<typename T>
using Func = std::function<void(T)>;
template<typename T>
using FuncVoid = Func<void_template_alias_t<T>>;
int main()
{
FuncVoid<void> hello = [] { std::cout << "Hello\n"; };
hello();
}
Penso che questo non è consentito compilare.
Stavo giocando, il codice era un po 'più complesso. Mi aspettavo ingenuamente che funzionasse, ma all'improvviso mi sono reso conto che questo codice non doveva essere compilato perché non è possibile creare uno Func<void>
(o mi sbaglio di questo?).
- Ho trovato una soluzione magica?
- Si tratta di un nuovo comportamento dallo standard C++ 14?
- O è semplicemente un bug del compilatore?
Modifica: la seguente versione semplificata non viene compilata.
#include <functional>
#include <iostream>
template<typename T>
using Func = std::function<void(T)>;
int main()
{
Func<void> hello = [] { std::cout << "Hello\n"; };
hello();
}
- Allora perché il codice di cui sopra la compilazione e lavorando come mi aspettavo prima?
- È un'implementazione corretta, in caso contrario, come sarebbe?
C'è un mondo di differenza tra 'foo (void)' e 'using X = void; foo (X); '. Sarei sorpreso se altri compilatori lo accettassero. –
Oh, ero troppo sicuro. Lo standard afferma che "La lista dei parametri' (void) 'è equivalente alla lista dei parametri vuota.", Ma non specifica che '(void)' è un testo letterale. E non c'è alcuna produzione grammaticale specifica, e sia g ++ che Visual C++ compilano 'void foo (X)' dove 'X' è un nome per' void', e compilano la chiamata 'foo()'. –
Forse dovrei notare esplicitamente, che l'interpretazione in cui '(void)' si riferisce a una funzione in cui il * tipo * del singolo argomento è effettivamente 'void', e quindi denota una funzione senza argomenti, non funziona bene con il codice del template che richiama la funzione con un argomento, cioè non è pratico. Eppure sia MSVC che MinGW g ++ accettano il non-template 'foo (My_void)' e chiamano 'foo()'. :( –