Skepsis am neuen Standard
-
Nexus schrieb:
Da hast du Recht. Wie angetönt kann ich gut nachvollziehen, dass
decltype
undauto
manchmal sehr praktisch sein sollen. Nur befürchte ich, dass man sehr schnell zur Übertreibung tendiert. Klar, keinauto
undtypedef
wäre auch nicht besser. Aber es birgt eben schon Gefahren.Es gibt ganze Sprachen die streng typisiert sind und man nie einen typen angeben muss. absolut top. der typ interessiert nämlich sowieso nie.
-
knivil schrieb:
Halbwahrheiten und sonstiges kommt ja hier zum Vorschein ... Rtti laesst sich deaktivieren, nur darf man dann kein dynamic_cast oder exceptions benutzen.
RTTI läßt sich nicht deaktivieren. Man kann höchstens darauf hoffen, daß der Linker in der Lage ist, sie wegzulassen (und bei polymorphen Klassen ist er das nicht). Halbwissen, anyone?
knivil schrieb:
Exceptions lassen sich deaktivieren.
Nicht ohne ein speziell angepaßtes Build der RTL. Du kannst zwar auf ihre Verwendung verzichten, aber das ändert nichts daran, daß der Startup-Code und terminate() einen try/finally-Block enthalten, was impliziert, daß der ganze Exception-Handling-Mechanismus dazugelinkt werden muß.
knivil schrieb:
Besseres Rtti gibt es ueber Bibliotheken fuer C++.
Es gibt fast für alles eine Bibliothek für C++. Doch ist es ein verbreiteter Irrglaube, Bibliotheken könnten oder sollten alle Sprachfeatures ersetzen. Ansonsten zeige mir bitte, wie du mit so einer Bibliothek z.B. ein Dispinterface für ein bereits bestehendes Interface generierst.
knivil schrieb:
template bloat etc. sind nur Schlagworte.
Ich konkretisiere das gerne für dich. Boost.Regex beispielsweise ist vollständig in Headerdateien implementiert - primär, damit man einen beliebigen Char-Typen angeben kann. Das führt das bei C++ ohnehin nur schwach ausgeprägte Modulkonzept vollends ad absurdum, von den Übersetzungszeiten ganz zu schweigen.
knivil schrieb:
Und Rtti habe ich noch nie wirklich gebraucht.
Das spricht gegen deinen Horizont.
Addendum: Die in C++ verfügbare RTTI beschränkt sich auf das Identifizieren von Typen und die Ausgabe eines mehr oder weniger lesbaren Typnamens primär für Debuggingzwecke. Das hat praktisch nichts mit dem zu tun, was mit der RTTI in Delphi/C++Builder möglich ist, von .NET/Java ganz zu schweigen.knivil schrieb:
Desweiteren muss man nicht alles mit C++ machen. The right tool for the right problem. Dann nimmt man halt nicht C++ wenn man sowas braucht.
Das sehe und praktiziere ich auch so. Allerdings ist das ein schlechtes Argument, wenn es um die mögliche Verbesserung der Sprache C++ geht.
-
Bei g++ als auch bei Visual C++ gibt es Kompilerswitches, die Exceptions als auch Rtti deaktivieren. Was tatsaechlich generiert wird, habe ich mir noch nicht in der Executable angesehen
Dispinterface für ein bereits bestehendes Interface generierst
Keine Ahnung was das ist, hab 's bestimmt noch nie gebraucht. Genauso kann ich dir bei der Sprache deiner Wahl (Delphi/C++Builder, .NET/Java) auch sofort die Grenzen aufzeigen. In den anderen Sprachen ist das vielleicht ganz nett, aber es kostet auch. Desweiteren gehts ja wohl schwerlich darum Features aus anderen Sprachen zu uebernehmen, damit dann alles irgendwie Einheitsbrei wird.
Boost.Regex beispielsweise ist vollständig ...
Wenn es dich stoert, nutze was anderes (es gibt genug). Aber mit Codebloat hat es wenig zu tun, da du den Code nicht selbst schreibst. Ausserdem soll's ja sowas wie pre compiled templates geben, k.A. was draus wird. Selbst benutze ich Boost aber kaum, da manches mir sowieso suspekt ist oder einfach unnoetig.
-
knivil schrieb:
Bei g++ als auch bei Visual C++ gibt es Kompilerswitches, die Exceptions als auch Rtti deaktivieren.
Womit fast sämtlicher C++-Code unbenutzbar wird.
Interessant ist, ob sich RTTI selektiv aktivieren oder deaktivieren läßt; wenn C++ ausführlichere RTTI einführen würde, wäre es problemlos möglich, das nur bei Bedarf spezifisch für eine Klasse zu aktivieren.knivil schrieb:
Keine Ahnung was das ist
Google hilft.
knivil schrieb:
Desweiteren gehts ja wohl schwerlich darum Features aus anderen Sprachen zu uebernehmen, damit dann alles irgendwie Einheitsbrei wird.
Es geht aber durchaus darum, Features aus anderen Sprachen zu übernehmen, weil sie nützlich und sinnvoll sind. Das wird ja auch gemacht (-> Closures).
knivil schrieb:
Wenn es dich stoert, nutze was anderes (es gibt genug). Aber mit Codebloat hat es wenig zu tun, da du den Code nicht selbst schreibst.
?
Natürlich hat das was damit zu tun. Es bläht den Code in den eingebundenen Headerateien, in meinen Übersetzungsmodulen und oft auch in der fertigen Executable auf.
Außerdem geht es ja nicht spezifisch um Boost.Regex (wie "z.B." eigentlich ausdrückt). Es gibt jede Menge Bibliotheken nach diesem Prinzip. C++ und die Standardbibliothek begünstigen solche Bibliotheken nachdrücklich.knivil schrieb:
Ausserdem soll's ja sowas wie pre compiled templates geben, k.A. was draus wird.
Falls du
export template
meinst: vermutlich nichts. Und Precompiled Headers sind lediglich ein Workaround für das konzeptionell defizitäre Modulkonzept von C++; sie machen es erträglicher, sind aber auch nicht ganz unproblematisch. Meine Übersetzungszeiten bei C++-Projekten, die ohne PCHs zu einer Kaffeepause würden, sind auch mit PCHs deutlich höher als die von vergleichbaren Delphi-Projekten. Dabei ist BCC, soweit ich weiß, von den verbreiteten Compilern noch der Schnellste, zudem hat er einen höheren Zeilendurchsatz als der Delphi-Compiler.knivil schrieb:
Selbst benutze ich Boost aber kaum, da manches mir sowieso suspekt ist oder einfach unnoetig.
Vieles aus Boost ist aber auf dem besten Wege, in der nächsten Revision zum Teil des C++-Standards zu werden. Es ist also keineswegs getan mit "nimm doch etwas anderes, wenns dir nicht paßt". std::string paßt mir auch nicht, aber ich muß ihn trotzdem immer mal wieder verwenden, weil anderer Code das auch tut.
-
Shade Of Mine schrieb:
Es gibt ganze Sprachen die streng typisiert sind und man nie einen typen angeben muss. absolut top. der typ interessiert nämlich sowieso nie.
Das sagst du jetzt so. Ich bin aber der Meinung, als Programmierer identifiziert man wichtige Informationen mit dem Typen. Ich kann mir unter
std::vector<T, std::allocator<T> >
einigermassen etwas vorstellen, und zwar mehr als nur ein Container von T. Klar ist es okay, bis zu einem gewissen Grad zu abstrahieren, das hat man ja jetzt bereits mittypedef
.Aber es gibt auch eine gewisse Sicherheit, den Typen zu kennen - denn die Funktionalität unterscheidet sich meistens deutlich, auch wenn die Schnittstelle mehr oder weniger die gleiche ist. Ich habe vor, im neuen Standard soweit wie möglich auf
auto
unddecltype
verzichten, sofern die Übersicht nicht stark darunter leidet.audacia schrieb:
Boost.Regex beispielsweise ist vollständig in Headerdateien implementiert
Nein, Boost.Regex führt Bibliotheken mit.
audacia schrieb:
Natürlich hat das was damit zu tun. Es bläht den Code in den eingebundenen Headerateien, in meinen Übersetzungsmodulen und oft auch in der fertigen Executable auf.
Außerdem geht es ja nicht spezifisch um Boost.Regex (wie "z.B." eigentlich ausdrückt). Es gibt jede Menge Bibliotheken nach diesem Prinzip. C++ und die Standardbibliothek begünstigen solche Bibliotheken nachdrücklich.Templates haben eben auch ihren Preis, das hat man dafür in anderen Sprachen nicht. Man muss sie ja nicht exzessiv anwenden, aber sie verleihen einem enorme Möglichkeiten. Dafür bin ich gerne bereit, Kompromisse beim Kompilieren einzugehen. Und wie
export
gezeigt hat, scheint die Problematik nicht allzu trivial zu sein - was sollte also deiner Meinung nach geändert werden?
-
Nexus schrieb:
audacia schrieb:
Boost.Regex beispielsweise ist vollständig in Headerdateien implementiert
Nein, Boost.Regex führt Bibliotheken mit.
Ah, tatsächlich. Dann muß ich meine Äußerung natürlich korrigieren: 80% von Boost.Regex befinden sich in Headerdateien.
Nexus schrieb:
Templates haben eben auch ihren Preis, das hat man dafür in anderen Sprachen nicht. Man muss sie ja nicht exzessiv anwenden
Gleiches Argument, gleicher Widerspruch: doch, man muß, weil andere das auch tun, und in der Praxis hast du gewöhnlich nicht den Luxus, nur mit selbstgeschriebenem Code arbeiten zu müssen.
Nexus schrieb:
was sollte also deiner Meinung nach geändert werden?
Templates sind sehr nützlich und haben ihre Berechtigung. Die meisten Anwendungsfälle für Templates hätten sich allerdings mit gut spezifizierten Generics genauso lösen lassen. Und sobald man Generics verwendet, läßt sich
export
wunderbar implementieren. Man hätte der Sprache eine Menge erspart, wenn man zusätzlich zu Templates so etwas wie Restricted Templates oder eben Generics eingeführt hätte.
-
audacia schrieb:
Gleiches Argument, gleicher Widerspruch: doch, man muß, weil andere das auch tun, und in der Praxis hast du gewöhnlich nicht den Luxus, nur mit selbstgeschriebenem Code arbeiten zu müssen.
Das kann gut sein, dazu kenne ich mich ehrlich gesagt zu wenig im professionellen Bereich aus. Aber stellen Templates wirklich ein solches Problem dar? Man kann Instanziierungen in andere Module auslagern und auch vorkompilierte Header helfen enorm bei der Kompilierzeit-Verkürzung. Oder ist die grössere Binary das Hauptproblem? Oder alles zusammen?
Nexus schrieb:
Man hätte der Sprache eine Menge erspart, wenn man zusätzlich zu Templates so etwas wie Restricted Templates oder eben Generics eingeführt hätte.
Aber so was kann man sich ja eigentlich selber basteln, zum Beispiel über
void*
. Klar ist das nicht der schönste Weg, aber wenigstens etwas in die Richtung. Ich verstehe aber, dass das aufgrund der existierenden Templates, die auch meistens angewandt werden, nicht wirklich eine Alternative darstellt.
-
Nexus schrieb:
Ich bin aber der Meinung, als Programmierer identifiziert man wichtige Informationen mit dem Typen. Ich kann mir unter
std::vector<T, std::allocator<T> >
einigermassen etwas vorstellen, und zwar mehr als nur ein Container von T. Klar ist es okay, bis zu einem gewissen Grad zu abstrahieren, das hat man ja jetzt bereits mittypedef
.Warum ist es wichtig ob es ein vector<int, std::allocator> oder ein vector<int, my_alloc> oder ein my_vec<int> ist?
Aber es gibt auch eine gewisse Sicherheit, den Typen zu kennen - denn die Funktionalität unterscheidet sich meistens deutlich, auch wenn die Schnittstelle mehr oder weniger die gleiche ist. Ich habe vor, im neuen Standard soweit wie möglich auf
auto
unddecltype
verzichten, sofern die Übersicht nicht stark darunter leidet.Es ist stark typisiert. du kannst also nicht ein vec.run_forrest_run() machen.
auto iter = v.begin();
ist zB super praktisch. wozu muss ich hier extra den typen angeben. mich interessieren die allocatoren doch garnicht, ich will nen iterator haben.
und das ist fast überall so. typen händisch angeben wenn es eh keine wahl gibt, ist sinnloser mehraufwand. es ist ja nicht so als ob es andere typen wären - auto reduziert den wartungsaufwand enorm. da du plötzlich nicht mehr dauernd typedef verwenden musst - sondern einfach auto nimmst.
wenn du mal länger mit type inference gearbeitet hast willst du es nicht mehr missen.
-
Templates sind Generics. Und den rigerosen Templateeinsatz bei Boost finde ich auch nicht toll. Desweiteren habe ich google benutzt, wurde daraus aber nicht recht schlau.Und zum Thema Closures: das "Feature" hat schon C (und wahrscheinlich jede andere Programmiersprache), aber du erkennst sie vielleicht nicht als Closure.
-
Nexus schrieb:
Ich verstehe aber, dass das aufgrund der existierenden Templates, die auch meistens angewandt werden, nicht wirklich eine Alternative darstellt.
Das ist der Punkt.
-
knivil schrieb:
Templates sind Generics.
Nein.
knivil schrieb:
Und zum Thema Closures: das "Feature" hat schon C
Nein.
Wie kommst du dazu, anderen das Verbreiten von Halbwahrheiten anzulasten?
-
Fuer dich Wikipedia: http://de.wikipedia.org/wiki/Generischer_Typ und http://de.wikipedia.org/wiki/Closure . Objekte koennen Closures sein, Closures koennen Objekte sein.
Wie kommst du dazu, anderen das Verbreiten von Halbwahrheiten anzulasten?
Weil sie anscheinend dahinterstehende Konzepte nicht verstanden haben. Klar ist das Generics aus C# nicht vergleichbar mit denen aus C++, aber es sind doch beides Elemente der generischen Programmierung, Generics.
-
Hi audacia,
ich will Dir gar nicht widersprechen, aber ich habe den Eindruck, dass hier einfach 2 Paradigmen aufeinanderstoßen: Compilezeit vs. Laufzeit.
Da schlägt sich C++ halt sehr eindeutig auf die Seite der Compilezeit (außer z.B. bei exceptione specifications, wo es mal wirklich sinnvoll gewesen wäre ). Je mehr man das Ziel verfolgt, möglichst alle Fehlerquellen bereits zur Compilezeit auszumerzen und das Ganze noch mit generischer Programmierung würzt, desto schwerer wird es einfach, dem Compiler den kompletten Quellcode vorzuenthalten .... mit allen Nachteilen wie: Zerbröselnde Linkzeit-Modularisierung, unzureichende Typinformation zur Laufzeit (wobei man die als "Gimmick" wohl trotzdem implementieren dürfte, es aber wohl eher nicht so wichtig ansieht), ...
Vielleicht haben sich die C++-Kommittee-ler auch einfach gedacht: "Wer das möchte, ist mit Java prima bedient."Ich persönlich vermisse die "Compilerunabhängigkeit" (und sei es nur auf einer Plattform) am meisten; für jedes Produkt NxM-Matrizen an plattform- UND compiler(versions)abhängigen Libs gegeneinander abgleichen zu müssen, wird zur Sysiphusarbeit und oftmals absoluten Innovationsbremse...
Gruß,
Simon2.
-
Shade Of Mine schrieb:
Warum ist es wichtig ob es ein vector<int, std::allocator> oder ein vector<int, my_alloc> oder ein my_vec<int> ist?
Ich habe jetzt eher im Vergleich zu
std::list
oder anderen Containern gemeint. Das Wissen über den Allokator kann zwar auch nie schaden, aber das ist leicht bei der Deklaration (oder beim Rückgabetypen einer Funktion) nachlesbar.Shade Of Mine schrieb:
auto iter = v.begin();
ist zB super praktisch. wozu muss ich hier extra den typen angeben. mich interessieren die allocatoren doch garnicht, ich will nen iterator haben.
und das ist fast überall so. typen händisch angeben wenn es eh keine wahl gibt, ist sinnloser mehraufwand. es ist ja nicht so als ob es andere typen wären - auto reduziert den wartungsaufwand enorm. da du plötzlich nicht mehr dauernd typedef verwenden musst - sondern einfach auto nimmst.
Da hast du Recht, mit Iteratoren oder längeren Typen wie solchen aus Boost kann automatische Typerkennung wirklich sehr praktisch sein (hatte ich zwar früher bereits geschrieben, aber im letzten Post irgendwie verdrängt).
Aber schon beim
begin()
kann es zu Problemen führen, da man je nachdem einenconst_iterator
will... Oder?Und eben befürchte ich, dass man schnell zur Übertreibung neigt, denn
auto
ist fast überall anwendbar, wo eine Initialisierung mit einem Ausdruck stattfindet.auto x = 3; auto pos = Object.GetPosition(); // Was ist jetzt pos? Vector<3, float> oder Vector<2, int>? auto size = Blabla.GetSize(); // wie gross ist size? short? int? long? size_t?
Die Beispiele sind vielleicht etwas überspitzt, aber ich selber würde wahrscheinlich relativ schnell die Übersicht verlieren. Es fängt ja schon mit Dingen wie IntelliSense an, wo man sich nicht mehr viel Bezeichner merken muss. Mit
auto
bekommt man auch die Typen geschenkt. An manchen Orten ist die Abstraktion hilfreich, an anderen weniger...knivil schrieb:
Fuer dich Wikipedia: http://de.wikipedia.org/wiki/Generischer_Typ
Hast du auch den Satz "Ein anderer Weg, den u.a. C++ geht, ist die Anwendung von Templates." gelesen?
-
Hast du auch den Satz "Ein anderer Weg, den u.a. C++ geht, ist die Anwendung von Templates." gelesen?
Soll ich dir auch den Artikel vorlesen: "Bei Programmiersprachen gibt es prinzipiell zwei Ansätze, generische Typen zu unterstützen ...". Und mit "ein anderer Weg" stellt einfach nur einen Gegensatz zur ersten Moeglichkeit dar. Ja und genau deswegen Halbwissen, weil aus nicht richtig Lesen und noch weniger Verstehen irgendwie 'ne Meinung entsteht, die einfach nur zum Himmel schreien ist.
-
knivil schrieb:
Fuer dich Wikipedia
Wikipedia-Links sind nicht gut geeignet, um zu kaschieren, daß du dich mit der Differentation von Templates und Generics noch nicht beschäftigt hast.
knivil schrieb:
Jedes Objekt kann man als Closure abstrahieren oder aber auch andersherum.
Der Unterschied zwischen der grundsätzlichen Möglichkeit und einer Sprachunterstützung ist dir bekannt?
Simon2 schrieb:
Vielleicht haben sich die C++-Kommittee-ler auch einfach gedacht: "Wer das möchte, ist mit Java prima bedient."
Den Eindruck habe ich auch
Simon2 schrieb:
Je mehr man das Ziel verfolgt, möglichst alle Fehlerquellen bereits zur Compilezeit auszumerzen und das Ganze noch mit generischer Programmierung würzt, desto schwerer wird es einfach, dem Compiler den kompletten Quellcode vorzuenthalten ....
Das stimmt schon, aber z.B. Generics sind ebenso typsicher wie Templates, können aber anders als diese in untypisiertem Zustand geparst werden. Dadurch ist dann auch ein
export
-Mechanismus gut machbar. (Praktischer Beweis: Delphi 2009. Das unterstützt Generics, die zur Übersetzungszeit instantiiert werden - sie sind demnach ebenso effizient wie Templates -, doch werden sie dennoch wie gewöhnliche Klassen geparst - was das Problem der nutzlosen Fehlermeldungen, das man in C++ durch Concepts angehen will, vermeidet.)Simon2 schrieb:
Ich persönlich vermisse die "Compilerunabhängigkeit" (und sei es nur auf einer Plattform) am meisten; für jedes Produkt NxM-Matrizen an plattform- UND compiler(versions)abhängigen Libs gegeneinander abgleichen zu müssen, wird zur Sysiphusarbeit und oftmals absoluten Innovationsbremse...
So wünschenswert das wäre: auch hierfür ist es viel zu spät. An so etwas hätte man zu Anfang der Entwicklung denken müssen.
-
Gut, auf Wikipedia werden Generics mit generischen Typen gleichgesetzt. Im Sprachgebrauch meint man mit Generics aber eher die Typen, wie sie z.B. in Java verwendet werden. Im englischen Wikipedia-Artikel werden die Begriffe zum Beispiel auch weniger verwaschen.
Ich hatte deinen Post zuerst auch so verstanden, als wolltest du Templates und Generics als identisch bezeichnen.
-
Nexus schrieb:
Gut, auf Wikipedia werden Generics mit generischen Typen gleichgesetzt. Im Sprachgebrauch meint man mit Generics aber eher die Typen, wie sie z.B. in Java verwendet werden. Im englischen Wikipedia-Artikel werden die Begriffe zum Beispiel auch weniger verwaschen.
Ich habe den englischen auch gelesen. Dort heisst es im Eingangsbeispiel: commonly called generics.
-
knivil schrieb:
Ich habe den englischen auch gelesen. Dort heisst es im Eingangsbeispiel: commonly called generics.
Stimmt, hab ich übersehen. Wie dem auch sei, Wikipedia ist nicht der Weisheit letzter Schluss. Ich habe jedenfalls noch nie jemanden die C++-Templates Generics nennen hören, allzu verbreitet scheint der Begriff also nicht zu sein. Aber wenden wir uns lieber wieder dem Thema zu...
audacia schrieb:
Das stimmt schon, aber z.B. Generics sind ebenso typsicher wie Templates, können aber anders als diese in untypisiertem Zustand geparst werden. Dadurch ist dann auch ein
export
-Mechanismus gut machbar. (Praktischer Beweis: Delphi 2009. Das unterstützt Generics, die zur Übersetzungszeit instantiiert werden - sie sind demnach ebenso effizient wie Templates -, doch werden sie dennoch wie gewöhnliche Klassen geparst - was das Problem der nutzlosen Fehlermeldungen, das man in C++ durch Concepts angehen will, vermeidet.)Wie kann die volle Typsicherheit in untypisiertem Zustand bewahrt werden? Das klingt auch so, als hätte sich das C++-Standardkomitee gar nichts überlegt.
-
audacia schrieb:
...
Simon2 schrieb:
Je mehr man das Ziel verfolgt, möglichst alle Fehlerquellen bereits zur Compilezeit auszumerzen und das Ganze noch mit generischer Programmierung würzt, desto schwerer wird es einfach, dem Compiler den kompletten Quellcode vorzuenthalten ....
Das stimmt schon, aber z.B. Generics sind ebenso typsicher wie Templates, ...
Gleich vorweg: Mit Generics habe ich mich noch nicht beschäftigt und auch mit Delphi nicht.
Allerdings (oder vielleicht deswegen) fällt es mir schwer, mir vorzustellen, wie man das (vom Templateparameter abhängige) Verhalten eines Templates typsicher gestalten will, wenn man es nicht (noch) einmal mit diesem zusammen compiliert.Wie gesagt: Kann an meiner Unwissenheit oder mangelnden Phantasie liegen, ist aber so.
Gruß,
Simon2.