2013-01-17 7 views
10

Da Sie ganzzahlige Werte als Template-Parameter verwenden und arithmetische Berechnungen an ihnen vornehmen können, was ist die Motivation hinter boost :: mpl :: int_ <> und anderen Integralkonstanten? Gilt diese Motivation in C++ 11 noch?Warum hat Boost MPL Integralkonstanten?

+6

Wenn dies wirklich von Interesse ist, lesen Sie das Buch "C++ Template Metaprogramming", von den Hauptautoren von Boost MPL, es erklärt die Motivationen hinter all diesen Arten von Dingen. Und dies gilt nicht nur für C++ 11, sondern wurde in C++ 11 mit [std :: integral_constant] (http://en.cppreference.com/w/cpp/types/integral_constant) zum Standard gemacht. –

Antwort

12

können Sie ganzzahlige Werte als Template-Parameter, aber Sie können nicht nehmen beide Typen und nicht-Typ Template-Parameter mit einer einzigen Vorlage. Lange Geschichte kurz, Behandlung Nicht-Typ-Vorlage Parameter als Typen ermöglicht es ihnen mit einer Vielzahl von Dingen innerhalb MPL verwendet werden.

Betrachten Sie zum Beispiel eine Metafunktion find, die mit Typen arbeitet und nach einem gleichen Typ innerhalb einer Sequenz sucht. Wenn Sie es mit Nicht-Typ-Vorlage Parameter verwenden möchten, müssten Sie neue Algorithmen 'Überladungen', eine find_c, für die Sie den Typ des Integralwerts manuell angeben müssen. Nun stellen Sie sich vor, Sie möchten, dass es mit gemischten integrierten Typen wie der Rest der Sprache funktioniert, oder dass Sie Typen und Nicht-Typen mischen möchten, erhalten Sie eine Explosion von "Überladungen", die auch passieren schwieriger zu verwenden, da Sie den Typ jedes Nicht-Typparameters überall angeben müssen.

Diese Motivation gilt immer noch in C++ 11.

wird diese Motivation zu C gelten nach wie vor ++ y und andere Version, es sei denn, wir haben einige neue Regel, die Umwandlung von nicht-Typ Template-Parameter-Typ Template-Parameter erlaubt. Wenn Sie beispielsweise 5 verwenden und die Vorlagenanforderungen einen Typ anfordern, instanziieren Sie ihn stattdessen mit std::integral_constant< int, 5 >.

+2

C++ y? Ich dachte, es war C++ 1y? –

13

tldr; Wenn ein Wert als Typ codiert wird, kann er an viel mehr Stellen als an einem einfachen Wert verwendet werden. Sie können Typen überladen, Sie können Werte nicht überladen.

K-Ballos Antwort ist großartig.

Es gibt noch etwas anderes, das ich für relevant halte. Die Integral-Konstantentypen sind nicht nur als Template-Parameter nützlich, sondern können auch als Funktionsargumente und Funktionsrückgabetypen nützlich sein (die C++ 11-Typen in meinen Beispielen verwenden, aber das gleiche Argument gilt für die Boost-Vorgänger):

template<typename R, typename... Args> 
    std::integral_constant<std::size_t, sizeof...(Args)> 
    arity(R (*)(Args...)) 
    { return {}; } 

Diese Funktion benötigt einen Funktionszeiger und gibt einen Typ zurück, der die Anzahl der Argumente angibt, die die Funktion benötigt. Bevor wir constexpr Funktionen hatten, gab es keine Möglichkeit, eine Funktion in einem konstanten Ausdruck aufzurufen, also Fragen zu stellen wie "wie viele Argumente nimmt dieser Funktionstyp?" Sie müssten einen Typ zurückgeben und den ganzzahligen Wert daraus extrahieren.

Auch mit constexpr in der Sprache (was bedeutet, dass die obige Funktion könnte nur return sizeof...(Args); und dieser Integer-Wert wäre zur Kompilierzeit verwendbar) gibt es immer noch gute Verwendungen für integrale Konstante Typen, z.Tag Disposition:

template<typename T> 
    void frobnicate(T&& t) 
    { 
    frob_impl(std::forward<T>(t), std::is_copy_constructible<T>{}); 
    } 

Diese frob_impl Funktion kann als zweites Argument übergeben auf der Grundlage der integer_constant<bool, b> Typ überlastet werden:

template<typename T> 
    void frob_impl(T&& t, std::true_type) 
    { 
    // do something 
    } 

template<typename T> 
    void frob_impl(T&& t, std::false_type) 
    { 
    // do something else 
    } 

Sie versuchen, etwas Ähnliches zu tun könnte, indem der boolean einen Template-Parameter:

aber es ist nicht möglich, eine Funktionsvorlage teilweise zu spezialisieren, so dass Sienicht machen konntenund frob_impl<false, T> verschiedene Dinge tun. Überladen auf Typ der booleschen Konstante können Sie leicht verschiedene Dinge auf der Grundlage der Wert der "ist Kopie konstruierbar" Eigenschaft, und , dass ist immer noch sehr nützlich in C++ 11.

Eine andere Stelle, an der die Konstanten nützlich sind, ist das Implementieren von Merkmalen mit SFINAE. In C++ 03 bestand der herkömmliche Ansatz darin, Funktionen überladen zu haben, die zwei Typen mit unterschiedlichen Größen (z. B. int und eine Struktur mit zwei int s) zurückgeben und den "Wert" mit sizeof testen. In C++ 11 können die Funktionen true_type und false_type zurückgeben, was viel aussagekräftiger ist, z. Eine Eigenschaft, die testet "Hat dieser Typ ein Element namens foo?" kann die Funktion, die ein positives Ergebnis anzeigt, true_type zurückgeben und die Funktion, die ein negatives Ergebnis anzeigt, zurückgeben false_type, was könnte klarer als das sein?

Als Standardbibliothek Implementierer Ich mache sehr häufige Verwendung von true_type und false_type, weil eine Menge von Compile-Zeit „Fragen“ wahr/falsch beantwortet hat, aber wenn ich will etwas testen, die mehr als zwei haben kann andere Ergebnisse werde ich andere Spezialisierungen von integral_constant verwenden.

+0

Was ist los mit 'foo' und' bar'? : P –

+0

Andere metasytaktische Variablen brauchen auch Liebe! –

Verwandte Themen