Was ist der Unterschied zwischen C ++ 0x-Konzepte und die Boost-Concept Check Library (BCCL)?
-
20-09-2019 - |
Frage
Konzepte machte nicht die C ++ 0x-Standard, aber Erhöhung bietet noch Die Boost Concept Check Library (BCCL) . Ich denke, dass BCCL nicht alles abdecken, die in die C gemeint war ++ 0x-Standard. Was ist der Unterschied zwischen BCCL und der vorgeschlagenen C ++ 0x Lösung?
Lösung
Überprüfen der Template-Definition
Ein großer Unterschied der Konzepte zu diesen manuellen Lösungen ist, dass Konzepte der Definition einer Vorlage, damit seinen Typen-geprüft ohne etwas Besonderes zu tun. Das Konzept Check Bibliothek erlaubt nur die Verwendung von geprüft sein Typ. Beispiel:
template<typename InputIterator>
int distance(InputIterator a, InputIterator b)
{ return b - a; }
Sie können nun diese Vorlage mit Konzept überprüft und Eigenschaften streuen, aber Sie werden nie einen Fehler nach dieser Vorlage zu schreiben - weil der Standard der Compiler Verzögerung ermöglicht die Vorlage bis Instanziierung kompilieren. Zur Überprüfung, müssen Sie „Urform“ Klassen, die genau diese Vorgänge enthalten schreiben, die von der Schnittstelle erforderlich sind, und sie dann künstlich instanziiert.
in der Dokumentation von BCCL Lesen, fand ich es schon die gemeinsamen Urformen wie „default konstruierbar“ enthält. Aber wenn Sie Ihre eigenen Konzepte zu schreiben, müssen Sie auch Ihre eigenen Vorbilder liefern, was nicht einfach ist (Sie müssen genau das finden, die minimale Funktionalität eine Art zu schaffen hat). Zum Beispiel, wenn Ihr Urbild einen operator-
enthält, dann ist der Test der Vorlage mit dem (falschen) Urbild erfolgreich sein wird, obwohl die Konzepte nicht so einen Operator erforderlich.
Der abgelehnte Konzept Vorschlag schafft Vorbilder für Sie automatisch, basierend auf den Anforderungen, die festgelegt wurden und dass wurden implizierte (eine Zeigertyp T*
in einem Parameter verwendet werden, die PointeeType Anforderung für T
zum Beispiel bedeuten). Sie müssen nicht über diese Dinge kümmern müssen -. Außer natürlich, wenn Ihre Template-Definition einen Typfehler enthält
Überprüfen semantische Anforderungen
Betrachten Sie diesen Code, mit hypothetischen Konzept überprüft
template<ForwardIterator I>
void f(I a, I b) {
// loop two times!
loopOverAToB(a, b);
loopOverAToB(a, b);
}
Das BCCL Handbuch sagt, dass semantische Anforderungen sind nicht überprüft. Nur Syntax Anforderung und Typen geprüft. Betrachten wir eine Vorwärts-Iterator: Dort wird die semantische Anforderung besteht, dass Sie es in Multi-Pass-Algorithmen verwenden. Syntax-Prüfung wird nur nicht in der Lage sein, diese Anforderung zu testen (darüber nachdenken, was passiert, wenn ein Strom Iterator zufällig, dass der Check passieren würde!)
In dem abgelehnten Vorschlag, Sie hatten ausdrücklich auto
vor Konzept Definitionen setzen, um den Compiler-Flag Erfolg nach Syntax-Prüfung zu machen. Wenn auto
nicht angegeben wurde, dann eine Art explizit ein Konzept Karte zu definieren, zu sagen hatte es dieses Konzept unterstützt. Ein Strom Iterator würde also nie eine ForwardIterator Prüfung bestehen genommen werden.
Syntax Remapping
Dies war ein weiteres Merkmal. Eine Vorlage wie
template<InputIterator I>
requires OutputStreamable<I::value_type>
void f(I a, I b) {
while(a != b) std::cout << *a++ << " ";
}
Kann wie die folgenden verwendet werden, wenn der Benutzer ein Konzept Karte zur Verfügung stellen würde, die den Compiler lehrt, wie eine ganze Zahl dereferenzieren und damit wie eine ganze Zahl erfüllt das InputIterator Konzept.
f(1, 10);
Dies ist der Vorteil einer Sprache-basierte Lösung, und kann nicht immer durch BCCL gelöst werden, glaube ich.
Konzept basiert Overloading
Auf einem schnelles Lesen von BCCL, kann ich auch nichts erkennen, dass dies geschehen kann. Ein Konzept Matching Scheitern scheinen einen harten Kompilierungsfehler zu verursachen. Der abgelehnte Vorschlag ermöglicht die folgende:
template<ForwardIterator I>
I::difference_type distance(I a, I b) {
I::difference_type d = 0; while(a != b) ++a, ++d;
return d;
}
template<RandomAccessIterator I>
I::difference_type distance(I a, I b) {
return b - a;
}
Wenn ein Typ mit beiden Vorlagen verwendet werden könnte, dann wäre die zweite Vorlage verwendet werden, weil es mehr spezialisiert ist: RandomAccessIterator
verfeinert das ForwardIterator
Konzept.
Andere Tipps
Das C ++ 0x Konzept Merkmal wäre eine Kernsprachenfunktion , deren gesamten Prozess vom Compiler durchgeführt werden würde.
Die Boost-Konzept Bibliothek prüfen ist die fast gleiche Funktion, aber in C ++ geschrieben und Makro als Bibliothek einen Teil der Funktion zu simulieren. Es kann nicht alles tun, was in der letzten Sprache-Funktion erforderlich wäre (abhängig von der endgültigen Funktion Definition), aber einige äquivalenten Lösungen für Vorlagentypprüfung zur Verfügung stellen (und andere Kompilierung überprüft).
Wie bereits angedeutet, wie das C ++ 0x-Konzept ein Sprachfeature ist, würde es ermöglichen, elegantere semantische bereitzustellen und Compiler verwenden Informationen erlauben derzeit nicht zur Verfügung, um das Programm, so dass ausführlichere oder intelligente Fehler bei der Kompilierung (als das Konzept erste Ziel ist die abstrakte Typprüfung in Templates) zu ermöglichen.
Disclaimer: Ich war erfolgreich BCCL nicht in der Lage innerhalb der letzten 30 Minuten zu verwenden, obwohl ich hatte schon Boost-installiert. Das Beispiel sehen Sie unten sieht OK nach der BCCL Dokumentation Boost 1,37 aber hat nicht funktioniert. Ich denke, dies gilt als Nachteil.
Mit BCCL Sie nur so etwas wie statische Behauptungen erhalten, während die Kern Sprachkonzept Funktion voll modular Typprüfung bietet und in der Lage, einige Funktionsvorlage von der Teilnahme an der Überladungsauflösung zu verhindern. Mit nativer Konzepten kann der Körper von einer eingeschränkten Vorlage sofort vom Compiler überprüft werden, während BCCL nicht die Compiler Prüfung nichts in dieser Hinsicht machen. Sie müssen manuell die Vorlage mit „arche Typ“ Parametern instanziiert, um zu sehen, wenn die Vorlage keine Operationen verwendet, die nicht verfügbar sind (zum Beispiel operator-- auf Vorwärts Iteratoren).
Wie bei der Überladungsauflösung hier ein Beispiel:
template<typename Iter>
void foo(Iter,Iter) {
BOOST_CONCEPT_ASSERT((RandomAccessIterator<Iter>));
}
void foo(long, int);
int main() {
foo(2,3); // compile-time error
}
Die Vorlage ist ein besseres Spiel, weil das Nicht-Template zu lange eine Umwandlung von int erfordert. Aber Instanziierung schlägt fehl, weil int kein Iterator ist. Sie erhalten eine nette Fehlermeldung es zu erklären, aber die nicht sehr befriedigend ist, ist es? Mit nativer Konzepte haben Sie geschrieben konnten
template<typename Iter>
requires RandomAccessIterator<Iter>
void foo(Iter,Iter) {}
void foo(long, int);
int main() {
foo(2,3); // OK, picks non-template foo
}
die Funktion Vorlage Hier wird nicht an der Überladungsauflösung, weil die Voraussetzung für T = int nicht erfüllt ist. Great!
Wir bekommen immer noch zu constrain Funktionsschablonen mit dem SFINAE Trick. C ++ 0x erweitert SFINAE auf Ausdrücke und zusammen mit decltype und Standardvorlage Argumente für Funktionsschablonen können wir schreiben
template<typename T> T&& make();
template<typename Iter, class = decltype( *make<Iter>() )>
void foo(Iter,Iter) {}
void foo(long, int);
int main() {
foo(2,3); // OK, picks non-template foo
}
In diesem Fall Vorlage Argument Abzug fehl leise , da der Compiler nicht weiß, was die Art des Ausdrucks * make
template <typename Iter
REQUIRES( RandomAccessIterator<Iter> )
>
void foo(Iter,Iter) {}
HTH, S