Kruze Frage zur Ermittlung der String-Länge
-
@(D)Evil: und wieder nicht exception safe. Und es muss "new char[len];" heissen, "i" ist nicht definiert.
@all: ist euch allen das (exception safety) eigentlich *so* egal, oder seht/glaubt/versteht ihr es nur nicht?
@noNeed 4 aNick: es IST praxisnah, wie man an hunderten und tausenden von (kommerziellen, hobby-, ...) Source-Codes sieht die m_x verwenden. Dass du es nicht magst ist deine Sache, bloss mach dich bitte nicht lächerlich indem du behauptest es wäre nicht praxisnah.
-
hustbaer schrieb:
Davon abgesehen finde ich es grausig this-> zu schreiben. "this" gibts für Fälle wo man den "this" Zeiger irgendwo übergeben muss, also für Dinge wie "ptr->Foo(this)". IMO sicher NICHT dafür dass man zwischen Membern und nicht Membern mit gleichem Namen unterscheiden kann. BTW: wenn man "m_" für Member verwendet hat man das Problem auch gleich garnicht.
In meinem Oberstübchen rumpelt was bezüglich this. Ich meine mich erinnern zu können, dass es bei Verwendung von templates angeraten sein kann, this->blabla zu benutzen. Hatte meine ich was mit Vererbung und name-lookup zu tun, ich suchs mal raus...
/edit:
Aalso. Bei abhängigen Basisklassen á latemplate <typename T> class D : public B<T> { };ist this-> nötig, um
a) virtuelle Funktionen der abhängigen Basisklasse aufzurufen (einB<T>::foo()würde virtualität verhindern)
b) Den lookup zu verzögern, wenn es z.B. eine Spezialisierung der Basisklasse vorhanden ist.
Ist im aktuellen Problem zwar nicht anwendbar, aber ganz ohne this-> kommt man nicht aus
-
Yo ich weiss.
Templates, besonders mit dependent base classes, sind eine ganz eigene Sache.
Ich denke es war klar was ich meinte, nämlich die verwendung von "this->" in "normalem" Code -- der eben ohne das auskommt, solange man nicht gerade Parameter/lokale Variablen gleich nennt wie Member.
Was IMO komplett pöse weil verwirrend ist.
-
Hi,
ich empfinde die Verwendung von "this->" (mal abgesehen von der meistens unnötigen Tipparbeit) eine Einschränkung der Generizität ... ebenso wie die direkte Qualifizierung mittels std:: - und lasse Beides deswegen (und die "m_"-Notation ebenfalls).

Gruß,
Simon2.
-
Simon2 schrieb:
ich empfinde die Verwendung von "this->" (mal abgesehen von der meistens unnötigen Tipparbeit) eine Einschränkung der Generizität ... ebenso wie die direkte Qualifizierung mittels std:: - und lasse Beides deswegen (und die "m_"-Notation ebenfalls).

Was hat den this und std:: mit Generizität zu tun?
-
Simon2 schrieb:
Hi,
ich empfinde die Verwendung von "this->" ... eine Einschränkung der Generizität ...
Es ist genau umgekehrt, da manche Konstrukte eben nur dann funktionieren, wenn man "this->" benutzt. Ergo man muß nur etwas mehr tippen verliert aber nichts.
Simon2 schrieb:
ebenso wie die direkte Qualifizierung mittels std::
Der unqualifizierte Zugriff auf den Namesraum std via using Direktive führt doch Namensräume ad absurdum. Gerade C++ Projekte sind meist keine Ex und Hopp Projekte, so daß es sehr sinnvoll ist die Lesbarkeit des Programmcodes sicherzustellen. std::vector ist nun einmal sehr viel informativer als vector. Letzteres kann irgend ein vector aus irgend einem Namensraum sein.
-
Runde 126 schrieb:
Simon2 schrieb:
ich empfinde die Verwendung von "this->" (mal abgesehen von der meistens unnötigen Tipparbeit) eine Einschränkung der Generizität ... ebenso wie die direkte Qualifizierung mittels std:: - und lasse Beides deswegen (und die "m_"-Notation ebenfalls).

Was hat den this und std:: mit Generizität zu tun?
Ma legt über den Namen hinaus bereits einen "Gültigkeitsbereich" (meint nicht C++-Scope - finde gerade keine bessere Bezeichnung) fest.
Was, wenn in einer späteren Version nicht mehr std::cout, sondern das semantisch identische myOwn::cout verwendet werden soll ?
Was, wenn eine Membervariable später "ausgelagert" wird (z.B. in den globalen Namensraum) ?=> Jeweils an 1000 Codestellen rumändern, statt da, wo es hingehört: In der Deklaration:
// Version 1: // A.h struct A { int x, y; A(); void f() const; void g(); }; // A.cpp #include <iostream> using std::cout; A::A() : x(0), y(0) {} void A::f() const { cout << x; } void A::g() { f(); ++y; }Zwischenzeitlich haben sich die Anforderungen ein wenig geändert, so dass f() und x eigentlich nicht mehr viel mit A zu tun haben.
// Version 2: // A.h struct A { int y; void g(); }; // A.cpp #include <MyTools> using myTools::cout; static int x = 0; void f() { cout << x; } // Code identisch mit oben void A::g() { f(); ++y; } // Code identisch... später alles ausgelagert:
// Version 2: // A.h struct A { int y; void g(); }; // A.cpp #include <MyTools> using myTools::f; void A::g() { f(); ++y; } // Code identischDas wäre mit this->x und this->f() mehr Getippe (mit mehr Fehlerpotential) geworden.
Gruß,
Simon2.
-
~john schrieb:
Simon2 schrieb:
Hi,
ich empfinde die Verwendung von "this->" ... eine Einschränkung der Generizität ...
Es ist genau umgekehrt, da manche Konstrukte eben nur dann funktionieren, wenn man "this->" benutzt....
Du beziehst Dich hier auf einen Spezialfall im template-name-lookup. In allen anderen Fällen verbaut man sich aber gerade die Anbindung an templates durch die Forderung von "this->"....
D.h. ich habe die Wahl, ob von 100 Idiomen 99 oder 1 funktionieren. Welcher Ansatz generischer ist, kann man IMHO deutlich ablesen.~john schrieb:
...
Der unqualifizierte Zugriff auf den Namesraum std via using Direktive führt doch Namensräume ad absurdum...Wieso sollte das der Fall sein ?
Im Gegenteil: Dass ich an einer zentralen Stelle "umswitchen" kann, stärkt die Bedeutung von namespaces.~john schrieb:
...Letzteres kann irgend ein vector aus irgend einem Namensraum sein.
Eben: Das nennt man Generische Programmierung !
Muss man nicht mögen oder einsetzen, ich halte es aber (gerade in größeren Projekten) für einen großen Vorteil.
Mit demselben Argument müsste man sonst auch overloading bei Funktionen wieder abschaffen, weil "... man ja gar nicht mehr sieht, welche Funktion aufgerufen wird...".Gruß,
Simon2.
-
Simon2 schrieb:
Was, wenn in einer späteren Version nicht mehr std::cout, sondern das semantisch identische myOwn::cout verwendet werden soll ?
Das wäre im Extremfall eine automatische Suchen&Ersetzen Aktion - kein Drama, da ja der Name "std::cout" eindeutig ist. Was bei "cout" nicht gewährleistet ist. Wenn man den Ausgabestrom verändern können will, so sollte man das auch im Design berücksichtigen. Referenzen von std::cout oder anderen std::ostream lassen sich leicht erzeugen. Man sollte im Design immer darauf vorbereitet sein, daß man den Ausgabestrom umlenken kann,w enn man einen fest kodierten Bezug auf eine globale Variable nimmt (std::cout), ist das eindeutig nicht der Fall, und dann muß man mit den Defiziten leben.
-
~john schrieb:
...
Das wäre im Extremfall eine automatische Suchen&Ersetzen Aktion - kein Drama...Aber warum sollte ich das tun, wenn ich einfach nur ein einziges "using" umbiegen müsste ... was auch im vi prima funktioniert ?

BTW: Du solltest Dich nicht zu sehr am cout-Beispiel aufhängen. Das gilt genauso bei allen anderen Konstrukten.
Nochmal: Mit derselben Argumentation musst Du auch gegen overloading bei Funktionen sein, weil man da ja auch:
- vollqualifizierte Namen hat (f_int(int), f_char(char), ...),
- bei denen man sich keine "Sprachregel für die Namensauflösung" merken muss und
- die man ganz easy per Suchen&Ersetzen ändern kann.
Wie gesagt: Die Frage war hier nicht "Warum man (nicht) generisch programmieren soll ?", sondern: "Warum schränkt die Verwendung von this->/std:: die Generizität ein ?".
Und die beantwortest Du ganz eindeutig und richtig mit Deinem Wunsch nach "festen Bezügen".Gruß,
Simon2.
-
Simon2 schrieb:
In allen anderen Fällen verbaut man sich aber gerade die Anbindung an templates durch die Forderung von "this->"....
Beispiel?
Wieso sollte das der Fall sein ?
Im Gegenteil: Dass ich an einer zentralen Stelle "umswitchen" kann, stärkt die Bedeutung von namespaces.Da beliebige includes (man denke nur mal an die vielen C-Libraries) Kollisionen auslösen können, ist dies nicht sonderlich geschickt. Man kann ja Umbennungen von Namesräumen durchführen, so daß man im Projekt seine eigenen Benennung für einen Namensraum hat. Das erfüllt Deine Vorgabe, und man müllt den globalen Namenraum trotzdem nicht zu.
Eben: Das nennt man Generische Programmierung !
Diese Interpretation von generischer Programmierung kann ich nicht teilen. Typsicherheit ist zum Beispiel in Ada ein fundamentaler Bestandteil von generischer Programmierung, die C++ leider nicht im Kontext von Templates kennt. Man kann Templates leider beliebige Typen übergeben, so daß die von allen "geliebten" und sehr "aussagekräftigen" Fehlermeldungen auftreten. Man muß das Problem nicht vorsätzlich vergrößern, wenn es Möglichkeiten gibt es zu umgehen in dem man das Programm anders entwirft.
Mit demselben Argument müsste man sonst auch overloading bei Funktionen wieder abschaffen, weil "... man ja gar nicht mehr sieht, welche Funktion aufgerufen wird...".
Der Vergleich hinkt, da es sich um eine andere Problematik handelt.
Grüße
-
~john schrieb:
Simon2 schrieb:
In allen anderen Fällen verbaut man sich aber gerade die Anbindung an templates durch die Forderung von "this->"....
Beispiel?...
Habe ich oben schon gebracht. In Kurzform: mit "this->" nagele ich die Entscheidung fest, dass sich das gesuchte Element in meinem Vererbungsbaum befinden muss. Ohne kann ich ein passendes Element auch außerhalb finden => generischer.
~john schrieb:
Wieso sollte das der Fall sein ?
Im Gegenteil: Dass ich an einer zentralen Stelle "umswitchen" kann, stärkt die Bedeutung von namespaces.Da beliebige includes (man denke nur mal an die vielen C-Libraries) Kollisionen auslösen können, ist dies nicht sonderlich geschickt. ...
Was hat das denn damit zu tun ?
Gerade durch die namespaces werden doch Kollisionsmöglichkeiten aufgehoben (und zwar durch ein "using std::x;" exakt so wie ein permanentes "std::x..."~john schrieb:
Man kann ja Umbennungen von Namesräumen durchführen, so daß man im Projekt seine eigenen Benennung für einen Namensraum hat. Das erfüllt Deine Vorgabe, und man müllt den globalen Namenraum trotzdem nicht zu.
Das versehe ich jetzt gar nicht.
Ich habe auch nirgendwo von einer "Zumüllung des globalen namespaces" gesprochen und sehe auch keine....~john schrieb:
Typsicherheit ist zum Beispiel in Ada ein fundamentaler Bestandteil von generischer Programmierung, die C++ leider nicht im Kontext von Templates kennt. Man kann Templates leider beliebige Typen übergeben, so daß die von allen "geliebten" und sehr "aussagekräftigen" Fehlermeldungen auftreten. Man muß das Problem nicht vorsätzlich vergrößern, wenn es Möglichkeiten gibt es zu umgehen in dem man das Programm anders entwirft....
1.) templates sind absolut "typsicher" - genauso typsicher wie "nicht-template-Code", weil der Compiler letztlich "instantiierten Code" mit konkreten Typen sieht. Welche "Typsicherheit" und welche generische Programmierung ADA anbietet, weiß ich nicht, weil ich diese Sprache nicht beherrsche.
2.) Hier sprichst Du Dich halt gegen generische Programmierung wie sie C++ anbietet aus, weil sie Dir zu komplex erscheint. Macht ja nichts, aber es bleibt dabei: this->/std:: schränken die Generizität ein ! Du empfindest das als Vorteil, ich als Nachteil - damit ist doch die eigentliche Frage beantwortet.~john schrieb:
Mit demselben Argument müsste man sonst auch overloading bei Funktionen wieder abschaffen, weil "... man ja gar nicht mehr sieht, welche Funktion aufgerufen wird...".
Der Vergleich hinkt, da es sich um eine andere Problematik handelt.
Keineswegs !
In allen von Dir genannten Aspekten verhält sich overloading genau so wie templates => Alle Deine Argumente treffen ebenso auf overloading zu.
=> Du kannst nicht konsistent für das eine und gegen das andere sein.Gruß,
Simon2.
-
Simon2 schrieb:
Und die beantwortest Du ganz eindeutig und richtig mit Deinem Wunsch nach "festen Bezügen".
Es geht hier um Zusicherung von Eigenschaften von Objekten. Wenn ich in einem Programmteil "std::cout" (nur um bei diesem Beispiel zu bleiben) verwende, dann ist nur garantiert, daß der Code damit funktioniert. Wenn ich nun das einfach durch etwas anderes ersetze ist es dann wirklich garantiert, daß das ganze auch noch funktioniert wie vorgesehen? Weshalb wurde dann das Design nicht so gewählt, daß man "std::ostream" statt "std::cout" verwendet?
Fragen über Fragen für die ich bei Dir keine Anworten sehe.
Grüße
-
~john schrieb:
Simon2 schrieb:
Und die beantwortest Du ganz eindeutig und richtig mit Deinem Wunsch nach "festen Bezügen".
Es geht hier um Zusicherung von Eigenschaften von Objekten. Wenn ich in einem Programmteil "std::cout" (nur um bei diesem Beispiel zu bleiben) verwende, dann ist nur garantiert, daß der Code damit funktioniert. Wenn ich nun das einfach durch etwas anderes ersetze ist es dann wirklich garantiert, daß das ganze auch noch funktioniert wie vorgesehen? Weshalb wurde dann das Design nicht so gewählt, daß man "std::ostream" statt "std::cout" verwendet?....
Welche "Eigenschaften" soll denn ein Objekt zusichern und wie soll es das tun ?
Wohl doch über seine Schnittstelle ... und die wird immer exakt und identisch überprüft - unabhängig davon, ob ich mittels this->/std:: die Suche einschränke oder nicht (bei "std::" vs. "using std::" erhält man sogar dieselbe Suchmenge).~john schrieb:
...Wenn ich nun das einfach durch etwas anderes ersetze ist es dann wirklich garantiert, daß das ganze auch noch funktioniert wie vorgesehen? ...
(Schönes Beispiel, warum Du gegen overloading sein müsstest: Wer garantiert Dir, dass f(int) "dasselbe" macht wie f(char) ?)
zumm 1000ten Mal: Macht doch nichts, wenn Dir generische Programmierung zu kompliziert erscheint !
Mir persönlich ist sie das nicht - die Regeln zur Auflösung sind mir eindeutig genug und die entstandene Übersichtlichkeit und Flexibilität wert.~john schrieb:
Weshalb wurde dann das Design nicht so gewählt, daß man "std::ostream" statt "std::cout" verwendet?....
Auch das hat überhaupt nichts mit dem Thema zu tun. Ich wollte nie cout durch ostream ersetzen, sondern habe lediglich ein Beispiel gewählt.
Wenn es Dir so schwer fällt, davon zu abstrahieren, verwende ich zukünftig ein anderes:// Version 1 #include <HerstellerXLib.h> #using HerstellerXLib::calculate; template <typename T> T f(T t) { T ret = calculate(t); t++; ret += calculate(t); ret.setFlag(); return ret; }// Version 2 #include <HerstellerYLib.h> #using HerstellerYLib::calculate; //.... Rest bleibt so wie er war.~john schrieb:
Fragen über Fragen für die ich bei Dir keine Anworten sehe....
Vollkommen überflüssige Überdramatisierung, die inhaltlich wohl gar nicht weiterbringt .... 
Gruß,
Simon2.
-
Simon2 schrieb:
Habe ich oben schon gebracht. In Kurzform: mit "this->" nagele ich die Entscheidung fest, dass sich das gesuchte Element in meinem Vererbungsbaum befinden muss. Ohne kann ich ein passendes Element auch außerhalb finden => generischer.
Globale Namen gilt es wann immer möglich nicht zu verwenden, das ist ein fundamentaler Grundsatz in der OOP. "this->x" bezieht sich auf Instanzvariable, wenn man nun eine globale Variable hat, dann folgt diese nicht mehr der Semantik einer Instanzvariablen. Wenn ich also so einfach x aus der Klasse auswerfe und durch ein globales x ersetze, habe ich ganz anderes Problem, und ich muß so oder so richtiges Refactoring machen.
Simon2 schrieb:
Was hat das denn damit zu tun ?
Gerade durch die namespaces werden doch Kollisionsmöglichkeiten aufgehoben (und zwar durch ein "using std::x;" exakt so wie ein permanentes "std::x..."Leider stimmt das nicht, denn "x" kann nun "::x" oder "::std::x" sein, wenn beides deklariert ist, welches meinst Du denn?
Simon2 schrieb:
1.) templates sind absolut "typsicher" - genauso typsicher wie "nicht-template-Code", weil der Compiler letztlich "instantiierten Code" mit konkreten Typen sieht.
Nein, typsicher sind sie eben nicht, der Compiler merkt beim Compileren erst an der Stelle an der er eine Methode T::method benötigt, daß T diese Methode gar nicht kennt und es kommt zu den typischen C++ Template Fehlermeldungen. Mit Erfahrung weiß man wo der Fehler liegt, aber Anfänger kompatibel ist das nicht. Typsicher wäre es, wenn man sofort beim Instanzieren der Fehler bekommen würde: MyContainer<> benötigt folgende Methode "method", T stellt diese aber nicht zur Verfügung. Zwar schrebt Stroustrup in [The Design & Evolution of C++, Kapitel 15.4], daß eine solche Maßnahme überflüssig sei, aber wenn dem wirklich so wäre, dann gäbe es nicht solche Projekt wie die Boost Concept Check Library.
2.) Hier sprichst Du Dich halt gegen generische Programmierung wie sie C++ anbietet aus, weil sie Dir zu komplex erscheint.
Ich will das mal so formulieren, weder in "Modern C++ Design" noch "Generative Programming" wird so ein "generischer" Programmierstil propagiert wie Du ihn pflegst.
-
Eine Literaturempfehlung: C++ Templates von Vandervoorde, Josuttis
Simon2 schrieb:
Wenn es Dir so schwer fällt, davon zu abstrahieren, verwende ich zukünftig ein anderes:
// Version 1 #include <HerstellerXLib.h> #using HerstellerXLib::calculate; template <typename T> T f(T t) { T ret = calculate(t); t++; ret += calculate(t); ret.setFlag(); return ret; }Der Begriff Functor ist Dir wohl fremd?
Ich würde Dein Beispiel so umschreiben, kein include notwendig, kein using notwendig.
template <typename T, typename FO> T f(T t) { FO calculate; T ret = calculate(t); t++; ret += calculate(t); ret.setFlag(); return ret; }Oder man löst das über eine Traits bzw. Policy Class
template <typename T, typename Calculator> T f(T f) { T ret = Calculator::calculate(t); t++; ret += Calculator::calculate(t); ret.setFlag(); return ret; }Auch hier ist weder ein using noch ein include notwendig. Daher gibt es weniger Abhängigkeiten.
-
~john schrieb:
Nein, typsicher sind sie eben nicht, der Compiler merkt beim Compileren erst an der Stelle an der er eine Methode T::method benötigt, daß T diese Methode gar nicht kennt und es kommt zu den typischen C++ Template Fehlermeldungen. Mit Erfahrung weiß man wo der Fehler liegt, aber Anfänger kompatibel ist das nicht. Typsicher wäre es, wenn man sofort beim Instanzieren der Fehler bekommen würde: MyContainer<> benötigt folgende Methode "method", T stellt diese aber nicht zur Verfügung. Zwar schrebt Stroustrup in [The Design & Evolution of C++, Kapitel 15.4], daß eine solche Maßnahme überflüssig sei, aber wenn dem wirklich so wäre, dann gäbe es nicht solche Projekt wie die Boost Concept Check Library.
Der Compiler merkt bei der Instanziierung, wenn ein Typ nicht die geforderten Operationen hat. Daß die daraus resultierenden Fehlermeldungen etwas kryptisch sein können, steht auf einem anderen Blatt (und Lösungen wie Concept Check dienen auch nur dazu, die Fehlermeldungen lesbarer zu gestalten).
~john schrieb:
Der Begriff Functor ist Dir wohl fremd?
Ich würde Dein Beispiel so umschreiben, kein include notwendig, kein using notwendig.
Ist dir schonmal in den Sinn gekommen, daß die verwendeten Fremdbibliotheken nicht unbedingt auf deinen Programmierstil ausgerichtet sind?
-
Simon2 schrieb:
Runde 126 schrieb:
Simon2 schrieb:
ich empfinde die Verwendung von "this->" (mal abgesehen von der meistens unnötigen Tipparbeit) eine Einschränkung der Generizität ... ebenso wie die direkte Qualifizierung mittels std:: - und lasse Beides deswegen (und die "m_"-Notation ebenfalls).

Was hat den this und std:: mit Generizität zu tun?
Ma legt über den Namen hinaus bereits einen "Gültigkeitsbereich" (meint nicht C++-Scope - finde gerade keine bessere Bezeichnung) fest.
Was, wenn in einer späteren Version nicht mehr std::cout, sondern das semantisch identische myOwn::cout verwendet werden soll ?
Was, wenn eine Membervariable später "ausgelagert" wird (z.B. in den globalen Namensraum) ?=> Jeweils an 1000 Codestellen rumändern, statt da, wo es hingehört: In der Deklaration:
Also ich weiß ja, dass es in C++ keine richtigen Interfaces gibt, dafür kann man ja rein virtuelle Klassen machen. Aber dass man den namespace als Interface missbraucht ist mir neu und hat nichts mit Generizität zu tun. Das haut vielleicht bei cout hin, weil da alle Methoden jedem geläufig sind und es wahrscheinlich wieder mit den selben funktionen neu implementiert wird, wenn man es will. Aber wenn man sich mal sowas wie std::vector und math::vector vorstellt, dann hat das garnichts mit Interface zu tun.
// Version 1: // A.h struct A { int x, y; A(); void f() const; void g(); }; // A.cpp #include <iostream> using std::cout; A::A() : x(0), y(0) {} void A::f() const { cout << x; } void A::g() { f(); ++y; }Zwischenzeitlich haben sich die Anforderungen ein wenig geändert, so dass f() und x eigentlich nicht mehr viel mit A zu tun haben.
// Version 2: // A.h struct A { int y; void g(); }; // A.cpp #include <MyTools> using myTools::cout; static int x = 0; void f() { cout << x; } // Code identisch mit oben void A::g() { f(); ++y; } // Code identisch... später alles ausgelagert:
// Version 2: // A.h struct A { int y; void g(); }; // A.cpp #include <MyTools> using myTools::f; void A::g() { f(); ++y; } // Code identischDas wäre mit this->x und this->f() mehr Getippe (mit mehr Fehlerpotential) geworden.
Ich bin zwar auch nicht dafür überall this-> hinzuschreiben. Aber das hat nichts mit Generizität zu tun, sondern ist nur ein "Trick", damit du einfacher Refactoren kannst. Wenn du ein richtiges Refactoring Tool hättest (Wenns so ein gibt), dann bräuchtest du sowas nicht.
-
CStoll schrieb:
Ist dir schonmal in den Sinn gekommen, daß die verwendeten Fremdbibliotheken nicht unbedingt auf deinen Programmierstil ausgerichtet sind?
Wir waren eben bei dem Problem, daß die Verwendung von qualifizierten Namen angeblich die Generizität des Codes verringern würde. Wenn eine Fremdlibrary in einem deutlich anderen Stil geschrieben wurde: Wie wahrscheinlich ist es dann, daß ich sie ohne Wrapper als Substitution für eigenen Code verwenden kann?
Zum Stil: Da die Standard Library exakt dasselbe macht, ist das bei neueren Libraries mittlerweile unwahrscheinlicher als früher, aber es ist leider nicht auszuschließen, daß es zu Problemen kommt. Trotzdem halte ich es für erstrebenswert konfigurierbare Eigenschaften von Klassen auch durch deren Parametrisierung zum Ausdruck zu bringen. Eine Wrapperklasse für einen Funktionszeiger ist schnell geschrieben, so daß dieser wie ein Functor genutzt werden kann.
-
~john schrieb:
...
Globale Namen gilt es wann immer möglich nicht zu verwenden, das ist ein fundamentaler Grundsatz in der OOP. ....Seltsam nur, dass ich in keinem der von mir gelesenen Bücher (2x"exceptional", 2x"effective", "Gotchas", "C++ Templates: The Complete Guide" oder in "imperfect C++") dieser "fundamentale Grundsatz der OOP" erwähnt wird, noch sich in deren Codesamples niederschlägt.
~john schrieb:
...
Nein, typsicher sind sie eben nicht, der Compiler merkt beim Compileren erst an der Stelle an der er eine Methode T::method benötigt, daß T diese Methode gar nicht kennt ...Und wann merkt der C++-Compiler das bei "normalen" Typen ?
~john schrieb:
...
Der Begriff Functor ist Dir wohl fremd?...
Wieder mal so ein "Dramaqueensatz" - verkneif Dir die doch einfach mal.
Ganz allgemein gilt: Dass es noch andere Techniken gibt, ist in keinster Weise als "Gegenbeweis".
Meine Aussage ("das geht ohne Codeveränderung => mein Ansatz ist generischer") gilt natürlich ebenso für Funktoren - dass Du Deinen Code ändern kannst, um denselben Effekt zu erzielen, hattest Du schon mit dem "Suche&Ersetzen"-Ansatz belegt (und von mir unbestritten).Da ich das Gefühl habe, dass Du meinen Satz die letzten 3 mal nicht gelesen hast (die Hoffnung stirbt zuletzt): Verwendung von "this->/std::" definieren stärker und schränken deswegen die Flexibilität ein - das hast Du bislang in keinsterweise widerlegt, sondern lediglich dargelegt, warum Du persönlich diese Flexibilität nicht möchtest.
Gruß,
Simon2.