Il 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 oggetti

modifica

Il 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

  1. la definizione di una variabile time_keeper di classe TimeKeeper, inizializzata con un'istanza anonima della classe Timer;
  2. la dichiarazione di una funzione time_keeper con tipo di ritorno TimeKeeper e un singolo parametro (senza nome) di tipo puntatore a funzione senza parametri e con tipo di ritorno Timer.

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 time_keeper è una funzione dichiarata alla riga precedente, per cui non è possibile chiamare su essa il metodo get_time().

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 funzionale

modifica

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));
}

In questo caso, i viene interpretata come una definizione di funzione, equivalente alla seguente

// 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 syntax

modifica

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{}};

Note

modifica

Collegamenti esterni

modifica
  Portale Informatica: accedi alle voci di Wikipedia che trattano di informatica

📚 Artikel Terkait di Wikipedia

Racket (linguaggio di programmazione)

Felleisen, Programming Languages as Operating Systems (or, Revenge of the Son of the Lisp Machine), International Conference on Functional Programming, 1999

Guerra degli editor

worse on white space sensitive languages (Python, CoffeeScript) as this might actually cause syntax errors or programming logic errors. However, you can

Read–eval–print loop

of a REPL implementation in Common Lisp. Joël Franusic Online-REPs-and-REPLs list repl.it is a client-side web REPL for various programming languages

Lista di standard ISO

ISO 8802-x IEEE 802-x LAN/MAN Standards Committee ISO/IEC 8824 Abstract Syntax Notation One (ASN.1) ISO/IEC 8825 ASN.1 regole di codifica ISO 8859 codifica

C++11

versione finale del C++11 da parte di ISO e IEC (ISO/IEC 14882:2011(E) Programming Languages—C++, Third Edition.) Le maggiori implementazioni di compilatori

GraalVM

platform for polyglot programming, in Proceedings of the 16th ACM SIGPLAN International Conference on Managed Programming Languages and Runtimes, Association