2014-10-17 13 views
5

ich über den folgenden Code kam:Was bedeutet der Typ "char (& (...)) [2]"?

char (&f(...))[2];

ich die Art der geprüft (typeid und C++ filt verwenden) und bekam:

char (&(...)) [2]

Aber ich kann nicht Machen Sie einen Sinn für diesen Typ. Der [2] ist der Teil, der mich abwirft. Ohne sie kann den Typen I in einer Funktionsdefinition replizieren, zum Beispiel:

char (&f(...))

f ist vom gleichen Typ wie in h (zumindest von dem Ausgang des typeid + C++ filt):

char& h(...)

+0

Bitte geben Sie den vollständigen Kontext ein, in dem dieser Code angezeigt wird. –

+0

ist es nicht Referenz auf Array von 2 Funktionen, die char zurückgeben und C-Stil Elipse nehmen? – Creris

+3

Es ist eine Funktion, die einen Verweis auf ein Array von zwei Zeichen zurückgibt. Der zweite ('char (& f (...))') ist eine Funktion, die einen Verweis auf ein Zeichen zurückgibt. Die äußere Klammer ist im zweiten Fall überflüssig und in beiden Fällen ist "..." ein C variadic Argument-Pack. – 0x499602D2

Antwort

3

Es ist eine Funktionsdeklaration, die Anzahl der Parameter variiert ist, und kehrt zu einem Zeichen-Array aus zwei Elementen eine Referenz.

Es könnte einfacher erklärt werden, indem Sie ein Typedef verwenden. Zum Beispiel

typedef char char_array[2]; 

char_array & f(...); 
2

können Sie cdecl verwenden und einen beliebigen Typ für die Ellipse ersetzen, wie int:

char (&f(int)) [2] 

führt zu

erklären f als Funktion (int) wiederkehrende Referenz zu Array 2 von char [...]

Ersatz zurück und Sie haben Ihre Erklärung in Worte gefasst.

2
char (&f(...))[2]; 

Dies ist die Deklaration einer Funktion, die einen Verweis auf ein Array von zwei Zeichen zurückgibt. Die Klammern müssen syntaktisch korrekt sein. Andernfalls wird die & an char binden und es wird einen Syntaxfehler geben, weil [2] bedeutungslos ist.

Die Syntax kann mit einem Typalias zerlegt werden. Zum Beispiel:

using array_ref = char (&)[2]; 
array_ref f(...); 

Der Grund für einen Verweis auf ein Feld zurückkehrt, anstatt eine tatsächliche Anordnung ist aufgrund der Tatsache, dass nicht-Arrays von Funktionen zurückgebracht werden kann. Es ist unmöglich. Sie können nur Referenzen oder Zeiger auf Arrays zurückgeben, genau wie Funktionen. In allen Beispielen ist ... ein C variadic argument pack.


Die einzigen Orte, an denen ich diese Art von Syntax gesehen habe ist, wo ist es für SFINAE als Teil der Funktion der Überladungsauflösung verwendet wird. In der Regel wird diese Funktion von einer gleichnamigen Überladung begleitet, bei der die Vorlagenersetzung zum Überprüfen eines Attributs eines bestimmten Typs verwendet wird.Wenn ein Substitutionsfehler auftritt, wird die zweite Überladung (diejenige, die ein variadisches Paket annimmt) als Fallback gewählt. Sein Rückgabetyp unterscheidet Erfolg oder Misserfolg.

Zum Beispiel, hier ist Charakterzug Klasse, die, wenn ein Typ überprüft hat eine Memberfunktion f():

template <typename T> 
struct has_f 
{ 
private: 
    using true_type = char (&)[1]; 
    using false_type = char (&)[2]; 

    template <typename U> 
    static decltype(std::declval<U>().f(), true_type()) f(int); 

    template <typename> 
    static false_type f(...); 
public: 
    static constexpr bool value = sizeof(check<T>(0)) == 1; 
}; 

Wie Sie sehen können, wenn T eine Memberfunktion f() hat, dann ist die Größe des Typs zurückgegeben werden 1, sonst 2. true_type und false_type werden heutzutage weitgehend durch die Standard-Merkmalsklassen std::true_type und std::false_type ersetzt, aber dies ist nur ein Beispiel, um seine Verwendung zu veranschaulichen.