2013-07-03 19 views
11

ho un problema comprendere tipi di funzione (appaiono esempio come parametro Signature modello di un std::function):tipi di funzione C++

typedef int Signature(int); // the signature in question 

typedef std::function<int(int)> std_fun_1; 
typedef std::function<Signature> std_fun_2; 

static_assert(std::is_same<std_fun_1, std_fun_2>::value, 
       "They are the same, cool."); 

int square(int x) { return x*x; } 

Signature* pf = square; // pf is a function pointer, easy 
Signature f;    // but what the hell is this? 
f(42);     // this compiles but doesn't link 

non possono essere assegnati La variabile f, ma può essere chiamato. Strano. A cosa serve allora?

Ora, se io const-qualificare il typedef, posso ancora usare per costruire altri tipi ma a quanto pare non per altro:

typedef int ConstSig(int) const; 

typedef std::function<int(int) const> std_fun_3; 
typedef std::function<ConstSig>  std_fun_4; 

static_assert(std::is_same<std_fun_3, std_fun_4>::value, 
       "Also the same, ok."); 

ConstSig* pfc = square; // "Pointer to function type cannot have const qualifier" 
ConstSig fc;   // "Non-member function cannot have const qualifier" 

Che remoto angolo della lingua ho colpito qui? Come si chiama questo strano tipo e cosa posso usarlo al di fuori dei parametri del template?

+0

Lo standard consente semplicemente di dichiarare * * funzioni attraverso un typedef per la loro firma (in realtà, tipo di funzione). – Xeo

risposta

15

Questo è il paragrafo pertinente dello standard. Parla praticamente da solo.

8.3.5/10

Un typedef del tipo di funzionamento può essere utilizzato per dichiarare una funzione, ma non devono essere utilizzati per definire una funzione (8.4).

Esempio:

typedef void F(); 
F fv;   // OK: equivalent to void fv(); 
F fv { }  // ill-formed 
void fv() { } // OK: definition of fv 

Un typedef di un tipo di funzione cui dichiaratore comprende un cv-qualificazione-seq possono essere utilizzate soltanto per dichiarare il tipo di funzione per una funzione membro non statica, a dichiarare il tipo di funzione a cui fa riferimento un puntatore al membro o dichiarare il tipo di funzione di primo livello di un'altra dichiarazione typedef di una funzione.

Esempio:

typedef int FIC(int) const; 
FIC f;    // ill-formed: does not declare a member function 
struct S { 
    FIC f;    // OK 
}; 
FIC S::*pm = &S::f; // OK 
+0

Eccellente. Questa è esattamente l'informazione che stavo cercando. Grazie. – marton78

+0

Grazie! Avrei dovuto accorgermene prima. – Bikineev

0

Nel tuo caso, std_fun_1 e std_fun_2 sono oggetti identici con le stesse firme di tipo. Sono entrambi std::function<int(int)> e possono entrambi contenere puntatori di funzione o oggetti richiamabili di tipo int(int).

pf è un puntatore a int(int). Cioè, serve lo stesso scopo di base di std::function, ma senza il meccanismo di quella classe o supporto per le istanze di oggetti chiamabili.

Analogamente, std_fun_3 e std_fun_4 sono oggetti identici con firme di tipo identico e possono sia contenere puntatori di funzione o oggetti richiamabili di tipo int(int) const.

Allo stesso modo, pfc è un puntatore a funzione di tipo int(int) const e può contenere puntatori a funzioni di quel tipo, ma non istanze di oggetti chiamabili.

Ma f e fc sono dichiarazioni di funzione .

La linea:

Signature fc; 

è identicamente equivalente a:

int fc(int) const; 

Che è una dichiarazione di una funzione denominata fc di tipo int(int) const.

Non c'è niente di strano da fare qui. Ti sei semplicemente imbattuto in sintassi che probabilmente già comprendi, da una prospettiva a cui non sei abituato.