Polymorphie Adé
-
Jo, type erasure. std::function funktioniert so. Manchmal ist das so flexibler als mit Vererbung (hier ... naja).
Das mit const/immutable und COW verstehe ich nicht ganz, das const kann da genasogut entfernt werden. Gleich mit multithreading.
Vielleicht meinte er const=threadsafe, aber das lässt sich nicht so recht in Zusammenhang mit diesem Code bringen. Ok mal geraten:
objects[0] = class1()ist fast(tm) threadsafe. Um ganz threadsafe zu sein müsste unique_ptr mit einem atomic<model_t*> implementiert sein. Deshalb wahrscheinlich COW. Man macht alles const=threadsafe. Um zu verändert kopiert man das Zeugs und steckt das veränderte dann wieder rein. Aber deine Beschreibung, kp.
-
Naja, mir ist ja eben nicht so ganz klar, aus welcher Perspektive seine Sicht auf die ganze Sache stattfindet. Ich denke eben gerade an GUI-Applikation und er hat da vorher von Task-Chains und Task-Graphen geredet etc..
Es ging ihm dann vor allem darum, dass wenn mehrere Mutable-Referenzen auf ein Objekt draußen sind, dann kann an einer lokalen Stelle nicht darauf schließen wie es hier funktioniert, weil ein anderer Thread das Model zum gleichen Zeitpunkt verändern kann.
Und ich kann mir diesen Ansatz wirklich überhaupt nicht praktikabel vorstellen, es sei denn, diese Objekte sind eher als Nachrichtenpakete zwischen Tasks in einem Threadpool zu verstehen.
Es gibt doch nunmal einfach Problemstellungen, bei denen natürlicherweise mehrere "weit entfernte" Codestellen eine Mutable-Referenz (egal ob jetzt durch Zeiger, oder PIMPL/Handle/Type-Erasure-Superproxies) auf dasselbe Objekt im Speicher halten. Er sagt aber in dem Talk, er sei nicht davon überzeigt, dass Immutable irgendeine Einschränkung wäre.
Diese Stelle des Vortrags war eben bei Going Native 2013 und das ganze beim Zeitstempel 3:43:30 unter der Überschrift "No Raw Pointers".
-
Ohne das jetzt überprüft zu haben: Es klingt nach Sean Parent. Da hatte ich schon einmal einen Vortrag von ihm zum Thema "value semantics and concepts based polymorphism" gesehen. COW kam auch drin vor. Und das Anwendungsbeispiel war ja relevant. Die haben mit dem Ansatz angeblich Photoshop eine komplett neue Implementierung von undo/redo spendiert. Das mit dem
constda ist mir aber neu. Muss ich mir heute Abend mal reinziehen, wenn ich mehr Zeit habe.<OT>
Die Strousttrup-Vorträge hauen mich irgendwie auch nicht mehr vom Hocker. Hatte gestern da mal reingezappt und fragte mich, wie sinnig Konzepte (concepts) sind, die nur für genau eine Funktion aus <algorithm> gemacht wurden: Sortable, Mergable. Und die Verlagerung der Komplexität der Requirments aus std::merge nach Mergable war jetzt eine Leistung? "Guckt mal, jetzt steht da nur noch requires Mergable<...>()". Toll, dafür hast du jetzt ein dickes unnützes Mergable-Konzept.
</OT>
-
Ja, das war er glaube ich.
War der Vortrag, von dem Du sprichst "kostenlos sichtbar"? Würde ich mir gerne anschauen. Ich glaube, er sagte auch, er würde noch einen weiteren Vortrag halten auf der diesjährigen Going Native, vielleicht geht er da nochmal genauer drauf ein.
-
die Videoqualität ist leider nicht so toll:
http://isocpp.org/blog/2012/12/value-semantics-and-concepts-based-polymorphism-sean-parent
-
krümelkacker schrieb:
und fragte mich, wie sinnig Konzepte (concepts) sind, die nur für genau eine Funktion aus <algorithm> gemacht wurden
Genau so sinnig wie Funktionen die nur ein mal aufgerufen werden.
-
Ich stimme kk hier zu. Ein concept und eine Funktion sind voellig unterschiedliche Dinge. Waehrend bei einer Funktion die Implementierung von aussen betrachtet voellig egal ist, muss man bei einem Concept wissen, was die Anforderungen an den Typ sind. Letzten endes bringt das also rein gar nichts, meiner Meinung nach.
-
Kellerautomat schrieb:
Waehrend bei einer Funktion die Implementierung von aussen betrachtet voellig egal ist, muss man bei einem Concept wissen, was die Anforderungen an den Typ sind. Letzten endes bringt das also rein gar nichts, meiner Meinung nach.
Das Argument verstehe ich nicht. Ein Concept erfordert eine bestimmte Schnittstelle, keine bestimmte Implementierung. Du hast bei der Benutzung des Konzepts ebenso eine Abstraktion wie beim Aufruf einer Funktion.
Ob die einzelnen Konzepte wirklich einen Mehrwert bringen, ist dann eine andere Frage.
-
Alles klar, der Talk hat mir sehr geholfen. Fine-Grained COW usw. Das spielt zwar zusammen mit seinen PIMPL-Handles, aber im Prinzip sind das unterschiedliche Konzepte, die eben hier einfach zusammenwirken um möglichst Kosten für Value-Semantics zu zahlen.
Ich finde den PIMPL-Handle-Trick (Oder ihr nennt es Type-Erasure) eigentlich ganz nett, aber wie handhabt man nun, dass der Client-Code bei seinen Objekten eben die Kompatibilität sicherstellen kann?
Mit Basisklassen hilft einem schon die IDE dabei und sagt dass eine Implementierung fehlt, mit dieser Type-Erasure bekommt man wahrscheinlich eine große Menge unleserlicher Fehlermeldungen erst zur Compile-Zeit. Sollte man vielleicht noch auf Concepts warten, um sowas umzusetzen?
-
möglichst WENIG Kosten zu haben/zahlen oder soetwas wollte ich dort oben schreiben.
-
DerEineDaDuWeißtSchon schrieb:
Mit Basisklassen hilft einem schon die IDE dabei und sagt dass eine Implementierung fehlt, mit dieser Type-Erasure bekommt man wahrscheinlich eine große Menge unleserlicher Fehlermeldungen erst zur Compile-Zeit. Sollte man vielleicht noch auf Concepts warten, um sowas umzusetzen?
Man kann die Existenz von Memberfunktionen zur Compilezeit checken und dann static_asserts durchführen. Mit Concepts wäre das einfacher, aber ein simples
CONCEPT_CHECK(T, std::is_copy_constructible, std::is_nothrow_move_constructible, ...) was dann ein static_assert für jede Bedingung an T ausführt, ist schnell geschrieben.
-
Nexus schrieb:
Kellerautomat schrieb:
Waehrend bei einer Funktion die Implementierung von aussen betrachtet voellig egal ist, muss man bei einem Concept wissen, was die Anforderungen an den Typ sind. Letzten endes bringt das also rein gar nichts, meiner Meinung nach.
Das Argument verstehe ich nicht. Ein Concept erfordert eine bestimmte Schnittstelle, keine bestimmte Implementierung. Du hast bei der Benutzung des Konzepts ebenso eine Abstraktion wie beim Aufruf einer Funktion.
Ob die einzelnen Konzepte wirklich einen Mehrwert bringen, ist dann eine andere Frage.
Ein Concept hat keine "Implementierung", es ist eine Liste an Anforderungen und damit Teil des Interfaces. Bei einer Funktion trifft das nicht zu. Die Funktion ist also eine Abstraktion. Das Concept fuer eine einzige funktion nicht, es ist nur eine Verschiebung des Problems.
-
@Kellerautomat: Ja, das Problem wird verschoben, aber an eine Stelle wo es für den User einfacher ist.
Wenn du eine Funktion aufrufst, kann es sein, dass diese nicht direkt sort aufruft, sondern der Aufruf kann irgendwo tief in einer Kette von Aufrufen verfolgen. In dem Fall ist es gut, wenn du direkt im Interface der Funktion einstellen kannst, dass das übergebene Objekt sortable ist. Insbesondere wenn dann im aufrufstack noch wrappertypen und alles mögliche andere hinzu kommt, kann es für eher unerfahrene Programmierer - und die Welt besteht aus unerfahrenen Programmierern - unmöglich sein, den Fehlermeldungen des Compilers noch sinnvolle Informationen zu entnehmen.
Ich hab selbst erlebt, wie Leute quasi hilflos vor einer Din-A4 Seite langen Fehlermeldung saßen und einfach nicht wussten, wie sie damit umgehen sollen. Ein "Objekt ist nicht sortable" ist dann doch klarer.
---
Und natürlich kann ein freie Funtion als Teil des Interfaces angesehen werden:begin(container)
end(container)