Most vexing parseIl most vexing parse è una forma di soluzione di ambiguità sintattica del C++, definita nella sezione 8.2 dello standard[1], determinata dal fatto che la sintassi per l'inizializzazione di una variabile è in alcuni casi ambigua con quella di dichiarazione di una funzione. La locuzione most vexing parse è stata introdotta da Scott Meyers in Effective STL (2001).[2] Esempio con classi e oggettiIl seguente è un esempio di dichiarazione o definizione ambigua: class Timer {
public:
Timer();
};
class TimeKeeper {
public:
TimeKeeper(const Timer& t);
int get_time();
};
int main() {
TimeKeeper time_keeper(Timer());
return time_keeper.get_time();
}
La riga TimeKeeper time_keeper(Timer());
potrebbe essere interpretata come
Lo standard richiede di interpretare questa riga nella seconda maniera, per cui la riga successiva non sarà valida. Ad esempio, g++ restituisce il seguente messaggio di errore: $ g++ -c time_keeper.cc
time_keeper.cc: In function ‘int main()’:
time_keeper.cc:15: error: request for member ‘get_time’ in ‘time_keeper’, which is
of non-class type ‘TimeKeeper(Timer (*)())’
in quanto Clang++ fornisce un messaggio di warning: $ clang++ time_keeper.cc timekeeper.cc:14:25: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] TimeKeeper time_keeper(Timer()); ^~~~~~~~~ timekeeper.cc:14:26: note: add a pair of parentheses to declare a variable TimeKeeper time_keeper(Timer()); ^ ( ) timekeeper.cc:15:21: error: member reference base type 'TimeKeeper (Timer (*)())' is not a structure or union return time_keeper.get_time(); ~~~~~~~~~~~^~~~~~~~~ Per fare in modo che l'istruzione venga interpretata come definizione di variabile con inizializzazione, è possibile aggiungere una coppia di parentesi supplementare: TimeKeeper time_keeper( (Timer()) );
Esempio con cast funzionaleUn altro esempio coinvolge l'uso del cast funzionale, quando viene usato per convertire il valore di un'espressione passata poi come variabile o come parametro di un costruttore void f(double adouble) {
int i(int(adouble));
}
In questo caso, // takes an integer and returns an integer
int i(int adouble);
Per disambiguare l'espressione affinché venga interpretata come dichiarazione di variabile, si può usare la stessa tecnica dell'esempio precedente, oppure si può sostituire il cast funzionale con un cast in stile C // declares a variable called 'i'
int i((int) adouble);
oppure si può usare l'opportuno operatore di casting del C++ // declares a variable called 'i'
int i(static_cast<int>(adouble));
Uniform initialization syntaxLo standard C++11 ha introdotto la uniform initialization syntax (sintassi di inizializzazione uniforme), che uniforma la sintassi per l'inizializzazione di oggetti o variabili con quella per gli array e permette di evitare ogni ambiguità con la dichiarazione di funzioni. La riga problematica del primo esempio può essere riscritta come: TimeKeeper time_keeper{Timer{}};
Note
Collegamenti esterni
|