2013-07-03 9 views
11

Ich habe ein Problem zu verstehen, Funktionstypen (sie erscheinen zum Beispiel als Signature Template-Parameter eines std::function):C++ Funktionstypen

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 

Die Variable f kann nicht zugeordnet werden, sondern bezeichnet werden kann. Seltsam. Wofür ist es dann gut? Jetzt

wenn ich const qualifizieren die typedef, ich es noch weitere Typen erstellen können aber offenbar für nichts anderes:

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" 

Welche entfernten Ecke der Sprache habe ich getroffen hier? Wie wird dieser seltsame Typ aufgerufen und was kann ich außerhalb von Template-Parametern verwenden?

+0

Der Standard einfach ermöglicht es Ihnen, * bis * Funktionen über eine typedef ihrer Unterschrift erklären (eigentlich Funktionstyp). – Xeo

Antwort

15

Hier ist der relevante Absatz aus dem Standard. Es spricht ziemlich viel für sich.

8.3.5/10

A typedef Funktionstyp kann verwendet erklären verwendet werden, eine Funktion, jedoch nicht eine Funktion (8.4) zu definieren.

Beispiel:

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

A typedef eines Funktionstyps, dessen declarator a umfasst cv-Qualifier-seq nur verwendet werden, wird der Funktionstyp für eine nicht-statische Elementfunktion zu erklären, um Deklarieren Sie den Funktionstyp, auf den sich ein Zeiger auf Member bezieht, oder deklarieren Sie den Top-Level-Funktionstyp einer anderen Funktionstypdef-Deklaration.

Beispiel:

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

Ausgezeichnet. Das ist genau die Information, nach der ich gesucht habe. Vielen Dank. – marton78

+0

Danke! Ich hätte es früher bemerken sollen. – Bikineev

0

In Ihrem Fall sind std_fun_1 und std_fun_2 identische Objekte mit identischen Typ-Signaturen. Sie sind beide std::function<int(int)> und können sowohl Funktionszeiger als auch abrufbare Objekte vom Typ int(int) enthalten.

pf ist ein Zeiger auf int(int). Das heißt, es dient dem gleichen grundlegenden Zweck wie std::function, aber ohne die Maschinerie dieser Klasse oder Unterstützung für Instanzen von Callable Objects.

Ebenso sind std_fun_3 und std_fun_4 identische Objekte mit identischen Typ-Signaturen und können sowohl Funktionszeiger als auch aufrufbare Objekte vom Typ int(int) const enthalten.

In ähnlicher Weise ist pfc ein Funktionszeiger vom Typ int(int) const und kann Zeiger auf Funktionen dieses Typs halten, aber keine Instanzen von aufrufbaren Objekten.

Aber f und fc sind Funktionsdeklarationen.

Die Linie:

Signature fc; 

Ist identisch äquivalent zu:

int fc(int) const; 

, die eine Erklärung für eine Funktion fc vom Typ int(int) const benannt ist.

Hier passiert nichts Seltsames. Sie sind einfach auf eine Syntax gestoßen, die Sie wahrscheinlich bereits aus einer Perspektive kennen, die Sie nicht gewohnt sind.