2015-09-12 12 views
7

Oggi mi sono imbattuto this pezzo di codice:funzione di prototipo di struct

int main() { 
    struct Foo {}; 
    struct Bar {}; 

    Foo(b)(int (Bar*c)); // ? 

    return 0; 
} 

non ho assolutamente idea di cosa sta succedendo. Il mio compilatore (VC14) mi avvisa della funzione prototipo non utilizzata?

Che cosa fa questa linea fa (dichiarare una funzione:? Il cui nome, quali parametri e tipo di ritorno come chiamarlo?)

Foo(b)(int (Bar*c)); 

Grazie in anticipo per avermi aiutato!

risposta

6

Questo dichiara una funzione chiamata b che:

  • prende int (Bar*c) come argomento;
  • restituisce Foo.

Il tipo dell'argomento, int (Bar*c), è un puntatore a una funzione che richiede un puntatore ad Bar e restituisce un int. Qui, c è il nome dell'argomento e può essere omesso: int (Bar*).

Ecco come si può chiamare b:

int main() { 
    struct Foo {}; 
    struct Bar {}; 

    Foo(b)(int (Bar* c)); // the prototype in question 

    int func(Bar*);  // a function defined elsewhere 
    Foo result = b(func); 

    return 0; 
} 
4

Questo non è valido C (perché i nomi Foo e Bar non si riferiscono ai tipi; si dovrà utilizzare la parola chiave struct o utilizzare un typedef).

In C++, questa è una dichiarazione sorprendente ma valida. Dichiara b come una funzione che restituisce Foo e che accetta un argomento di tipo "(puntatore a) restituendo int assumendo un argomento di tipo puntatore a Bar".

Al fine di generare una dichiarazione di tipo leggibile, ho scritto il seguente codice:

#include <typeinfo> 
#include <iostream> 


int main() { 
    struct Foo {}; 
    struct Bar {}; 

    Foo(b)(int (Bar*c)); 
    std::cout << typeid(b).name(); 

    return 0; 
} 

Poi ho compilato e filtrato attraverso la sua uscita c++filt. Il risultato è stato:

main::Foo (int (*)(main::Bar*)) 

che è del tutto chiaro.

+1

Sarebbe utile spiegare perché non è valido C. –

+0

@ JohannesSchaub-litb Anche questo è stato aggiunto. –

2

In realtà, il mio compilatore (Clang 3.5) mi dà il seguente avviso:

avvertimento: tra parentesi sono stati disambiguare come una dichiarazione di funzione [-Wvexing-parse]

Che è più su punto, come si sta trattando con Most vexing parse.

dichiarazione:

Foo(b)(int (Bar*c)); 

dichiara un puntatore bfunzione punta a una funzione che restituisce Foo e prende come argomento una funzione che restituisce int e prende puntatore a Bar un argomento (es: int (Bar*c)).

Il tuo compilatore probabilmente pensa che questo sia un prototipo di una funzione, quindi l'avviso.