Most vexing parse: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
←Nuova pagina: Il '''most vexing parse''' è una forma di soluzione di ambiguità sintattica del C++, definita nella sezione 8.2 dello standard.<ref name="C... Etichetta: Sequenze di caratteri ripetuti da parte di un nuovo utente o IP |
Funzionalità collegamenti suggeriti: 3 collegamenti inseriti. |
||
(5 versioni intermedie di 5 utenti non mostrate) | |||
Riga 1:
Il '''most vexing parse''' è una forma di soluzione di [[grammatica ambigua|ambiguità sintattica]] del [[C++]], definita nella sezione 8.2 dello standard
|cognome= Meyers
|wkautore=
|
▲| year = 2001
|url= https://archive.org/details/effectivestl50sp0000meye
▲| title = Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library
|
| isbn = 0-201-74962-9
}}</ref>
Riga 11:
== Esempio con classi e oggetti ==
Il seguente è un esempio di dichiarazione o definizione ambigua:
<
class Timer {
public:
Riga 28:
return time_keeper.get_time();
}
</syntaxhighlight>
La riga
<
TimeKeeper time_keeper(Timer());
</syntaxhighlight>
potrebbe essere interpretata come
# la definizione di una [[variabile (informatica)|variabile]] {{Code|time_keeper}} di classe {{Code|TimeKeeper}}, inizializzata con un'istanza anonima della classe {{Code|Timer}};
Riga 39:
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 (*)())’
</syntaxhighlight>
in quanto {{Code|time_keeper}} è una funzione dichiarata alla riga precedente, per cui non è possibile chiamare su essa il metodo {{Code|get_time()}}.
Riga 63:
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()) );
</syntaxhighlight>
== Esempio con cast funzionale ==
Un 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));
}
</syntaxhighlight>
In questo caso, {{code|i}} viene interpretata come una definizione di funzione, equivalente alla seguente
<
// takes an integer and returns an integer
int i(int adouble);
</syntaxhighlight>
Per [[Disambiguazione|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);
</syntaxhighlight>
oppure si può usare l'opportuno operatore di casting del C++
<
// declares a variable called 'i'
int i(static_cast<int>(adouble));
</syntaxhighlight>
== Uniform initialization syntax ==
Lo 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{}};
</syntaxhighlight>
== Note ==
Riga 111:
* [https://web.archive.org/web/20160709112804/http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=439 The Most Vexing Parse] by Danny Kalev
* [http://blog.llvm.org/2010/04/amazing-feats-of-clang-error-recovery.html Amazing feats of Clang Error Recovery] LLVM Project Blog
* [
* [http://www.stroustrup.com/C++11FAQ.html#uniform-init Uniform initialization syntax and semantics]
{{portale|informatica}}
|