Was sind die Unterschiede zwischen Konzepten und Vorlageneinschränkungen?

96

Ich möchte wissen, was die semantischen Unterschiede zwischen dem C ++ - Vorschlag für vollständige Konzepte und den Vorlagenbeschränkungen sind (z. B. Einschränkungen, wie sie in Dlang oder im neuen Konzept -Lite-Vorschlag für C ++ 1y enthalten sind ).

Was können vollwertige Konzepte, was Template-Einschränkungen nicht können?

Rayniery
quelle
2
Der Beschränkungsvorschlag geht darauf ein.
Chris
Ich erinnerte mich an 4.8 Entwerfen von Konzepten , aber es ist nicht viel darüber aufgeführt, wie Konzepte weitere Einschränkungen verursachen. Wenn überhaupt, könnten Googeln-Konzepte jetzt einige leicht erkennbare Unterschiede aufzeigen, nachdem sie ein besseres Verständnis der Einschränkungen aus dem Vorschlag gewonnen haben.
Chris
IMHO-Konzepte verbessern die Lesbarkeit und bieten klarere programmatische Fähigkeiten, wie sie vor langer Zeit von Alexander Stepanov in "Elements of Programming" gefordert wurden. Der Lite-Vorschlag ist nur ein Schritt in diese Richtung, um die Belastung durch seltsame Einschränkungen des Typs enable_if zu verringern, die derzeit erforderlich sind. Je früher desto besser für die generische Programmierung.
Dirvine

Antworten:

135

Die folgenden Informationen sind veraltet. Es muss gemäß dem neuesten Entwurf von Concepts Lite aktualisiert werden.

Abschnitt 3 des Beschränkungsvorschlags behandelt dies in angemessener Tiefe.

Der Konzeptvorschlag wurde für kurze Zeit in den Hintergrund gedrängt, in der Hoffnung, dass Einschränkungen (dh Concepts-Lite) in kürzerer Zeit konkretisiert und implementiert werden können, wobei derzeit zumindest etwas in C ++ 14 angestrebt wird. Der Einschränkungsvorschlag soll als reibungsloser Übergang zu einer späteren Definition von Konzepten dienen. Einschränkungen sind Teil des Konzeptvorschlags und ein notwendiger Baustein in seiner Definition.

Bei der Gestaltung von Konzeptbibliotheken für C ++ berücksichtigen Sutton und Stroustrup die folgende Beziehung:

Konzepte = Einschränkungen + Axiome

Um ihre Bedeutung schnell zusammenzufassen:

  1. Einschränkung - Ein Prädikat über statisch auswertbare Eigenschaften eines Typs. Rein syntaktische Anforderungen. Keine Domain-Abstraktion.
  2. Axiome - Semantische Anforderungen von Typen, von denen angenommen wird, dass sie wahr sind. Nicht statisch geprüft.
  3. Konzepte - Allgemeine, abstrakte Anforderungen von Algorithmen an ihre Argumente. Definiert in Bezug auf Einschränkungen und Axiome.

Wenn Sie also Einschränkungen (syntaktische Eigenschaften) Axiome (semantische Eigenschaften) hinzufügen, erhalten Sie Konzepte.


Concepts-Lite

Der Concepts-Lite-Vorschlag bringt uns nur den ersten Teil, Einschränkungen, aber dies ist ein wichtiger und notwendiger Schritt in Richtung vollwertiger Konzepte.

Einschränkungen

Bei Einschränkungen dreht sich alles um Syntax . Sie bieten uns die Möglichkeit, Eigenschaften eines Typs zur Kompilierungszeit statisch zu erkennen, sodass wir die als Vorlagenargumente verwendeten Typen basierend auf ihren syntaktischen Eigenschaften einschränken können. Im aktuellen Vorschlag für Einschränkungen werden sie mit einer Teilmenge der Satzrechnung unter Verwendung logischer Verknüpfungen wie &&und ausgedrückt ||.

Werfen wir einen Blick auf eine Einschränkung in Aktion:

template <typename Cont>
  requires Sortable<Cont>()
void sort(Cont& container);

Hier definieren wir eine Funktionsvorlage namens sort. Der Neuzugang ist die require-Klausel . Die require-Klausel enthält einige Einschränkungen für die Vorlagenargumente für diese Funktion. Diese Einschränkung besagt insbesondere, dass der Typ Contein SortableTyp sein muss. Eine nette Sache ist, dass es in einer prägnanteren Form geschrieben werden kann als:

template <Sortable Cont>
void sort(Cont& container);

Wenn Sie nun versuchen, etwas zu übergeben, das Sortablefür diese Funktion nicht berücksichtigt wurde , wird eine nette Fehlermeldung angezeigt, die Sie sofort darüber informiert, dass der abgeleitete Typ Tkein SortableTyp ist. Wenn Sie dies in C ++ 11 getan hätten, wäre in der sortFunktion ein schrecklicher Fehler aufgetreten , der für niemanden Sinn macht.

Constraints-Prädikate sind Typmerkmalen sehr ähnlich. Sie nehmen einen Vorlagenargumenttyp und geben Ihnen einige Informationen darüber. Einschränkungen versuchen, die folgenden Arten von Fragen zum Typ zu beantworten:

  1. Hat dieser Typ den einen oder anderen Operator überladen?
  2. Können diese Typen als Operanden für diesen Operator verwendet werden?
  3. Hat dieser Typ das eine oder andere Merkmal?
  4. Ist dieser konstante Ausdruck gleich dem? (für nicht typisierte Vorlagenargumente)
  5. Hat dieser Typ eine Funktion namens yada-yada, die diesen Typ zurückgibt?
  6. Erfüllt dieser Typ alle syntaktischen Anforderungen, die als solcher verwendet werden sollen?

Einschränkungen sollen jedoch keine Typmerkmale ersetzen . Stattdessen arbeiten sie Hand in Hand. Einige Typmerkmale können jetzt in Form von Konzepten und einige Konzepte in Form von Typmerkmalen definiert werden.

Beispiele

Das Wichtige an Einschränkungen ist also, dass sie sich nicht um die Semantik ein Jota kümmern. Einige gute Beispiele für Einschränkungen sind:

  • Equality_comparable<T>: Überprüft, ob der Typ ==mit beiden Operanden desselben Typs hat.

  • Equality_comparable<T,U>: Überprüft, ob es einen ==mit linken und rechten Operanden des angegebenen Typs gibt

  • Arithmetic<T>: Überprüft, ob der Typ ein arithmetischer Typ ist.

  • Floating_point<T>: Überprüft, ob der Typ ein Gleitkommatyp ist.

  • Input_iterator<T>: Überprüft, ob der Typ die syntaktischen Operationen unterstützt, die ein Eingabe-Iterator unterstützen muss.

  • Same<T,U>: Überprüft, ob der angegebene Typ identisch ist.

Sie können dies alles mit einem speziellen Concept-Lite-Build von GCC ausprobieren .


Jenseits von Concepts-Lite

Jetzt kommen wir zu allem, was über den Konzept-Lite-Vorschlag hinausgeht. Dies ist noch futuristischer als die Zukunft selbst. Alles von hier an wird sich wahrscheinlich ziemlich ändern.

Axiome

In Axiomen dreht sich alles um Semantik . Sie spezifizieren Beziehungen, Invarianten, Komplexitätsgarantien und andere solche Dinge. Schauen wir uns ein Beispiel an.

Während die Equality_comparable<T,U>Einschränkung wird Ihnen sagen , dass es eine ist , operator== die Arten nimmt Tund Ues wird Ihnen nicht sagen , was das Betrieb Mittel . Dafür werden wir das Axiom haben Equivalence_relation. Dieses Axiom besagt, dass wenn Objekte dieser beiden Typen mit dem operator==Geben verglichen werden true, diese Objekte äquivalent sind. Dies mag überflüssig erscheinen, ist es aber sicherlich nicht. Sie können leicht eine definieren operator==, die sich stattdessen wie eine verhält operator<. Du wärst böse, das zu tun, aber du könntest.

Ein anderes Beispiel ist ein GreaterAxiom. Es ist alles schön und gut zu sagen , zwei Objekte vom Typ im TVergleich zu können >und <Betreibern, aber was sie bedeuten ? Das GreaterAxiom sagt, wenn iff xgrößer ist y, dann yist kleiner als x. Die vorgeschlagene Spezifikation eines solchen Axioms sieht aus wie:

template<typename T>
axiom Greater(T x, T y) {
  (x>y) == (y<x);
}

Axiome beantworten also die folgenden Arten von Fragen:

  1. Haben diese beiden Operatoren diese Beziehung zueinander?
  2. Bedeutet dieser Operator für den einen oder anderen Typ dies?
  3. Hat diese Operation für diesen Typ diese Komplexität?
  4. Bedeutet dieses Ergebnis dieses Operators, dass dies wahr ist?

Das heißt, sie befassen sich ausschließlich mit der Semantik von Typen und Operationen für diese Typen. Diese Dinge können nicht statisch überprüft werden. Wenn dies überprüft werden muss, muss ein Typ in irgendeiner Weise verkünden, dass er dieser Semantik entspricht.

Beispiele

Hier sind einige gängige Beispiele für Axiome:

  • Equivalence_relation: Wenn zwei Objekte verglichen werden ==, sind sie gleichwertig.

  • Greater: Wann immer x > ydann y < x.

  • Less_equal: Wann immer x <= ydann !(y < x).

  • Copy_equality: Für xund yvom Typ T: if x == y, ein neues Objekt desselben Typs, das durch Kopierkonstruktion erstellt wurde T{x} == yund dennoch x == y(dh es ist nicht destruktiv).

Konzepte

Jetzt sind Konzepte sehr einfach zu definieren. Sie sind einfach die Kombination von Zwängen und Axiomen . Sie bieten eine abstrakte Anforderung an die Syntax und Semantik eines Typs.

Betrachten Sie als Beispiel das folgende OrderedKonzept:

concept Ordered<Regular T> {
  requires constraint Less<T>;
  requires axiom Strict_total_order<less<T>, T>;
  requires axiom Greater<T>;
  requires axiom Less_equal<T>;
  requires axiom Greater_equal<T>;
}

Zunächst ist zu beachten , dass für den Template - Typen Tsein Ordered, es muss auch die Anforderungen des gerecht RegularKonzepts. Das RegularKonzept ist eine sehr grundlegende Voraussetzung dafür, dass sich der Typ gut verhält - er kann konstruiert, zerstört, kopiert und verglichen werden.

Zusätzlich zu den Anforderungen, die Orderederfordern , dass Terfüllen eine Einschränkung und vier Axiome:

  • Einschränkung: Ein OrderedTyp muss eine haben operator<. Dies wird statisch überprüft, sodass es vorhanden sein muss .
  • Axiome: Für xund yvom Typ T:
    • x < y gibt eine strikte Gesamtbestellung.
    • Wann xist größer als y, yist kleiner als xund umgekehrt.
    • Wenn xkleiner oder gleich ist y, yist nicht kleiner als xund umgekehrt.
    • Wenn xgrößer oder gleich ist y, yist nicht größer als xund umgekehrt.

Wenn Sie solche Einschränkungen und Axiome kombinieren, erhalten Sie Konzepte. Sie definieren die syntaktischen und semantischen Anforderungen für abstrakte Typen zur Verwendung mit Algorithmen. Algorithmen müssen derzeit davon ausgehen, dass die verwendeten Typen bestimmte Operationen unterstützen und bestimmte Semantiken ausdrücken. Mit Konzepten können wir sicherstellen, dass die Anforderungen erfüllt werden.

Im neuesten Konzeptentwurf überprüft der Compiler nur, ob die syntaktischen Anforderungen eines Konzepts durch das Vorlagenargument erfüllt werden. Die Axiome bleiben unkontrolliert. Da Axiome Semantiken bezeichnen, die nicht statisch auswertbar sind (oder oft nicht vollständig überprüft werden können), müsste der Autor eines Typs explizit angeben, dass sein Typ alle Anforderungen eines Konzepts erfüllt. Dies war in früheren Entwürfen als Concept Mapping bekannt, wurde jedoch inzwischen entfernt.

Beispiele

Hier einige Beispiele für Konzepte:

  • Regular Typen sind konstruierbar, zerstörbar, kopierbar und können verglichen werden.

  • OrderedTypen unterstützen operator<und haben eine strikte Gesamtreihenfolge und andere Ordnungssemantik.

  • CopyableTypen sind kopierkonstruierbar, zerstörbar, und wenn sie xgleich sind yund xkopiert werden, wird die Kopie auch gleich verglichen y.

  • IteratorTypen müssen zugeordnet Typen haben value_type, reference, difference_type, und iterator_categorydie müssen sich bestimmte Konzepte erfüllen. Sie müssen auch unterstützen operator++und dereferenzierbar sein.

Der Weg zu Konzepten

Einschränkungen sind der erste Schritt in Richtung einer vollständigen Konzeptfunktion von C ++. Sie sind ein sehr wichtiger Schritt, da sie die statisch durchsetzbaren Anforderungen von Typen bereitstellen, damit wir viel sauberere Vorlagenfunktionen und -klassen schreiben können. Jetzt können wir einige der Schwierigkeiten und Hässlichkeiten std::enable_ifseiner und seiner Metaprogrammierfreunde vermeiden .

Es gibt jedoch eine Reihe von Dingen, die der Vorschlag für Einschränkungen nicht tut:

  1. Es bietet keine Konzeptdefinitionssprache.

  2. Einschränkungen sind keine Konzeptkarten. Der Benutzer muss seine Typen nicht speziell mit Anmerkungen versehen, um bestimmte Einschränkungen zu erfüllen. Sie werden statisch überprüft, indem einfache Sprachfunktionen zur Kompilierungszeit verwendet werden.

  3. Die Implementierungen von Vorlagen sind nicht durch die Einschränkungen ihrer Vorlagenargumente eingeschränkt. Das heißt, wenn Ihre Funktionsvorlage mit einem Objekt vom eingeschränkten Typ etwas tut, was sie nicht tun sollte, hat der Compiler keine Möglichkeit, dies zu diagnostizieren. Ein voll ausgestatteter Konzeptvorschlag wäre dazu in der Lage.

Der Einschränkungsvorschlag wurde speziell so konzipiert, dass zusätzlich ein vollständiger Konzeptvorschlag eingeführt werden kann. Mit etwas Glück sollte dieser Übergang ziemlich reibungslos verlaufen. Die Konzeptgruppe versucht, Einschränkungen für C ++ 14 (oder kurz darauf in einem technischen Bericht) einzuführen, während irgendwann um C ++ 17 herum vollständige Konzepte auftauchen könnten.

sftrabbit
quelle
5
Es ist zu beachten, dass Concepts-Lite die Einschränkungen nicht anhand der Implementierung der Vorlage selbst überprüft. Sie könnten also behaupten, dass jedes DefaultConstructable verwendet werden kann, aber der Compiler hindert Sie nicht daran, versehentlich einen Kopierkonstruktor zu verwenden. Ein umfassenderer Konzeptvorschlag wäre.
Nicol Bolas
24
Das ist ein erster Entwurf?!
Nicol Bolas
2
@sftrabbit, sehr gute Antwort. Aber ich habe eine Frage: Wie prüft ein Compiler, ob ein Typ die semantischen Anforderungen eines Konzepts erfüllt?
Rayniery
1
Werden die Axiome (mit viel Unsicherheit) zur Laufzeit überprüft oder dienen sie nur als Versprechensschilder?
Red XIII
4
@ScarletAmaranth: Weil es darauf hinausläuft, einen Satz in endlicher Zeit automatisch zu beweisen. Dies hat zwei Hindernisse: 1. Beweisen eines Satzes in endlicher Zeit, der theoretisch extrem schwierig und mit der gegenwärtigen Technologie unmöglich ist. 2. Sie können ein Axiom nicht beweisen, es sei denn, der Beweis basiert auf anderen Axiomen. (In diesem Fall wird es mathematisch "kein Axiom".) Diese Axiome sollen dem Compiler mitteilen, "Natürlich können Sie den Vergleich umkehren, wenn Sie es für nützlich halten ..." oder "Ja, ein EmptySet, das immer in einer Kreuzung verwendet wird." gibt das gleiche Ergebnis. "
Laurent LA RIZZA
4

Meine 2 Cent:

  1. Die Konzepte-lite Vorschlag wird nicht zu tun „Typprüfung“ der Vorlage gemeint Implementierung . Das heißt, Concepts-lite stellt (fiktiv) die Schnittstellenkompatibilität auf der Template-Instanziierungsseite sicher. Zitat aus dem Artikel: "Concepts Lite ist eine Erweiterung von C ++, die die Verwendung von Prädikaten zur Einschränkung von Vorlagenargumenten ermöglicht." Und das ist es. Es heißt nicht, dass der Vorlagenkörper (isoliert) gegen die Prädikate geprüft wird. Das bedeutet wahrscheinlich, dass es keine erstklassige Vorstellung von Archtypen gibt, wenn Sie über Concepts -Lite sprechen. Archtypen, wenn ich mich richtig erinnere, sind in konzeptlastigen Vorschlägen Typen, die nicht weniger und nicht mehr bieten, um die Implementierung der Vorlage zu befriedigen .

  2. konzepte-lite verwenden verherrlichte constexpr-Funktionen mit einem vom Compiler unterstützten Syntaxtrick. Keine Änderungen in den Suchregeln.

  3. Programmierer müssen keine Konzeptkarten schreiben.

  4. Abschließend noch einmal zitieren: "Der Einschränkungsvorschlag befasst sich nicht direkt mit der Spezifikation oder Verwendung der Semantik; er zielt nur auf die Überprüfung der Syntax ab." Das würde bedeuten, dass Axiome (bisher) nicht in den Geltungsbereich fallen.

Sumant
quelle