C++0x - late_check
-
Dravere schrieb:
Bist du dir da sicher, Sebastian Pizer?
Ich dachte bisher wirklich, dass erst bei der Angabe eines konkreten Typs geprüft wird, ob dieser dem Konzept entspricht.Ja, bin mir sicher. Das ist ja gerade der Witz bei
concepts. Du hast die Typüberprüfung auf zwei Seiten und kannst -- wenn der Compiler meckert -- sofort den Schuldigen ausmachen: War es der Template-Autor oder der Template-Benutzer?Wenn ihr den Google "Tech-Talk" von Doug Gregor noch nicht kennt und Euch für
concepts interessiert, kann ich das Video dazu empfehlen. Die einzigen Dinge, die nicht mehr aktuell zu sein scheinen, ist zum einen die "where clause" (wurde ja nach "requires clause" umbenannt) und das Konzept "For", was jetzt "Range" heißt.Gruß,
SP
-
hustbaer schrieb:
Das sofort zu überprüfen, und nicht erst wenn das Template das erste mal instanziert wird, macht natürlich Sinn.
Empfinde ich nicht wirklich. Es erscheint mir zu strikt zu sein.
Ich persönlich sehe darin zwei Nachteile:
1. Wenn ichConceptsverwenden will, dass darin immer alles berücksichtig werden muss. Also zum Beispiel:template<typename T> requires ArithmeticConcept<T> class Foo { private: T a; T b; public: Foo(T const& a, T const& b) : a(a) // brauch ich wohl noch CopyConstructible? Wargh ... , b(b) { } T bar() { return a + b; // ok ... } void floop() { a.floop(b); // brauch ich wohl noch ein Floopible? lol ... } };Gut, man könnte dann alles in einem gemeinsamen
FooConceptunterbringen. Aber was ist, wenn ich diese Klasse verwenden will mit einem Typ, welcher keinefloopFunktion hat, wobei ich allerdings sowieso nur die Funktionbarverwende?
Dann meckert der Kompiler sicher, dass mein Typ das KonzeptFloopiblenicht unterstützt. Und wenn ich das KonzeptFloopibleweglasse, dann wird in der ersten Phase gemeckert, weil die entsprechende Funktion in den verschiedenen Konzepten nicht gefunden wurde. Also müsste ich hierlate_checkverwenden, was ziemlich scheisse aussieht.Am Ende kommt es dann soweit, dass niemand die Konzepte verwendet, weil sie zu strikt sind.
2. Der Programmierer wird bevormundet und er hat grundsätzlich doppelte Schreibarbeit. Das Konzept folgt eigentlich bereits aus dem, was er in der Funktion oder wo auch immer hingeschrieben hat. Ich habe bisher die Konzepte als zusätzliche Hilfestellunge empfunden und nicht als Blockaden.
Ich wäre eher dafür, dass immer ein
late_checkgilt und es dafür einstrict_checkgeben würde. Oder vielleicht ganz optional machen, so dass man sagen kann, wie es in der Funktion gehandhabt werden soll ... also ca:template<typename T> requires // ... strict_check // oder late_check void foo() { // ... }@Sebastian Pizer,
Werde mir das Video mal anschauen, danke.Grüssli
-
Ich persönlich sehe darin zwei Nachteile:
1. Wenn ich Concepts verwenden will, dass darin immer alles berücksichtig werden muss.Das ist ja gerade der Sinn der Concepts. Ist für mich kein Nachteil, sondern ein Vorteil.
Und nochwas: bedenke dass es Concept-Maps gibt.
Ich kann z.B. eine Klasse haben, die eine Funktion X hat. Dann habe ich ein Concept "C", welches eine Funktion X braucht. Dummerweise ist die Semantik eine andere. Dank Concept-Maps kein Problem, ich packe die "Übersetzung" einfach in eine Concept-Map.
Wenn ein Template nun aber auf die Funktionen des Concepts "C" zugreifen will, den Constraint aber nicht angibt, dann funktioniert die "Übersetzung" mittels der Concept-Map nichtmehr -- woher soll der Compiler auch wissen dass er die Concept-Map anzuwenden hat?. Schlimmer noch, ich bekomme u.U. nichtmal nen Fehler, nämlich wenn die Signatur der Funktion X in der Klasse dummerweise mit der benötigten übereinstimmt, obwohl die Funktionalität eine andere ist. Es kompiliert, macht aber nicht das richtige. -> Nicht so toll.
2. Der Programmierer wird bevormundet und er hat grundsätzlich doppelte Schreibarbeit. Das Konzept folgt eigentlich bereits aus dem, was er in der Funktion oder wo auch immer hingeschrieben hat. Ich habe bisher die Konzepte als zusätzliche Hilfestellunge empfunden und nicht als Blockaden.
Sind ja auch keine Blockaden. Man muss ja keine Concepts verwenden wenn man nicht will. Und die Hilfestellung wäre IMO minimal (=der Nutzen wäre mir zu klein), wenn der Compiler nicht die "vollständigkeit" der Concepts checken würde.
-
Dravere schrieb:
Also zum Beispiel:
template<typename T> requires ArithmeticConcept<T> class Foo { private: T a; T b; public: Foo(T const& a, T const& b) : a(a) // brauch ich wohl noch CopyConstructible? Wargh ... , b(b) { }ArithmeticLikegibt es wirklich und beinhaltet recht viele Anforderungen. Eine davon istRegular, welches vonSemiRegular"ableitet", welchesCopyConstructibleundCopyAssignablebeinhaltet.Dravere schrieb:
T bar() { return a + b; // ok ... } void floop() { a.floop(b); // brauch ich wohl noch ein Floopible? lol ...Richtig. Man würde das dann so aufschreiben:
// Bedingungen, die nur die Syntax betreffen heißen in der // Regel HasXXX und sind "automatische" Konzepte: auto concept HasFloopMember<typename T, typename U> { typename result_type; result_type T::floop(U); }Das lässt sich dann noch beliebig verfeinern. ZB:
auto concept Floopible<typename T> : HasFloopMember<T,T> { requires SameType<result_type, void>; }Da eingebaute Typen aber keine Elementfunktionen besitzen und sich Elementfunktionen auch nicht per concept maps umliegen lassen, sollte man von der Nutzung von Elementfunktionen absehen.
Dravere schrieb:
Am Ende kommt es dann soweit, dass niemand die Konzepte verwendet,
Könnte durchaus sein. Man geht eh nicht davon aus, dass Otto Normalbürger, Konzepte schreibt, höchstens Konzept-Maps, damit er einen Algorithmus A aus Bibliothek B auf seine Datenstruktor D loslassen kann. Eine "konzeptisierte" Standardbibliothek ist schonmal nicht schlecht. Leider hat man mit diesem Sprachfeature wenig Erfahrung bisher sammeln können und es gibt auch keinen experimentellen Compiler, der auf dem aktuellen Stand ist und nicht gleich abkackt, wenn man ihm mal ein etwas komplizierteres Beispiel zu fressen gibt.
Gruß,
SP
-
und sich Elementfunktionen auch nicht per concept maps umliegen lassen
Huch? Wozu sollen die dann überhaupt gut sein???
-
Sebastian Pizer schrieb:
Könnte durchaus sein. Man geht eh nicht davon aus, dass Otto Normalbürger, Konzepte schreibt, höchstens Konzept-Maps, damit er einen Algorithmus A aus Bibliothek B auf seine Datenstruktor D loslassen kann.
Die Frage ist nur, wieviele Bibliotheken Konzepte haben werden.
Sebastian Pizer schrieb:
Eine "konzeptisierte" Standardbibliothek ist schonmal nicht schlecht. Leider hat man mit diesem Sprachfeature wenig Erfahrung bisher sammeln können und es gibt auch keinen experimentellen Compiler, der auf dem aktuellen Stand ist und nicht gleich abkackt, wenn man ihm mal ein etwas komplizierteres Beispiel zu fressen gibt.
Und deshalb sage ich jetzt auch mal nichts weiteres dazu. Ich lasse mich überraschen, wie es sein wird, damit eine Templatebibliothek zu schreiben.
Allerdings wie hustbaer frage ich mich da auch noch etwas:
Sebastian Pizer schrieb:
... und sich Elementfunktionen auch nicht per concept maps umliegen lassen ...
Meinst du mit Elementfunktionen Memberfunktionen? Wenn ich den letzten Standard Draft n2914 richtig verstehe, soll dies allerdings möglich sein.
concept MyConcept<typename T> { void T::foo() const; } class MyClass { public: void bar() const; }; concept_map<MyClass> { void MyClass::foo() const { bar(); } } template<typename T> requires MyConcept<T> void foobar(T const& obj) { obj.foo(); }Allerdings habe ich zum Teil sowieso etwas Mühe mit den Formulierungen. Oder hast du womöglich sogar etwas anderes damit gemeint?
Grüssli
-
hustbaer schrieb:
und sich Elementfunktionen auch nicht per concept maps umbiegen lassen
Huch? Wozu sollen die dann überhaupt gut sein???
Eine Konzeptdefinition besteht aus bis zu 3 Dingen:
- assoziierte Anforderungen (associated requirements)
- assoziierte Typen (associated types)
- assoziierte Funktionen (associated functions)Mit concept maps kannst Du sagen, dass ein Typ (oder mehere) das Konzept modellieren:
concept Foo<typename T> {} concept_map Foo<int> {}Hier gibt es keine Anforderungen. Trotzdem modelliert nur der Typ int das Konzept, weil's keine andere concept_map gibt.
Concept maps sind aber auch dazu da, zu sagen, wie ein Typ das Konzept modelliert. Du musst dabei alle Anforderungen erfüllen. Beispiel:
auto concept Foo<typename T> { typename blah; // assoziierter Typ typename lola; // assoziierter Typ blah blupp(T); // assoziierte Funktion } template<typename T> requires Regular<T> && Foo<T> void xxx(T x) { typedef Foo<T>::lola zzz; } struct meintyp {}; int blupp(meintyp const&); int g() { xxx(meintyp()); // Klappt nicht! }Hier versucht der Compiler eine concept map für
Foo<meintyp>zu finden. Da ich eine solche nicht angegeben habe und Foo einauto conceptist, versucht der Compiler die concept map automatisch zu generieren. Dazu werden u.a. auch Defaults beachtet (Du kannst Default-Funktionen und -Typen in concepts definieren). In diesem Fall findet der Compiler eine Funktionbluppim assoziierten Namensraum der Klassemeintyp, welche aufFoo<meintyp>::blupppasst -- auch wenn sie eine Referenz auf const als Parameter erwartet. Der Compiler kann sogar den assoziierten Typenblahherleiten (Foo<meintyp>::blahist einint, dablupp(meintyp)einintzurückgibt). Aber der Compiler weiß nicht, was der Typlolasein soll. Deswegen braucht man hier eine concept map:concept_map Foo<meintyo> { typedef bool lola; }Gruß,
SP
-
Dravere schrieb:
Allerdings wie hustbaer frage ich mich da auch noch etwas:
Sebastian Pizer schrieb:
... und sich Elementfunktionen auch nicht per concept maps umliegen lassen ...
Meinst du mit Elementfunktionen Memberfunktionen? Wenn ich den letzten Standard Draft n2914 richtig verstehe, soll dies allerdings möglich sein.
Wenn ich mich richtig erinnere, benutzt das Buch "Die C++ Programmiersprache" (deutsche Übersetzung der TC++PL special edition) den Begriff Elementfunktion für Funktionen, die im englischen Original "member functions" heißen. Das kann ich aber gerade nicht nachgucken, weil das Buch im Büro liegt und ich jetzt zu Hause sitze.
Dass man Elementfunktionen jetzt auch umbiegen kann, ist mir neu. Ich dachte, da gäb es Probleme mit der Namensauflösung. Lass mich mal grad in N2914 reingucken ...
Gruß,
SP
-
Sebastian Pizer schrieb:
Wenn ich mich richtig erinnere, benutzt das Buch "Die C++ Programmiersprache" (deutsche Übersetzung der TC++PL special edition) den Begriff Elementfunktion für Funktionen, die im englischen Original "member functions" heißen. Das kann ich aber gerade nicht nachgucken, weil das Buch im Büro liegt und ich jetzt zu Hause sitze.
Das konnte ich dafür gerade nachschauen. Die verwenden dort tatsächlich Elementfunktion. Wahrscheinlich aus der genialen Idee der 1:1 Übersetzung. Aber gut, wie soll man sie sonst auf Deutsch nennen. Member ist ja kein deutsches Wort

Sebastian Pizer schrieb:
Dass man Elementfunktionen jetzt auch umbiegen kann, ist mir neu. Ich dachte, da gäb es Probleme mit der Namensauflösung. Lass mich mal grad in N2914 reingucken ...
Bereich 14.10, bzw. 14.10.2.1
Ich bin wirklich gespannt, ob ich das Zeug richtig verstanden habe, denn ich hatte sehr viel Mühe, aus dem Text schlau zu werden.Grüssli
-
Sebastian Pizer schrieb:
Aber der Compiler weiß nicht, was der Typ
lolasein soll. Deswegen braucht man hier eine concept map:concept_map Foo<meintyo> { typedef bool lola; }Alternativ kann man eine Vorgabe machen:
concept Bar<typename T> { typename value_type = typename T::value_type; // ..... }was für eingebeute Typen natürlich nicht funktionieren kann. Dann braucht man wieder
concept_maps:template<typename T> concept_map Bar<T*> { typedef T value_type; // ..... }Gruß,
SP
-
Dravere schrieb:
Sebastian Pizer schrieb:
Dass man Elementfunktionen jetzt auch umbiegen kann, ist mir neu. Ich dachte, da gäb es Probleme mit der Namensauflösung. Lass mich mal grad in N2914 reingucken ...
Bereich 14.10, bzw. 14.10.2.1
Ich bin wirklich gespannt, ob ich das Zeug richtig verstanden habe, denn ich hatte sehr viel Mühe, aus dem Text schlau zu werden.Ich kann auch im aktuellen Entwurf keine Syntax für das Definieren von Pseudo-Elementfunktionen in
concept maps finden. Es gibt auch keine Beispiele, in denen soetwas gemacht wird. Das, was Du innerhalb einerconcept mapschreibst, ist ganz normaler Code:typedefs und Funktionen, die die Konzept-Anforderungen erfüllen müssen.Gruß,
SP
-
Sebastian Pizer schrieb:
Ich kann auch im aktuellen Entwurf keine Syntax für das Definieren von Pseudo-Elementfunktionen in
concept maps finden. Es gibt auch keine Beispiele, in denen soetwas gemacht wird. Das, was Du innerhalb einerconcept mapschreibst, ist ganz normaler Code:typedefs und Funktionen, die die Konzept-Anforderungen erfüllen müssen.Es hat keine Beispiele, aber einen Text, den ich so verstehe.
Kapitel 14.10.2.1 Associated Function Definitions
Abschnitt 4...
The expression E is defined differently depending on the associated function and the concept map definition. Let parm1, parm2, ..., parmN be the parameters of f (after substitution of the concept map arguments) and parm1', parm2', ..., parmN' be expressions, where each parmi' is an id-expression naming parmi. If the declared type of parmi is an lvalue reference type, then parmi' is treated as an lvalue, otherwise, parmi' is treated as an rvalue.For an associated member function (or member function template) in a type X (after substitution of the concept map arguments into the associated member function or member function template), let x be an object of type cv X, where cv are the cv-qualifiers on the associated member function (or member function template). If the requirement has no ref-qualifier or if its ref-qualifier is &, x is an lvalue; otherwise, x is an rvalue.
The expression E is defined as follows:
— If f is an associated non-member function or function template and the concept map contains one or more function or function template definitions with the same name as f, E is f(parm1', parm2', ..., parmN'), and the overload set of entities f consists of the definitions of f in the concept map. [Note: Unqualified lookup 3.4.1 and argument dependent lookup 3.4.2 are suppressed. —end note ].
— Otherwise, if f is a non-static associated member function and the concept map contains one or more member function or member function template definitions in the type X and with the same name as f, E is x.f(parm1', parm2', ..., parmN'), where name lookup of x.f refers to the definitions of X::f in the concept map.
...Schau ruhig noch die Bereich davor und danach an. Wie gesagt, womöglich verstehe ich es einfach nur falsch. Aber wenn nicht, dann bedeuetet der hervorgehobene Teil, dass in einer
concept_mapnach einer Definition einer Memberfunktion gesucht wird.Grüssli
-
Wie gesagt, es ist dazu keine Syntax definiert. Die Formulierungen in 14.10.2.1/3-4 finde ich auch etwas komisch. Ich schätze mal, dass mit "definitions of X::f in the concept map" die "requirement members" gemeint sind.
N2914, 14.10.2/3-4:
A concept map may contain two kinds of members: requirement members and members that satisfy requirements. The latter may be explicitly declared within the concept map, explicitly declared within a concept map for a more refined concept, or generated implicitly from a default implementation from the concept or one of its more refined concepts.
Each requirement member represents an entity (a single associated functio (14.10.1.1), associated type or associated class template (14.10.1.2) in the corresponding concept that must be satisfied as described below. The set of requirement members is the set of associated functions, associated types and associated class templates from the concept after substitution of the concept’s template parameters with the corresponding template arguments. [ Note: There is no way to explicitly declare a requirement member. — end note ]
Gruß,
SP
-
Sebastian Pizer schrieb:
Wie gesagt, es ist dazu keine Syntax definiert. Die Formulierungen in 14.10.2.1/3-4 finde ich auch etwas komisch. Ich schätze mal, dass mit "definitions of X::f in the concept map" die "requirement members" gemeint sind.
Nee, das macht auch keinen Sinn.

Gruß,
SP
-
hustbaer schrieb:
und sich Elementfunktionen auch nicht per concept maps umliegen lassen
Huch? Wozu sollen die dann überhaupt gut sein???
Elementfunktionen sind nicht die einzigen Funktionen, die zu einer Schnittstelle einer Klasse gehören. Das sind auch alle Funktionen, die im selben Namensraum definiert wurden und die Klasse in den Parametern "erwähnt".
Gute Artikel dazu sind die hier:
What's in a Class? -- Herb Sutter (1998)
Namespaces & Interface Principle -- Herb Sutter (1999)Ich bin mir zu 100% sicher, dass man in concept maps keine Elementfunktion definieren kann. Diskussionen gab es dazu schon öfters (bin aber gerade zu faul, die Threads rauszusuchen, siehe comp.std.c++).
Gruß,
SP
-
Sebastian Pizer schrieb:
Ich bin mir zu 100% sicher, dass man in concept maps keine Elementfunktion definieren kann. Diskussionen gab es dazu schon öfters (bin aber gerade zu faul, die Threads rauszusuchen, siehe comp.std.c++).
In einem Thread aus dem Jahr 2007 wurde es ganz klar verneint:
http://groups.google.de/group/comp.std.c++/browse_thread/thread/c0e76cd89d837dae/b70460b055918af5Aus einem Thread im Jahr 2009 wurde ich nicht mehr ganz schlau. Aber so wie sich das liest, haben auch andere Leute Probleme mit der Erklärung

http://groups.google.de/group/comp.std.c++/browse_thread/thread/c6a53c8e77f1937b/b879bd39eb75aeebEin schönes Fundstück ist dies:
Scott Meyers schrieb:
Oh, this is going to be fun to explain to people....
Thanks for the explanation, which, upon third reading, actually began to
make sense
Scott
-> http://groups.google.de/group/comp.std.c++/browse_thread/thread/6e1b78a38f7c16ef/c746c77e95e34eb7
Ich glaub, dass ich einfach mal noch warten werde, bis der Standard rauskommt. Dann lasse ich mir dass von jemandem erklären. Vielleicht kann dass ja Scott Meyers in einem guten Buch tun

Grüssli
-
Dravere schrieb:
Ein schönes Fundstück ist dies:
Scott Meyers schrieb:
Oh, this is going to be fun to explain to people....
Thanks for the explanation, which, upon third reading, actually began to
make sense
-> http://groups.google.de/group/comp.std.c++/browse_thread/thread/6e1b78a38f7c16ef/c746c77e95e34eb7
Ja, Scott Meyers meldet sich da öfters mal mit Teils super Beiträgen zu Wort. Es ist noch nicht so lange her, wo er zum Thema Rvalue-Referenzen und "perfect forwarding" mit diskutiert hat. Zuletzt hatte ich mich mit ihm zum Thema "Argument passing semantics for threads" gestritten -- und "gestritten" ist nicht übertrieben. Im Prinzip haben wir uns über knapp 50 Posts im Kreis gedreht.

Es ist aber beruhigend, dass auch Leute, wie Scott Meyers Schwierigkeiten haben, Rvalue-Referenzen zu verstehen. Dann muss ich mir auch nicht mehr so doof vorkommen, wenn ich daran denke, wie lange ich gebraucht habe, das alles zu raffen.

Gruß,
SP