Hallo,
funktioniert sowas unter C? (unter C++ scheint das OK zu sein)
1
if(inta=1)
2
printf("%d \n",a);
Mein Compiler will das nicht haben (nicht dass ich es bräuchte, wollte
nur mal ausprobieren). Und falls es so nicht geht, dann warum.
Die Fehlermeldung lautet "error: expected expression before ‘int’". Ist
eine Variablendefinition keine Anweisung?
Also mal ehrlich, als Compiler würde ich mich da auch weigern.
Egal ob valide oder nicht, guter Stil geht anders.
Davon abgesehen, wo ist der Sinn darin, einen Konstanten Wert in eine
Variable zu packen, und drumherum eine Abfrage auf den Wert ebendieser
Variable zu machen? Ein
Wo genau ist Dein Problem? So wie der Code da oben steht, versucht er,
eine Variable innerhalb der Bedingung mit dem Wert 1 zu initialisieren.
Das Ergebnis dieser Zuweisung ist 1 - also ist die Bedingung wahr. Warum
braucht man dann überhaupt noch ein if, wenn die Bedingung konstant true
ergibt? Naaaa?
Nachdenklicher schrieb:> Wo genau ist Dein Problem? So wie der Code da oben steht, versucht> er,> eine Variable innerhalb der Bedingung mit dem Wert 1 zu initialisieren.> Das Ergebnis dieser Zuweisung ist 1 - also ist die Bedingung wahr. Warum> braucht man dann überhaupt noch ein if, wenn die Bedingung konstant true> ergibt? Naaaa?
Mit etwas Spurenintelligenz lässt sich erkennen, dass dies ein stark
vereinfachtes Beispiel ist, wo dieses Feature genutzt wird. Solche
Beispiele haben üblicherweise die Eigenschaft, nichts Nützliches zu
erreichen.
zitter_ned_aso schrieb:> Hallo,>> funktioniert sowas unter C? (unter C++ scheint das OK zu sein)>
1
if(inta=1)
2
>printf("%d \n",a);
>> Mein Compiler will das nicht haben (nicht dass ich es bräuchte, wollte> nur mal ausprobieren). Und falls es so nicht geht, dann warum.>> Die Fehlermeldung lautet "error: expected expression before ‘int’". Ist> eine Variablendefinition keine Anweisung?
Was die Kollegen hier sagen wollen:
1
if(inta==1)
2
printf("%d \n",a);
int=1 setzt Du a gleich 1 und somit wahr. Der Kompiler merkt das und
wird wahrscheinlich eine Fehlermeldung ausspucken... Beim nächsten mal
die Fehlermeldung des Kompilers mit hier angeben bzw. darauf achten.
Nachdenklicher schrieb:> printf("1\n");hätte den (gewünschten) Effekt ebenso.
ja, aber ich könnte dieser Variable auch was anderes zuweisen.
Oder z.B. das hier:
1
while(intch=getchar()){
2
if(ch=='e'){
3
puts("end");
4
break;
5
}
6
putchar(ch);
7
}
eine lokale Variable ch (wie bei einer for-Schleife). Läuft wieder mit
dem C++-Compiler.
Abstraktes Denken ist nicht so deine Stärke?
Genau so gut könnte natürlich dastehen
1
if(inta=foo())
2
printf("%d \n",a);
3
}
zitter_ned_aso schrieb:> Mein Compiler will das nicht haben (nicht dass ich es bräuchte, wollte> nur mal ausprobieren). Und falls es so nicht geht, dann warum.>> Die Fehlermeldung lautet "error: expected expression before ‘int’". Ist> eine Variablendefinition keine Anweisung?
In C99 ist nur folgendes legal:
1
#include<stdio.h>
2
#include<stdlib.h>
3
4
intmain(void)
5
{
6
inta;
7
if(a=rand()){
8
printf("%d",a);
9
}
10
}
Warum? Weils so im Standard steht, Variablendeklation in einer
Expression ist nicht zulässig.
SchlechterIng schrieb:> int=1 setzt Du a gleich 1 und somit wahr. Der Kompiler merkt das und> wird wahrscheinlich eine Fehlermeldung ausspucken...
ach so! bei werden werden Warnungen als Errors behandelt - vielleicht
liegt es daran. Danke für diesen Hinweis. Ich habe es ganz vergessen.
In C++ mit GCC scheint das zu gehen (ich sehe allerdings keine sinnvolle
Anwendung dafür):
1
if (int i = 42)
2
{
3
printf("true: %d", i);
4
}
5
else
6
{
7
printf("false: %d", i);
8
}
In C99 scheint es hingegen nicht möglich zu sein.
Wenn ich mich recht entsinne, gab es zwischen C99 und C++ ein paar
subtile Unterschiede in dieser Hinsicht bei Schleifen: Bei C99 existiert
eine solche Variable afaik in einem separaten Scope, während sie bei C++
als Bestandteil des gleichen Scopes der for Schleife ist.
In C99 sollte folgendes daher kompilieren, in C++ hingegen nicht:
x^2 schrieb:> (ich sehe allerdings keine sinnvolle> Anwendung dafür):
Die Anwendung dafür ist, dass man den Rückgabewert einer Funktion
überprüfen und gegebenfalls weiterverwenden kann, ohne das man das
außenliegende Scope vollmüllen muss (und wohlmöglich ungültige Daten
weitergenutzt werden) oder lästig noch mehr Klammern setzen muss.
Die Frage war halt ob die Variablendefinition eine Anweisung ist, die
einen Rückgabewert zurückgibt (den man dann z.B. mit "if" auswerten
kann).
Und wenn C++ sowas wie
x^2 schrieb:> Langsam verlieren sich diese C++ Leute auch im klein-klein und syntactic> sugar.
Mitnichten: es geht hier um die Begrenzung des Scope. Und das ist sehr
wichtig und nützlich.
zitter_ned_aso schrieb:> Und wenn C++ sowas wieif( int i=get_value() )> akzeptiert, warum wird dann beicout<< int x=42 <<endl;> gemeckert?
Weil das eine nichts mit dem anderen zu tun hat?
zitter_ned_aso schrieb:> Die Frage war halt ob die Variablendefinition eine Anweisung ist, die> einen Rückgabewert zurückgibt (den man dann z.B. mit "if" auswerten> kann).>>> Und wenn C++ sowas wie>
1
>if(inti=get_value())
2
>
> akzeptiert, warum wird dann bei>
1
>cout<<intx=42<<endl;
2
>
> gemeckert?
Schon mal was von Syntax gehört?
Das eine ist eine an der Stelle expl. zugelassene Definition, das andere
muss eine Ausdruck sein.
Wilhelm M. schrieb:> x^2 schrieb:>> Langsam verlieren sich diese C++ Leute auch im klein-klein und syntactic>> sugar.>> Mitnichten: es geht hier um die Begrenzung des Scope. Und das ist sehr> wichtig und nützlich.
Ich mag nicht streiten, aber das geht doch bereits mit einem klassischem
Scopeblock:
1
{
2
auto x = f();
3
if (x == 42) { ... }
4
}
In meinen Augen ist das deshalb nur syntactic sugar. Man müßte ja drei
Zeichen mehr tippen und spart sich die Einrückung (Oh nein, der Herr
behüte!).
Pattern durch Scopeblöcke sind ja durchaus üblich a la:
1
{
2
Mutex lock(x);
3
// do things in critical section here, may throw exceptions
4
}
5
// auto release mutex here
Zumal dieses neue Feature ja nur mit einer Variable geht. Folgendes geht
ja aus gutem Grund nicht, da gar nicht klar wäre, welche Variable danach
überhaupt existiert:
1
if (auto a = f1() || auto b = f2() || auto c = f3())
Wilhelm M. schrieb:> Schon mal was von Syntax gehört?> Das eine ist eine an der Stelle expl. zugelassene Definition, das andere> muss eine Ausdruck sein.
Ich finde es schon bemerkenswert. Eigentlich hat "int i = get_value()"
keinen Wert, da es kein Ausdruck ist. Dennoch kann man im if den Wert
offenbar abfragen. Es scheint sich also um eine kontextabhängige
Erweiterung der Syntax zu handeln, die man im Sprachdesign normalerweise
zu vermeiden versucht.
Rolf M. schrieb:> Es scheint sich also um eine kontextabhängige Erweiterung der Syntax zu> handeln, die man im Sprachdesign normalerweise zu vermeiden versucht.
Der Zug ist bei C und damit C++ schon lange abgefahren ;-)
x^2 schrieb:> Ich mag nicht streiten, aber das geht doch bereits mit einem klassischem> Scopeblock:> {> auto x = f();> if (x == 42) { ... }> }
Du musst es ja nicht nutzen.
Trotzdem halte ich
1
if(constautox=f();isBla(x)){
2
// ...
3
}
für sinnvoll, weil es einfach Fehler vermeiden hilft.
Rolf M. schrieb:> Es scheint sich also um eine kontextabhängige Erweiterung der Syntax zu> handeln, die man im Sprachdesign normalerweise zu vermeiden versucht.
Naja, so wie bei "for" auch, wo es C99 ja übernommen hat (wenngleich,
wie etwas weiter oben gezeigt, leider mit geringfügig anderen
Randbedingungen bzgl. des Scopes).
Ja, ist manchmal praktisch, als Kurzform dafür, einen komplett neuen
Klammer-Block anlegen zu müssen. Hätte man wohl für "if" auch übernehmen
können, andererseits, wie ebenfalls genannt worden ist, mehr als eine
Variable lässt sich damit eben nicht definieren – weder bei "for" noch
bei "if" weder in C noch in C++. Da hat die Bequemlichkeit dann ihre
Grenzen.
Wilhelm M. schrieb:> Bequemlichkeit ist ja auch nicht das Ziel.
Doch. Es wurde doch schon gezeigt, dass ein neuer Klammerblock eine
vergleichbare Begrenzung des Scopes produzieren würde. Letztlich genau
das, was man tun muss, um es für mehr als eine Variable haben zu können.
Jörg W. schrieb:> Doch.
Nein.
>Es wurde doch schon gezeigt, dass ein neuer Klammerblock eine> vergleichbare Begrenzung des Scopes produzieren würde.
Die Aussage des Codes ist eine andere, und die Fehlermöglichkeiten auch.
Jörg W. schrieb:> Rolf M. schrieb:>> Es scheint sich also um eine kontextabhängige Erweiterung der Syntax zu>> handeln, die man im Sprachdesign normalerweise zu vermeiden versucht.>> Naja, so wie bei "for" auch, wo es C99 ja übernommen hat (wenngleich,> wie etwas weiter oben gezeigt, leider mit geringfügig anderen> Randbedingungen bzgl. des Scopes).
diese Variante ist analog zur for-Schleife:
Wilhelm M. schrieb:> if (const auto x = f(); isBla(x)) {
Da wurden die Definition der Variablen und die Abfrage der Bedingung
sauber getrennt. Hier aber nicht:
zitter_ned_aso schrieb:> if( int i=get_value() )
Jörg W. schrieb:> Ja, ist manchmal praktisch, als Kurzform dafür, einen komplett neuen> Klammer-Block anlegen zu müssen. Hätte man wohl für "if" auch übernehmen> können, andererseits, wie ebenfalls genannt worden ist, mehr als eine> Variable lässt sich damit eben nicht definieren – weder bei "for" noch> bei "if" weder in C noch in C++. Da hat die Bequemlichkeit dann ihre> Grenzen.
Es lassen sich schon mehrere Variablen anlegen:
1
std::set<double>m;
2
if(auto[it,flag]=m.insert(6.6);flag){
3
foo(*it);
4
}
Ok es lässt sich nicht direkt das Beispiel von x^2 umsetzen, aber das
scheint eh eine schlechte Idee zu sein. Wenn die Funktionen echte Namen
haben und länger als 2 Zeichen sind wird das sehr schnell sehr
unübersichtlich.
GEKU schrieb:> Variablen in Bedingungsanweisungen zu definieren ist in C nicht> vorgesehen und funktioniert erst in C++.>> Also cpp anstelle von gcc verwndet.
Du meinst wohl g++.
Ja, ich weiß, warum die zweite if-Anweisung so nicht möglich ist, aber
auf den ersten Blick sieht das Beispiel doch etwas paradox aus.
Ich empfinde ja viele der neu hinzugekommenen Sprachfeatures seit C++11
durchaus als sinnvoll und nützlich. Wenn aber für irgendwelche relativ
unwichtigen Dinge (bspw.um zwei Zeichen einzusparen) die Sprachsyntax
geändert wird, keimt in mir der leise Verdacht auf, dass es dem
Normungsgremium nicht immer nur um die Verbesserung der Sprache geht,
sondern manchmal auch um den Ausschluss jener Programmierer aus der
C++Community, die nicht die Möglichkeit haben, ihr C++-Wissen alle drei
Jahre auf den neuesten Stand zu bringen ;-)
Yalu X. schrieb:> Ich empfinde ja viele der neu hinzugekommenen Sprachfeatures seit C++11> durchaus als sinnvoll und nützlich. Wenn aber für irgendwelche relativ> unwichtigen Dinge (bspw.um zwei Zeichen einzusparen)
Wie schon gesagt: darum geht es nicht.
> die Sprachsyntax> geändert wird, keimt in mir der leise Verdacht auf, dass es dem> Normungsgremium nicht immer nur um die Verbesserung der Sprache geht,> sondern manchmal auch um den Ausschluss jener Programmierer aus der> C++Community, die nicht die Möglichkeit haben, ihr C++-Wissen alle drei> Jahre auf den neuesten Stand zu bringen ;-)
Blödsinn.
Hier haben wir die seit langem auf dem Plan stehende Vereinfachung, weil
for/if/switch nun gleich behandelt werden. Das macht die Sprache
einfacher.
Und beim for-statement würdest Du es je wohl auch nicht gegenüber der
c89-Version als Verschlechterung empfinden.
Das ist dieselbe Qualität wie uniform-initialization-Syntax (wichtig für
generische Programierung).
mh schrieb:> Es lassen sich schon mehrere Variablen anlegen:std::set<double> m;> if(auto [it, flag] = m.insert(6.6); flag) {> foo(*it);> }> Ok es lässt sich nicht direkt das Beispiel von x^2 umsetzen, aber das> scheint eh eine schlechte Idee zu sein.
Nein, eigentlich hast Du das Schulbeispiel benannt.
Wobei es streng genommen nicht zwei Variablen sind, sondern nur eine
(die einen unbekannten, eindeutigen Namen hat) als Aggregat, mit neuen
Namen für die Elemente des Aggregats.
Wilhelm M. schrieb:> Yalu X. schrieb:>> Ich empfinde ja viele der neu hinzugekommenen Sprachfeatures seit C++11>> durchaus als sinnvoll und nützlich. Wenn aber für irgendwelche relativ>> unwichtigen Dinge (bspw.um zwei Zeichen einzusparen)>> Wie schon gesagt: darum geht es nicht.
Dann erklär doch mal einem nicht so Fortgeschrittenen, warum
1
if(init-statementcondition)statement
so viel besser sein soll als
1
{
2
init-statement
3
if(condition)statement
4
}
dass man dafür extra die (ohnehin schon recht komplizierte) Syntax
erweitern muss.
Wilhelm M. schrieb:> Hier haben wir die seit langem auf dem Plan stehende Vereinfachung, weil> for/if/switch nun gleich behandelt werden. Das macht die Sprache> einfacher.
Das Argument würde ich ja sofort gelten lassen, wenn dabei
konsequenterweise auch while berücksichtigt worden wäre, also:
Yalu X. schrieb:> Ja, ich weiß, warum die zweite if-Anweisung so nicht möglich ist, aber> auf den ersten Blick sieht das Beispiel doch etwas paradox aus.
paradox++
:-)
Markiert man den parametrierten Konstruktor oder den Konversionsoperator
nach int als explicit, compiliert es nicht mehr - soweit so klar. Jetzt
aber folgende Änderung:
1
if (Test x(1); Test y(2))
2
{
3
printf("x=%d, y=%d\n", (int)x, (int)y);
4
}
DAS kompiliert NICHT mehr!
1
main.cpp: In function ‘int main()’:
2
main.cpp:24:25: error: expected primary-expression before ‘y’
Vincent H. schrieb:> Clang hat hier eine wesentlich bessere Fehlermeldung:> <source>:15:23: error: variable declaration in condition cannot have a> parenthesized initializer>> if (Test x(1); Test y(2)) {
Okay, aber warum geht das:
Yalu X. schrieb:> Wilhelm M. schrieb:>> Yalu X. schrieb:>>> Ich empfinde ja viele der neu hinzugekommenen Sprachfeatures seit C++11>>> durchaus als sinnvoll und nützlich. Wenn aber für irgendwelche relativ>>> unwichtigen Dinge (bspw.um zwei Zeichen einzusparen)>>>> Wie schon gesagt: darum geht es nicht.>> Dann erklär doch mal einem nicht so Fortgeschrittenen, warum>> if ( init-statement condition ) statement>> so viel besser sein soll als>> {> init-statement> if ( condition ) statement> }>> dass man dafür extra die (ohnehin schon recht komplizierte) Syntax> erweitern muss.
Also ich finde
1
if(init-statement1condition1){
2
if(init-statement3condition2){
3
if(init-statement3condition3){
4
foo();
5
}
6
}
7
}
deutlich besser als
1
{
2
init-statement1
3
if(condition1){
4
init-statement2
5
if(condition2){
6
init-statement3
7
if(condition3){
8
foo();
9
}
10
}
11
}
12
}
Der Vergleich wird noch vorteilhafter, wenn sowas wie "else" und weitere
Funktionsaufrufe vorkommen.
Yalu X. schrieb:> Wilhelm M. schrieb:>> Hier haben wir die seit langem auf dem Plan stehende Vereinfachung, weil>> for/if/switch nun gleich behandelt werden. Das macht die Sprache>> einfacher.>> Das Argument würde ich ja sofort gelten lassen, wenn dabei> konsequenterweise auch while berücksichtigt worden wäre, also:>> while ( init-statement condition ) statement>> Stattdessen geht nach wie vor nur>> while ( condition ) statement>> Wo bleibt da die Durchgängigkeit?
Das habe ich bis jetzt auch nicht verstanden. Hat das bis jetzt niemand
Vorgeschlagen oder wurde es abgelehnt?
Yalu X. schrieb:> Stattdessen geht nach wie vor nur>> while ( condition ) statement>> Wo bleibt da die Durchgängigkeit?
vielleicht hat man sich ja um folgendes Problem gedrückt:
mh schrieb:> Das habe ich bis jetzt auch nicht verstanden. Hat das bis jetzt niemand> Vorgeschlagen oder wurde es abgelehnt?
Ich schätze, weil es "for" gibt, wenn man eine Schleife mit init haben
will.
x^2 schrieb:> Vincent H. schrieb:>> Clang hat hier eine wesentlich bessere Fehlermeldung:>> <source>:15:23: error: variable declaration in condition cannot have a>> parenthesized initializer>>>> if (Test x(1); Test y(2)) {>> Okay, aber warum geht das:if (Test x{1}; Test y{2})> {> printf("x=%d, y=%d\n", (int)x, (int)y);> }
Weil das kein parenthesized initializer, sondern ein brace-initializer
ist.
mh schrieb:> Der Vergleich wird noch vorteilhafter, wenn sowas wie "else" und weitere> Funktionsaufrufe vorkommen.
Würde ich jetzt nicht bestreiten wollen; aber es bringt die Sprache
nicht weiter und bietet (Hand auf Herz) nur marginalen Mehrwert. Es ist
kein neues fundamentales Konzept, so wie einst Klassen, Namespaces oder
Templates.
Ich neige dazu solchen syntactic sugar etwas kritisch zu sehen: Die
Leute nutzen das dann begeistert und zwingen dadurch jeden der eine
kleine Klasse von ihnen wiederverwenden möchte dazu, erstmal auf die
allerneuste Compiler-Version upzudaten, weil jetzt die if's anders sind.
Für kleine Spielprojekte ist das immer schnell erledigt, aber bei den
großen Projekte in der Industrie, die nicht nur Programmiergold
enthalten ist so ein Compiler-Update durchaus mal kritisch und nicht so
eben mal getan.
Im Fall der while Loop wurde ja oben (m.M. nach absolut berechtigt)
angeführt, dass dieses spezielle Feature die Durchgängigkeit und Logik
kaputt macht. Das hätte man vermeiden können, indem man einfach etwas
länger über solche Dinge nachdenkt und "mental reifen" läßt. Das ist im
Wesentlichen auch meine Kritik an der C++ Weiterentwicklung der letzten
Zeit: Vieles ist zu hastig vorwärtsgetrieben und man läuft schnell
Gefahr mehr kaputt zu machen wie besser.
Rolf M. schrieb:> Weil das kein parenthesized initializer, sondern ein brace-initializer> ist.
Das wäre eine formale Erklärung; Auf logischer Ebene macht es afaik aber
keinen Unterschied: Die Konstruktion der Objekte läuft identisch ab. Es
ist unlogisch warum das eine gehen sollte, das andere aber nicht.
x^2 schrieb:> Das hätte man vermeiden können, indem man einfach etwas> länger über solche Dinge nachdenkt und "mental reifen" läßt.
Weil jede dumme Idee sofort im nächsten Standard landet... Warum gehen
so viele Leute davon aus, dass am Standard nur böswillige und/oder
unfähige Idioten arbeiten?
mh schrieb:> x^2 schrieb:>> Das hätte man vermeiden können, indem man einfach etwas>> länger über solche Dinge nachdenkt und "mental reifen" läßt.>> Weil jede dumme Idee sofort im nächsten Standard landet... Warum gehen> so viele Leute davon aus, dass am Standard nur böswillige und/oder> unfähige Idioten arbeiten?
Weil...
Es es einfch nur peinlich ist, wenn irgendwelche APIs verabschiedet
werden, die dann direkt im nächsten Standard deprecated werden, weil sie
einfach beschi**en war. Mal im ernst, was soll man da denken? Da sitzt
dann das Komitee und erwägt Jahre lang hin und her und dann kommt etwas
raus, was nach dem ersten "Testlauf" (lies: beschlossener
internationaler Standard) sofort auseinander fliegt?
Oder man denke mal an c++11 constexpr. "Exactly one return statement"
WTF!?
Warum??? Das wird so gesetzt, weil... Ja, das muss schon ein toller
Grund gewesen sein, wenn er ein paar Jahre später nicht mehr gilt. Was
hat sich verändert? Wurde bewiesen, dass mit einem erweiterten
Epsilon-Lambda-Kalkül komplexere Ausdrücke doch widerspruchsfrei
möglich sind? Habe ich was verpasst? Ist keiner auf die Idee gekommen,
da mit mehr als einem return arbeiten zu wollen? Oder war das ganze
halbgar, als es verabschiedet wurde und füllt jetzt "nur so" die cppref
(und so manchen Programmierer-Schädel) mit irgendwelchen Bestimmungen
aus grauer Vorzeit, führt zu (hoffentlich) totem Code in so mancher
Compiler-Implementierung, und erinnert, wie als Mahnmal daran, wie
armselig die Dinge früher waren?
Herb Sutter erzählte auch ganz ehrlich auf irgendeiner x-com: "Ja, bei
den braced initialiazers - da dachte ich im nachhinein echt, wir
hätten's so richtig verbockt, wenn man diese Beispiele hier
betrachtet..."
Sollte man das fixen? Könnte man das noch, wenn es einmal verabschiedet
war? So etwas wirkt schon ein wenig diskreditierend - ganz von selbst.
Und mir zumindest scheint das dem Prozess inhärent.
Das Grundprinzip ist scheinbar eben nicht: "Das hat sich bewährt, das
können wir standartisieren."
Heiko L. schrieb:> Oder man denke mal an c++11 constexpr. "Exactly one return statement"> WTF!?> Warum???
Das hatte vermutlich eher praktische Gründe: Wären constexpr-Funktionen
in C++11 gleich so allgemein spezifiziert worden wie in C++14, wären
wohl die Compilerschreiber auf die Barrikaden gegangen, weil sie in
kurzer Zeit einen C++-Interpreter in den C++Compiler hätten integrieren
müssen, was schon ein Bisschen Arbeit bedeutet. Beschränkt man die
Funktion auf ein einzelnes return-Statement, muss statt eines Stücks
allgemeinen Programmcodes (mit Variablen, Zuweisungen, Schleifen usw.)
nur ein Ausdruck ausgewertet werden, wofür die benötigten Mittel in
bestehenden Compilern bereits verfügbar waren.
Das war immerhin schon ein bedeutender Fortschritt gegenüber C++98/03,
wo algorithmische Compilezeitberechnungen nur mit einem gruseligen
Template-Hack möglich waren. Für diejenigen, die ein wenig funktionale
Programmierung konnten, stellte die Einschränkung auf 1 return-Statement
kein Problem dar, da in FP-Sprachen jede Funktion dieser Einschränkung
unterliegt.
Heiko L. schrieb:> mh schrieb:>> x^2 schrieb:>>> Das hätte man vermeiden können, indem man einfach etwas>>> länger über solche Dinge nachdenkt und "mental reifen" läßt.>>>> Weil jede dumme Idee sofort im nächsten Standard landet... Warum gehen>> so viele Leute davon aus, dass am Standard nur böswillige und/oder>> unfähige Idioten arbeiten?>> Weil...> [...]
Oh nein! Sie machen beim Lösen komplexer Probleme Fehler! Es müssen
Idioten am Werk sein! Und böswillig dazu!
Yalu X. schrieb:> Wären constexpr-Funktionen> in C++11 gleich so allgemein spezifiziert worden wie in C++14, wären> wohl die Compilerschreiber auf die Barrikaden gegangen, weil sie in> kurzer Zeit einen C++-Interpreter in den C++Compiler hätten integrieren> müssen, was schon ein Bisschen Arbeit bedeutet.
Ja, das ist es genau, was ich meine. Das sind Erwägungen, die mMn keinen
Ausdruck in so etwas wie einem ISO-Standard finden dürf(t)en.
Wenn es darum geht, eine Sprache sinnvoll zu spezifizieren, was soll
denn das dann für ein Argument sein? Warum sollte jede Implementierung,
die nicht auf Konformität pfeift, "erstmal" so etwas bereit stellen? Und
wie schlimm ist es dagegen de-facto eine Zeit lang (noch) nicht
standardkonform zu sein, wenn dann endlich eine finale (und hoffentlich
ausgereifte) Fasssung verabschiedet wird? Ich finde, der gesetzte
Standard sollte gerade kein Testbett und von Kompromissen an
Compiler-Autoren geprägtes Konstrukt sein, sondern die wohlüberlegte,
sinnvolle, gereifte Einsicht, wie es sein sollte, die als solche ihre
Gültigkeit auch nicht eben einbüßen kann.
mh schrieb:> Heiko L. schrieb:>> mh schrieb:>>> x^2 schrieb:>>>> Das hätte man vermeiden können, indem man einfach etwas>>>> länger über solche Dinge nachdenkt und "mental reifen" läßt.>>>>>> Weil jede dumme Idee sofort im nächsten Standard landet... Warum gehen>>> so viele Leute davon aus, dass am Standard nur böswillige und/oder>>> unfähige Idioten arbeiten?>>>> Weil...>> [...]>> Oh nein! Sie machen beim Lösen komplexer Probleme Fehler! Es müssen> Idioten am Werk sein! Und böswillig dazu!
Wenn das denn so ist, könnte man es schon als Hybris auffassen.
Heiko L. schrieb:> Und> wie schlimm ist es dagegen de-facto eine Zeit lang (noch) nicht> standardkonform zu sein, wenn dann endlich eine finale (und hoffentlich> ausgereifte) Fasssung verabschiedet wird?
Und wo ist denn das Problem den Standard erst etwas strikter zu
definieren und ihn dann aufzuweiten?
Volle Rückwärtskompatibilität ist gegeben.
Es wurde nichts deprecated. Lediglich erweitert.
Hättest du es besser gefunden, wenn man den Standard erst komplex
definiert und dann einen folgenschweren Fehler macht, weil man doch
etwas übersehen hat?
Lieber Schritt für Schritt vorgehen.
Heiko L. schrieb:> Ja, das ist es genau, was ich meine. Das sind Erwägungen, die mMn keinen> Ausdruck in so etwas wie einem ISO-Standard finden dürf(t)en.> Wenn es darum geht, eine Sprache sinnvoll zu spezifizieren, was soll> denn das dann für ein Argument sein? Warum sollte jede Implementierung,> die nicht auf Konformität pfeift, "erstmal" so etwas bereit stellen? Und> wie schlimm ist es dagegen de-facto eine Zeit lang (noch) nicht> standardkonform zu sein, wenn dann endlich eine finale (und hoffentlich> ausgereifte) Fasssung verabschiedet wird? Ich finde, der gesetzte> Standard sollte gerade kein Testbett und von Kompromissen an> Compiler-Autoren geprägtes Konstrukt sein, sondern die wohlüberlegte,> sinnvolle, gereifte Einsicht, wie es sein sollte, die als solche ihre> Gültigkeit auch nicht eben einbüßen kann.
Also einerseits darf der Standard keine kleinen Schritte machen und
andererseits darf der Standard nur ausgereifte Dinge übernehmen. Wie
soll das funktionieren? Soll jeder Compiler und jede
"Standardbibliothek" erstmal drauflos testen?
Dann lenken wir doch mal die Diskussion weg von den Selektionen mit
Initialisieren (if/switch) zu den Iterationen (for/while/do-while), die
in ihrer Mächtigkeit alle äquivalent sind und deshalb mechanisch
ineinander transformiert werden können. Es braucht also nur eine Form:
sagen wird die kopfgesteuerte while-Form.
Die Leute, die hier so gegen die vermeintliche Verkomplizierung der
Sprache (in der Tat ist es eine Vereinfachung) wettern, und schlechtere
Pseudoalternativen vorschlagen (nicht im Sinne von Mächtigkeit, auch
dort kämen wir mit der simplen Form if (<bool>) aus), sollten dann mal
sich fragen, warum gibt es denn auch noch die for- oder do-while-Form.
Wahrscheinlich auch, weil das Standardisierungskomitee von Idioten
durchsetzt ist, die die Sprache C kaputt machen wollen. Jaja, die
Depperten da oben!
Wilhelm M. schrieb:> Dann lenken wir doch mal die Diskussion weg von den Selektionen mit> Initialisieren (if/switch) zu den Iterationen (for/while/do-while), die> in ihrer Mächtigkeit alle äquivalent sind und deshalb mechanisch> ineinander transformiert werden können. Es braucht also nur eine Form:> sagen wird die kopfgesteuerte while-Form.
Dann können wir noch einen Schritt weiter gehen und alle Schleifen
streichen. Wir können einfach if + goto nutzen. Das sollte den Standard
deutlich vereinfachen. Die ganzen Schleifen machen immerhin ganze 3
Seiten aus.
(für alle die es nicht auswendig wissen, das c++17 Draft Dokument hat
1440 Seiten)
Schon komisch, dass mir C++ jüngst durch immer aggressiveres Marketing
auffällt. Hier auch wieder. Ich denke: Wer austeilt ("We stopped
teaching C" *) muss auch einstecken können.
Ein gutes Produkt hat sowas jedenfalls nicht nötig und würde Kritik
ernst nehmen, um so die Sprache zu verbessern.
Den Stohmann, dass im Standardisierungsgremium nur Idioten am Werk sind
könnt ihr gleich wieder einpacken, den hat "hm" hier mal auf der Wiese
aufgestellt um sich jetzt daran abarbeiten zu können.
* https://www.youtube.com/watch?v=YnWhqhNdYyk
x^2 schrieb:> Schon komisch, dass mir C++ jüngst durch immer aggressiveres Marketing> auffällt. Hier auch wieder. Ich denke: Wer austeilt ("We stopped> teaching C" *) muss auch einstecken können.
Ja, das zitiere ich sehr gerne. Und den unten von Dir verlinkten Vortrag
von Kate. Wer aber aufmerksam zuhört, wird feststellen, dass es nicht
darum geht, mit der Sprache C aufzuhören ...
> Ein gutes Produkt hat sowas jedenfalls nicht nötig und würde Kritik> ernst nehmen, um so die Sprache zu verbessern.
Ich bin leider nicht im Gremium: allerdings kann man sich mit
entsprechenden Papern am Prozess beteiligen. Hier sind also die
aufgefordert, die etwas kritisieren (pos/neg) wollen. Und das wird
positiv aufgenommen, sofern man kompetent genug argumentiert. Acho, da
sind ja nur Idioten im Gremium ...
> Den Stohmann, dass im Standardisierungsgremium nur Idioten am Werk sind> könnt ihr gleich wieder einpacken, den hat "hm" hier mal auf der Wiese> aufgestellt um sich jetzt daran abarbeiten zu können.
Ja, das ist m.E ein guter Vortrag:
> * https://www.youtube.com/watch?v=YnWhqhNdYyk
Wilhelm M. schrieb:> Und das wird> positiv aufgenommen, sofern man kompetent genug argumentiert.
Ich hoffe entschieden wird da nach Inhalt und nicht nach Art der
Argumentation. Vielleicht ist das aber auch das Problem, wenn man sich
durch die immer existierende Featuritis der Community treiben läßt. Ich
weiß es nicht.
Jedenfalls, es war ursprünglich mal schön, dass C und C++ eine Familie
war, wobei C im Wesentlichen eine Untermenge von C++ abbildete. Es
ermöglichte Skalierung wobei man bei Projekten unterschiedlicher Größe
und Einsatzbereiche "in der Familie" bleiben konnte und den Code
wiederverwenden konnte.
Die letzten Jahre und die Richtung zeigt aber, z.B. "Deprecating
volatile"
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r3.html
dass das kaputt gemacht wurde und wird. Im Prinzip entsteht eine völlig
neue Sprache und man interessiert sich auch nicht mehr für das
"gestern". Das alte und morsche, es lebe das neue... Schlüsselworte
werden umgenutzt ("auto") oder entfernt ("volatile"), ständig neue
hinzugefügt.
In meinen Augen begründet die Skalierbarkeit aber den großen Erfolg
dieser Sprachfamilie: Eine hochperformante Sprachfamilie, die für
Embedded ebenso taugt wie für Applikationsentwicklung. Wer z.B.
ernsthaft glaubt mit STL, Streams, Exceptions, RTTI und dynamischer
Speicherallokation sind MCUs programmierbar, hat m.M. den Verstand
verloren oder einfach keine Ahnung - schon ein "printf" ist da oft zu
viel. Eine solche hochdynamisch entwickelnde Sprache kann in der
Embedded Welt keiner mehr gebrauchen, wo jahrzehntelange Konstanz und
Kompatibilität wichtig sind. Da geht aktuell in meinen Augen extrem viel
kaputt und ich finde das einfach Schade.
x^2 schrieb:> Wilhelm M. schrieb:>> Und das wird>> positiv aufgenommen, sofern man kompetent genug argumentiert.>> Ich hoffe entschieden wird da nach Inhalt und nicht nach Art der> Argumentation.
Genau so ist es.
> Vielleicht ist das aber auch das Problem, wenn man sich> durch die immer existierende Featuritis der Community treiben läßt.
Die Community sind wir bzw. Du und ich.
> Die letzten Jahre
Allgemeinplatz: was genau meinst Du?
>und die Richtung zeigt aber, z.B. "Deprecating volatile"
Ja, und das war gut so: das ist eines der am wenigsten verstandenen
Schlüsselwörter (gleich nach inline).
> Im Prinzip entsteht eine völlig> neue Sprache und man interessiert sich auch nicht mehr für das> "gestern".
Das stimmt nicht. Der breaking change von auto ging über Jahrzehnte.
Auf der anderen Seite wurde immer die Starrheit der Sprache vorgeworfen
- nun haben wir aufgrund der Community den 3 Jahres Zyklus.
>Das alte und morsche, es lebe das neue... Schlüsselworte> werden umgenutzt ("auto") oder entfernt ("volatile"), ständig neue> hinzugefügt.
s.o., allerdings als non-breaking-change
> In meinen Augen begründet die Skalierbarkeit aber den großen Erfolg> dieser Sprachfamilie: Eine hochperformante Sprachfamilie, die für> Embedded ebenso taugt wie für Applikationsentwicklung. Wer z.B.> ernsthaft glaubt mit STL, Streams, Exceptions, RTTI und dynamischer> Speicherallokation sind MCUs programmierbar, hat m.M. den Verstand> verloren oder einfach keine Ahnung - schon ein "printf" ist da oft zu> viel. Eine solche hochdynamisch entwickelnde Sprache kann in der> Embedded Welt keiner mehr gebrauchen, wo jahrzehntelange Konstanz und> Kompatibilität wichtig sind. Da geht aktuell in meinen Augen extrem viel> kaputt und ich finde das einfach Schade.
Ganz und gar nicht: mit dem großen Augenmerk auf Compilezeit-Computing
haben wir extrem viel dazu gewonnen.
x^2 schrieb:> Wer z.B.> ernsthaft glaubt mit STL, Streams, Exceptions, RTTI und dynamischer> Speicherallokation sind MCUs programmierbar
Gerade die STL algorithms ermöglichen es, des Spagat aus Performant und
leserlich endlich besser hinzukriegen. Generell wird in aktuelleren
Standards der Fokus sehr stark auf zero overhead gelegt.
Keiner zwingt dich, Streams oder dynamischen Speicher zu verwenden,
genauso wenig wie du in C malloc oder printf verwenden musst.
Dein Rant ist schlicht unsinnig. Und ja, es ist gut dass eine neue
Sprache entsteht, und man den Kompatibilitätquatsch nicht mitschleppen
muss. C++ ist nun mal nicht C, enweder ich nehme das eine oder das
andere. Alles andere führt zu Pseudo-C++, das weder Fisch noch Fleisch
ist.
x^2 schrieb:> Die letzten Jahre und die Richtung zeigt aber, z.B. "Deprecating> volatile">> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r3.html
Es handelt sich dabei um einen Vorschlag. Es steht dir völlig frei,
Gegenargumente einzureichen, wenn du ihn für Unsinn hälst.
Als "Trockenübung" kannst du ihn ja mal lesen, verstehen, und die
Gegenargumente hier auflisten.
MaWin schrieb:> Und wo ist denn das Problem den Standard erst etwas strikter zu> definieren und ihn dann aufzuweiten?> Volle Rückwärtskompatibilität ist gegeben.> Es wurde nichts deprecated. Lediglich erweitert.>> Hättest du es besser gefunden, wenn man den Standard erst komplex> definiert und dann einen folgenschweren Fehler macht, weil man doch> etwas übersehen hat?> Lieber Schritt für Schritt vorgehen.
Ja, richtig, aber das doch nicht normativ! Generell wäre es schon
bedenklich, wenn die Initiative bei einem solchen Gremium liegt.
Deswegen wäre das hier
mh schrieb:> Also einerseits darf der Standard keine kleinen Schritte machen und> andererseits darf der Standard nur ausgereifte Dinge übernehmen. Wie> soll das funktionieren? Soll jeder Compiler und jede> "Standardbibliothek" erstmal drauflos testen?
durchaus eine echte Alternative. Diskussionen und Papers sind ja schön
und gut - es ist aber absolut absehbar, dass wenn erstmal Millionen
Entwickler anfangen mit dem Zeug rumzuspielen, sich da noch das ein oder
andere Problem auftun mag, das man einfach nicht auf dem Schirm hatte.
Ich wüsste nicht zu sagen, ob der schwarze Peter da nun primär beim
Komitee liegt: Wenn man jedenfalls noch-nicht standartisierte Features
testen will muß man zT einiges an Aufwand betreiben, um sich die Sourcen
zu organisieren, die dann ggf. erst noch mergen, komplette Toolchain
erstellen usw. usf. Aber vielleicht ist das ja nur bei uns so und
überall sonst sind "normale" Entwickler an breiter Front ständig dabei,
Feedback zu den neueren Entwicklungen zu geben. Sonst ist das Zeug
einfach relativ schlecht erprobt und man müsste die Frage stellen,
welche prozessualen Safeguards es denn bei der schier unmöglichen
Aufgabe gibt, sämtliche Konsequenzen aus einer 2k-Seitigen Spezifikation
zu erfassen. Ob es dann eine zufriedenstellende Antwort ist, dass man ja
auch einfach Sachen, die einmal normativ gesetzt wurden, wieder
deprecaten könne, mag jeder selbst entscheiden.
Gut ist es in der Tat, dass
mh schrieb:> euch niemand davon abhält das gut getestete c++98 zu nutzen.
wobei 98 nun doch ein wenig alt ist. Mittlerweile sind die Features aus
11 schon fast nutzbar!
Heiko L. schrieb:> ...
Wie stellst du dir das ganze vor? Beispiel:
google möchte sowas wie "move-Semantic" haben. Sie bauen etwas in clang
ein und nutzen es in chrome und ein paar weiteren internen Projekten.
Jetzt ist Microsoft auch unzufrieden mit auto_ptr und möchte nen Ersatz,
hat aber andere Vorstellungen. Also bauen sie etwas in ihren Compiler
ein und nutzen es für ihre Projekte. Beide Unternehmen stellen Probleme
fest und fixen sie und am Ende gibt es zwei funktionierende Varianten
als Ersatz für auto_ptr. Welche der beiden Varianten wird jetzt
standardisiert und was ist wenn beides nicht im gcc umsetzbar ist? Was
macht Microsoft, wenn die clang Variante ausgewählt wird? Glaubst du
ernsthaft, die sind bereit ihre gut funktionierende Lösung zu ersetzen
oder die clang Variante ohne eigenen Bedarf in ihren Compiler
einzubauen? Was ist mit Dingen, die Standardlib und Compiler betreffen?
Sollen wir mit libs leben, die nur mit einem Compiler funktionieren?
Es gibt einen Grund, warum der Prozess so ist, wie er aktuell ist. Weil
er funktioniert. Dass dabei nicht jeder mit allen Neureungen zufrieden
ist und Fehler gemacht werden, wird von der Allgemeinheit akzeptiert.
Dass du mit dem Prozess unzufrieden bist, ist schlicht egal. Es gibt
allerdings Möglichkeiten dich in den Prozess einzubringen und diese so
offensichtlichen Fehler zu vermeiden, wenn du willst.
mh schrieb:> Es gibt einen Grund, warum der Prozess so ist, wie er aktuell ist. Weil> er funktioniert. Dass dabei nicht jeder mit allen Neureungen zufrieden> ist und Fehler gemacht werden, wird von der Allgemeinheit akzeptiert.> Dass du mit dem Prozess unzufrieden bist, ist schlicht egal. Es gibt> allerdings Möglichkeiten dich in den Prozess einzubringen und diese so> offensichtlichen Fehler zu vermeiden, wenn du willst.
Genau, das meinte ich. Aber das sind wir Rufer in der Wüste.
Die, die hier am lautesten lamentieren, werden sich wohl nicht
beteiligen, sondern nur weiterhin von der Arbeit anderer leben. Das ist
mit dem qualifizierten Reporting von bugs für den Standard an sich oder
dem clang oder gcc genauso. Leider.
vn nn schrieb:> Gerade die STL algorithms ermöglichen es, des Spagat aus Performant und> leserlich endlich besser hinzukriegen. Generell wird in aktuelleren> Standards der Fokus sehr stark auf zero overhead gelegt.
Bei der STL mußt du erstmal einen eigenen Allokator schreiben um
dynamische Speicherverwaltung loszuwerfen - und Exceptions wirst du
überhaupt nicht los.
Wir arbeiten hier an Projekten, die müssen mit 8k Flash auskommen und
das SRAM ist an einer Hand abgezählt. Da muss man schon mit C gut planen
und aufpassen, wie man programmiert.
Welcher Programmierer versteht heute noch, was dynamic_cast mit sich
bringt, wann ganz ohne Absicht hinter den Kulissen copy-by-value statt
findet, wie Exception Handling vom Compiler umgesetzt wird, wie Lambdas
umgesetzt werden. Die ganze Sprache ist unglaublich komplex geworden.
Zero overhead bringt nichts, wenn ein Normalprogrammierer nicht mehr
begreifen kann, wie er denn zero overhead erreichen kann.
Klar, niemand zwing mich zu irgendwas. Aber dann frage ich mich doch,
warum laufen überall C++ Päpste durch die Gegend und wollen Leute
bekehren? Dann lasst das doch, wenn das Hauptargument am Ende "mußt du
ja nicht nehmen" ist, sobald jemand ein Problem aufzeigt. Und die
anderen, die keine Probleme sehen lässt man ins offene Messer laufen -
Hauptsache jemanden bekehrt.
vn nn schrieb:> Und ja, es ist gut dass eine neue> Sprache entsteht, und man den Kompatibilitätquatsch nicht mitschleppen> muss.
Genau die Einstellung die ich beschrieb.
x^2 schrieb:> vn nn schrieb:>> Gerade die STL algorithms ermöglichen es, des Spagat aus Performant und>> leserlich endlich besser hinzukriegen. Generell wird in aktuelleren>> Standards der Fokus sehr stark auf zero overhead gelegt.>> Bei der STL mußt du erstmal einen eigenen Allokator schreiben um> dynamische Speicherverwaltung loszuwerfen
Wo genau benötigt std::array oder std::tuple einen Allocator?
> Wir arbeiten hier an Projekten, die müssen mit 8k Flash auskommen und> das SRAM ist an einer Hand abgezählt. Da muss man schon mit C gut planen> und aufpassen, wie man programmiert.
Sehr gut!
> Welcher Programmierer versteht heute noch, was dynamic_cast mit sich> bringt, wann ganz ohne Absicht hinter den Kulissen copy-by-value statt> findet, wie Exception Handling vom Compiler umgesetzt wird, wie Lambdas> umgesetzt werden. Die ganze Sprache ist unglaublich komplex geworden.
Das ist ein Allgemeinplatz: die µC von heute sind auch komplexer als vor
10 Jahren. Lässt Du die auch links liegen, weil komplex? Das ist doch
Pipi-Langstrumpf-Geschwafel.
> Zero overhead bringt nichts, wenn ein Normalprogrammierer nicht mehr> begreifen kann, wie er denn zero overhead erreichen kann.
Dann muss man ihn dahin bringen, dass er das versteht. Bzw. ihm einen
Baukasten an die Hand geben, mit dem er zugleich fehlerfreier,
produktiver und effektiver ist.
> Klar, niemand zwing mich zu irgendwas. Aber dann frage ich mich doch,> warum laufen überall C++ Päpste durch die Gegend und wollen Leute> bekehren?
Ich will Dich überhaupt nicht bekehren. Am besten bleibst Du, wo Du
bist, und überliest ab jetzt einfach die Beiträge hier.
x^2 schrieb:> Klar, niemand zwing mich zu irgendwas. Aber dann frage ich mich doch,> warum laufen überall C++ Päpste durch die Gegend und wollen Leute> bekehren? Dann lasst das doch, wenn das Hauptargument am Ende "mußt du> ja nicht nehmen" ist, sobald jemand ein Problem aufzeigt. Und die> anderen, die keine Probleme sehen lässt man ins offene Messer laufen -> Hauptsache jemanden bekehrt.
Mir geht es nicht darum, dich oder irgend jemanden zu bekehren. Ich kann
gut damit leben, wenn es weniger C++ Entwickler gibt. Das bedeutet
weniger Konkurrenz und es besteht keine Möglichkeit, dass ich mit dir
zusammenarbeiten muss ;-). Mir geht es darum, deine und ähnliche
Meinungen nicht unkommentiert im Internet stehen zu lassen. Sonst
besteht die Möglichkeit, dass andere Leute sie lesen und unreflektiert
übernehmen.
mh schrieb:> Wie stellst du dir das ganze vor?
Tja, das gälte es wohl zu erarbeiten.
mh schrieb:> Also bauen sie etwas in ihren Compiler> ein und nutzen es für ihre Projekte. Beide Unternehmen stellen Probleme> fest und fixen sie und am Ende gibt es zwei funktionierende Varianten> als Ersatz für auto_ptr.
Wunderbar. Da hätte man ja echt die Wahl! Nicht, dass es nicht
realistisch eher tausende Implementierungen von auto_ptr gäbe.
In GCC jedenfalls wurden Lambdas auch eingebaut obwohl es ja
statement-expressions schon lange gab. Keine Ahnung, wie groß der
Widerstand da war.
mh schrieb:> Was ist mit Dingen, die Standardlib und Compiler betreffen?> Sollen wir mit libs leben, die nur mit einem Compiler funktionieren?
Du hast aber schon mal eine "real existierende", "compiler-neutrale"
Library gesehen, oder?
1
XYZ_EXPORT XYZ_STDCALL(something, void, int x[XYZ_STATIC 4] XYZ_RESTRICT, ...
Dann kommen noch Sachen dazu, wie komische ABI Issues uns schon verpufft
das tolle "ist doch Standard" vollends. Man muss sich schon angewöhnen,
clang-tidy zu ignorieren (oder abschalten).
mh schrieb:> Es gibt einen Grund, warum der Prozess so ist, wie er aktuell ist. Weil> er funktioniert.
"Funktionieren" tut auch eine Lampe mit offener Phase. Ob das nun ein
Argument ist...
mh schrieb:> Dass dabei nicht jeder mit allen Neureungen zufrieden> ist und Fehler gemacht werden, wird von der Allgemeinheit akzeptiert.
Du meinst: von dir, weil es dir egal ist.
Bei der obigen Lampe muß man auch nur ein bisschen aufpassen und alles
ist wunderbar.
mh schrieb:> Es gibt> allerdings Möglichkeiten dich in den Prozess einzubringen und diese so> offensichtlichen Fehler zu vermeiden, wenn du willst.
Ach, ich denke, das Thema wird da schon durchgekaut worden sein und
Meinungen sind Meinungen, nicht wahr?
Heiko L. schrieb:> In GCC jedenfalls wurden Lambdas auch eingebaut obwohl es ja> statement-expressions schon lange gab. Keine Ahnung, wie groß der> Widerstand da war.
Da gab es sicher gar keinen Widerspruch, weil statement-expressions und
Lambda-Ausdrücke zwei völlig verschiedene Dinge sind. Ok, Lambdas können
u.a. auch als Ersatz für statement-expressions herhalten, aber der
umgekehrte Weg ist nicht möglich.
Yalu X. schrieb:> Heiko L. schrieb:>> In GCC jedenfalls wurden Lambdas auch eingebaut obwohl es ja>> statement-expressions schon lange gab. Keine Ahnung, wie groß der>> Widerstand da war.>> Da gab es sicher gar keinen Widerspruch, weil statement-expressions und> Lambda-Ausdrücke zwei völlig verschiedene Dinge sind. Ok, Lambdas können> u.a. auch als Ersatz für statement-expressions herhalten, aber der> umgekehrte Weg ist nicht möglich.
Nicht 100%ig, nein. Das war auch nur ein Beispiel einer speziellen
Lösung, die gewissermaßen subsumiert wurde.
Wilhelm M. schrieb:> Wo genau benötigt std::array oder std::tuple einen Allocator?
Das nenne ich mal unseriös. Die sind hier:
std::vector
std::deque
std::forward_list
std::list
std::set
std::multiset
std::map
std::multimap
std::unordered_set
std::unordered_multiset
std::unordered_multimap
std::unordered_map
std::unordered_multimap
Und was da dann noch von der STL übrig bleibt hast du aufgezählt. Und
diesen kläglichen Rest programmiert dir ein durchschnittlich begabter
Erstsemester an einem Tag. Entsprechend nützlich ist die STL auch ohne
dynamischen Speicher bzw. ohne einen Custom Allokator.
x^2 schrieb:> vn nn schrieb:>> Gerade die STL algorithms ermöglichen es, des Spagat aus Performant und>> leserlich endlich besser hinzukriegen. Generell wird in aktuelleren>> Standards der Fokus sehr stark auf zero overhead gelegt.>> Bei der STL mußt du erstmal einen eigenen Allokator schreiben um> dynamische Speicherverwaltung loszuwerfen - und Exceptions wirst du> überhaupt nicht los.
Bullshit. Nur weil du es nicht kannst? Wofür brauchst du bei std::array
einen Allokator? Was hindert dich daran, das Array einfach statisch zu
allozieren, wenn du keinen dynamischen Speicher haben willst? Was
hindert dich daran, auf Funktionen die Exceptions werfen, zu verzichten?
Und wenn du es dir unbedingt antun willst, was hindert dich daran,
einfach ein klassisches C-Array zu verwenden, auch in C++?
Keiner zwingt dich, Features zu nutzen. Jedem ist klar, dass nicht jedes
Feature überall Sinn macht.
x^2 schrieb:> Wir arbeiten hier an Projekten, die müssen mit 8k Flash auskommen und> das SRAM ist an einer Hand abgezählt. Da muss man schon mit C gut planen> und aufpassen, wie man programmiert.
Und?
x^2 schrieb:> Welcher Programmierer versteht heute noch, was dynamic_cast mit sich> bringt, wann ganz ohne Absicht hinter den Kulissen copy-by-value statt> findet, wie Exception Handling vom Compiler umgesetzt wird, wie Lambdas> umgesetzt werden. Die ganze Sprache ist unglaublich komplex geworden.> Zero overhead bringt nichts, wenn ein Normalprogrammierer nicht mehr> begreifen kann, wie er denn zero overhead erreichen kann.
Tja, genauso wie ein ein Embedded-Entwickler wissen sollte, dass printf
und malloc auf kleinen Systemen Tabu sind, muss er halt wissen, welche
Features er in C++ (oder jeden anderen Sprache) nutzen kann. Kann er das
nicht, hätte er halt was anderes lernen sollen. Oder einfach
Wisch-App-Programmierer, dort ist Performance und Gebastel egal.
x^2 schrieb:> Klar, niemand zwing mich zu irgendwas. Aber dann frage ich mich doch,> warum laufen überall C++ Päpste durch die Gegend und wollen Leute> bekehren?
Wo denn? Keiner will dich bekehren. Bleib einfach bei dem was du willst.
Nachdem du ja sowieso nix sinnvolles zur Diskussion beitragen kannst
(nicht mal erläutern, warum das vorgeschlagene Entfernen von volatile
nun böse ist), werden sich deine C-Kentnisse eh auch in Grenzen halten.
Denn wer seine Programmiersprache kennt, weiß halt welche Features
suboptimal gelöst sind. Außer natürlich, er ist ideologisch verblendet,
und hält seinen Liebling für die Spitze der Evolution.
x^2 schrieb:> wenn das Hauptargument am Ende "mußt du> ja nicht nehmen" ist, sobald jemand ein Problem aufzeigt.
Weil du zu beschränkt bist um unterscheiden zu können, welche Features
du im Embedded-Bereich nutzen kannst (und große Vorteile gegenüber C
bieten), und welche nicht?
x^2 schrieb:> Und die> anderen, die keine Probleme sehen lässt man ins offene Messer laufen -> Hauptsache jemanden bekehrt.
Bitte was?
x^2 schrieb:> vn nn schrieb:>> Und ja, es ist gut dass eine neue>> Sprache entsteht, und man den Kompatibilitätquatsch nicht mitschleppen>> muss.>> Genau die Einstellung die ich beschrieb.
Na, dann klär uns doch auf, wo du das Problem siehst, "volatile" zu
eliminieren und gegen sinnvollere Sprachmittel auszutauschen? Achso,
weil du dir dann plötzlich Gedanken machen musst, anstatt einfach
pauschal mit volatile um dich zu werfen? Weil du dann plötzlich umlernen
musst?
Heiko L. schrieb:> mh schrieb:>> Wie stellst du dir das ganze vor?>> Tja, das gälte es wohl zu erarbeiten.
Also nur meckern und keine Lösung.
> Wunderbar. Da hätte man ja echt die Wahl!
Das genaue Gegenteil ist der Fall. Man kann nur noch das benutzen was
der eine Compiler unterstützt wenn man eins der "exclusiven Features"
nutzt.
Niemand hat etwas dagegen, dass die Compilerentwickler Extensions
einbauen und testen. Das ist sogar sehr wichtig. Du kannst aber nicht
erwarten, dass die in vielen großen Projekten getestet werden, weil
niemand bereit ist die Änderungen rückgängig zu machen, wenn die
Konkurrenz im Standard landet. Diese Test in vielen großen Projekten
wären aber notwendig, um Probleme zu finden und zu bewerten.
Es wäre sogar nötig, dass ganz neue Softwareprojekte gestartet werden
mit diesen experimentellen Extensions und Features, damit neue Wege
gegangen werden können die dadurch ermöglicht werden.
> Du hast aber schon mal eine "real existierende", "compiler-neutrale"> Library gesehen, oder?XYZ_EXPORT XYZ_STDCALL(something, void, int> x[XYZ_STATIC 4] XYZ_RESTRICT, ...> Dann kommen noch Sachen dazu, wie komische ABI Issues uns schon verpufft> das tolle "ist doch Standard" vollends. Man muss sich schon angewöhnen,> clang-tidy zu ignorieren (oder abschalten).
Klar hab ich real existierende Libs gesehen. Und das was du da
ansprichst hat wenig mit der Sprache zu tun als mit dem System auf dem
sie angewendet wird.
> Ach, ich denke, das Thema wird da schon durchgekaut worden sein und> Meinungen sind Meinungen, nicht wahr?
Genau! Du hast es endlich verstanden. Die Leute, die den Standard
entwickeln, haben sich lange damit beschäftigt und haben Ahnung von dem
was sie tun. Der Standard beruht auf Forschung, Fakten, Tests und
Kompromissen. Und deine Meinung ist nur eine Meinung und keine Lösung
für irgendwas.
x^2 schrieb:> Und was da dann noch von der STL übrig bleibt hast du aufgezählt.
Du solltest mal in den Standard gucken. Da steht noch etwas mehr drin
als Container.
x^2 schrieb:> Wilhelm M. schrieb:>> Wo genau benötigt std::array oder std::tuple einen Allocator?>> Das nenne ich mal unseriös. Die sind hier:> [...]> Und was da dann noch von der STL übrig bleibt hast du aufgezählt. Und> diesen kläglichen Rest programmiert dir ein durchschnittlich begabter> Erstsemester an einem Tag. Entsprechend nützlich ist die STL auch ohne> dynamischen Speicher bzw. ohne einen Custom Allokator.
Äh, du willst Features verwenden die dynamischen Speicher brauchen, aber
ohne dynamischen Speicher zu verwenden? Aber sonst gehts noch?
Ein durchschnittlich begabter Erstsemester wird dir sagen können, dass
du keine Ahnung hast.
Wilhelm M. schrieb:> Das ist ein Allgemeinplatz: die µC von heute sind auch komplexer als vor> 10 Jahren. Lässt Du die auch links liegen, weil komplex? Das ist doch> Pipi-Langstrumpf-Geschwafel.
Also gerade bei den gebrachten Argumenten würde ich auch zur Vorsicht
raten. Die Feinheiten von dynamic_cast und exceptions dürften in
höchstem Maße von der Architektur abhängig sein.
Da ist es, wenn es um wiederverwendbaren Code geht, absolut nicht
absehbar, ob man sich nicht in eine Sackgasse manövriert und das Zeug
auf Controller X nicht absolut unbrauchbar wird.
Das schreibe ich jetzt, auch wenn ich mich jedesmal darüber ärgere, wenn
ich mich wieder einmal mit irgendeiner C-Library herumschlagen muss.
Unter dem Ärger muss man einfach gestehen: Das Zeug funktioniert
wenigstens überall "problemlos". Keine komischen Unwind-Fehler, die
sofort das Programm terminieren. Keine uncatchbaren Exceptions oder
unmögliche dynamic_casts wegen fehlender Key-Functions in Interfaces
usw.
x^2 schrieb:> Das nenne ich mal unseriös. Die sind hier:
Und Du verwendest auf Deinen Systemen mit 8k Flash und - nach Deiner
Aussage - an der Hand abgezählten Bytes RAM - einen dynamischen
Allocator bzw. malloc oder dgl? Oh je ...
Du solltest jetzt mal an Deinem Diskussionsstil arbeiten, damit Du Dich
nicht permanent im Kreis drehst.
mh schrieb:> Also nur meckern und keine Lösung.
Richtig. Das zu akzeptieren nennt sich "Kritikfähigkeit".
mh schrieb:> Klar hab ich real existierende Libs gesehen. Und das was du da> ansprichst hat wenig mit der Sprache zu tun als mit dem System auf dem> sie angewendet wird.
Ach so, du meinst "die Sprache", die es, im Gegensatz zu ihrem Ausdruck,
real gar nicht gibt. Dort entsteht nämlich der Eindruck, dass es immer
auf solche Schauer-Konstruktionen hinausläuft, wenn man eine Lib nur
genug zwischen Compilern hin- und herschiebt. Also: Funktioniert
eigentlich überall, aber doch nirgends. Funktioniert alles, ist trotzdem
kaputt.
Man muss die Sache schon in ihrer "Wirklichkeit" betrachten.
mh schrieb:> Und deine Meinung ist nur eine Meinung und keine Lösung> für irgendwas.
Was die Fähigkeit zum freien Gedanken beweist. Wenn du Lösungen
diskutieren wolltest, wäre wohl kaum Statements wie
mh schrieb:> Wie gut, dass euch niemand davon abhält das gut getestete c++98 zu> nutzen.
angebracht gewesen. Denn dazu kann man auch eine haben...
vn nn schrieb:> Na, dann klär uns doch auf, wo du das Problem siehst, "volatile" zu> eliminieren und gegen sinnvollere Sprachmittel auszutauschen? Achso,> weil du dir dann plötzlich Gedanken machen musst, anstatt einfach> pauschal mit volatile um dich zu werfen? Weil du dann plötzlich umlernen> musst?
Gut, dann will ich das mal tun: Weil man sorgsam abwägen muss, ob es den
-Aufwand- und die -Probleme- rechtfertigt, die dadurch entstehen. Wenn
du volatile entfernst, wird jeglicher Code der es bis heute verwendet,
nicht mehr mit einer neuen C++ Version compilierbar sein. Ob uns das
gefällt wie volatile funktioniert oder nicht, solchen Code gibt es
nunmal und zwar in Massen.
Damit generierst du Arbeit (sehr viel Arbeit) überall in der Welt ODER
du schließt diejenigen, die diese Arbeit für die Anpassung nicht leisten
können, von der Weiterentwicklung der Sprache aus. Für diese Leute endet
dann C++ mit der neuen Version xyz, weil sie nicht updaten können.
Es ist obendrein -unproduktive- Arbeit, da du ein Produkt nicht
-weiterentwickelst- sondern nur wieder so -anpasst- dass es im gleichen
Zustand wie bisher auch weiterfunktioniert. Diese Zeit fehlt dann den
Entwicklern bei der Weiterentwicklung und Verbesserung des eigentlichen
Produkts. So eine Sprache ist ja kein Selbstzweck.
Und das NUR weil, überspitzt gesagt, irgendein Hanswurst (pardon)
gedacht hat, dass es statt volatile auch viel hübscher ginge und man das
jetzt ändern müsse.
Würdest du beispielsweise Linus Torvalds schreiben: "Achja Linus, du hör
mal, das mit dem volatile, das war doch schon immer ne blöde Idee. Pass
auf, pass kurz Kernel und die Treiber an, dann läuft's auch unter dem
neuen C++ Standard." - ich bin mir sicher er würde dir dafür den Kopf
abreißen.
Das gilt sinngemäß für alle inkompatiblen Änderungen.
vn nn schrieb:> Äh, du willst Features verwenden die dynamischen Speicher brauchen, aber> ohne dynamischen Speicher zu verwenden? Aber sonst gehts noch?> Ein durchschnittlich begabter Erstsemester wird dir sagen können, dass> du keine Ahnung hast.
Nein, diese Feature brauchen eben keinen dynamischen Speicher. Seit wann
brauchen Datenstrukturen zwingend dynamischen Speicher.
Selbstverständlich geht rein statischer Speicher. Dadurch beschränkt man
die Kapazität z.B. einer Queue, aber der Speicher auf kleinen
Controllern ist eben endlich und es muss entsprechend abgeschätzt und
geplant werden.
Die STL wurde nicht für Embedded geschrieben, deswegen ja auch
"Standard" Template Library. Und da statischer Speicher bei der STL
nicht out-of-the-box geht, bräuchte man zusätzlich einen Allokator, der
auf diesem arbeitet.
x^2 schrieb:> Und das NUR weil, überspitzt gesagt, irgendein Hanswurst (pardon)> gedacht hat, dass es statt volatile auch viel hübscher ginge und man das> jetzt ändern müsse.
Man merkt, dass du die Paper nicht gelesen hast oder sie nicht verstehen
kannst oder willst.
PS: ich muss mal wieder beim Rothfüsser nachgucken wann der dritte Teil
rauskommt ...
x^2 schrieb:> Würdest du beispielsweise Linus Torvalds schreiben: "Achja Linus, du hör> mal, das mit dem volatile, das war doch schon immer ne blöde Idee. Pass> auf, pass kurz Kernel und die Treiber an, dann läuft's auch unter dem> neuen C++ Standard." - ich bin mir sicher er würde dir dafür den Kopf> abreißen.
Der linux kernel enthält kein C++, das ist alles nur C.
x^2 schrieb:> Gut, dann will ich das mal tun: Weil man sorgsam abwägen muss, ob es den> -Aufwand- und die -Probleme- rechtfertigt, die dadurch entstehen. Wenn> du volatile entfernst, wird jeglicher Code der es bis heute verwendet,> nicht mehr mit einer neuen C++ Version compilierbar sein. Ob uns das> gefällt wie volatile funktioniert oder nicht, solchen Code gibt es> nunmal und zwar in Massen.
Tja, genau dieser Punkt wird in dem Paper auch abgewogen. Offensichtlich
hast du es nicht gelesen, regst dich aber trotzdem darüber auf.
x^2 schrieb:> Damit generierst du Arbeit (sehr viel Arbeit) überall in der Welt ODER> du schließt diejenigen, die diese Arbeit für die Anpassung nicht leisten> können, von der Weiterentwicklung der Sprache aus. Für diese Leute endet> dann C++ mit der neuen Version xyz, weil sie nicht updaten können.
Tja, wer nicht auf den neuen Sprachstandard wechseln will, kann ja beim
alten bleiben.
Entweder ich will Veränderung, oder ich will sie nicht.
x^2 schrieb:> Es ist obendrein -unproduktive- Arbeit, da du ein Produkt nicht> -weiterentwickelst- sondern nur wieder so -anpasst- dass es im gleichen> Zustand wie bisher auch weiterfunktioniert. Diese Zeit fehlt dann den> Entwicklern bei der Weiterentwicklung und Verbesserung des eigentlichen> Produkts. So eine Sprache ist ja kein Selbstzweck.
Natürlich ändert sich das Verhalten. Lies doch das PAper, bevor du dich
darüber auslässt.
x^2 schrieb:> Und das NUR weil, überspitzt gesagt, irgendein Hanswurst (pardon)> gedacht hat, dass es statt volatile auch viel hübscher ginge und man das> jetzt ändern müsse
"irgendein Hanswurst": leitender Entwickler in der Compilerentwicklung
von Apple
Alles klar, dir sicher um Längen überlegen.
Aber wie du beim lesen des Papers sicher gemerkt hast, handelt es sich
dabei nur um einen Draft, also einen Vorschlag. Du kannst natürlich
jederzeit deine Meinung als Kommentar einreichen, um das Komitee davon
zu überzeugen, dass dieser Hanswurst da Blödsinn vorgeschlagen hat.
x^2 schrieb:> Würdest du beispielsweise Linus Torvalds schreiben: "Achja Linus, du hör> mal, das mit dem volatile, das war doch schon immer ne blöde Idee. Pass> auf, pass kurz Kernel und die Treiber an, dann läuft's auch unter dem> neuen C++ Standard." - ich bin mir sicher er würde dir dafür den Kopf> abreißen.
Im Linux-Kernel wird kein C++ verwendet, aber das weißt du sicher.
Der Kernel wird auch nach wie vor C89-kompatibel geschrieben, damit wäre
eine ähnliche Argumentation auch für C89 vs. C99 hinfällig.
Aber ja, auch in C89 waren noch einige Dinge möglich, die in C99 oder
C11 nicht mehr gehen. Stell dir vor, dann müsste man doch tatsächlich
den Code anpassen, bevor man den Sprachstandard wechselt!!1!!elf
Natürlich hat man vorgesorgt, und verlangt in den Guidelines, dass der
Code sowohl C89- als auch C99-kompatibel sein muss.
x^2 schrieb:> Das gilt sinngemäß für alle inkompatiblen Änderungen.
Tja, ohne Änderungen gibts keine Änderungen. Und nichts nervt in C++
oder auch in C mehr, als dass immer noch jede Menge historisch
gewachsener Dinge mitgeschleppt werden.
x^2 schrieb:> Nein, diese Feature brauchen eben keinen dynamischen Speicher. Seit wann> brauchen Datenstrukturen zwingend dynamischen Speicher.
Natürlich brauchen gewisse Datenstrukturen dynamischen Speicher, nämlich
dann, wenn ich z.B. Elemente dynamisch (na, merkst du was?) anhängen
will.
Will oder kann ich keinen dynamischen allozierten Speicher nutzen, muss
ich eine Datenstruktur verwenden, die auf statisch Verwendung ausgelegt
ist. Genau deswegen bietet die STL ja auch drölf verschiedene
Datenstrukturen.
x^2 schrieb:> Selbstverständlich geht rein statischer Speicher. Dadurch beschränkt man> die Kapazität z.B. einer Queue, aber der Speicher auf kleinen> Controllern ist eben endlich und es muss entsprechend abgeschätzt und> geplant werden.
Richtig, deswegen bietet die STL auch solche an.
x^2 schrieb:> Die STL wurde nicht für Embedded geschrieben, deswegen ja auch> "Standard" Template Library. Und da statischer Speicher bei der STL> nicht out-of-the-box geht, bräuchte man zusätzlich einen Allokator, der> auf diesem arbeitet.
Bullshit.
Nochmal: std::array.
std::vector bietet dynamisches Anhängen von Elementen, das geht nunmal
nicht rein statisch.
std::list ist eine doppelt verkettete Liste, wenn du RAM-Bytes zählen
musst also ohnehin das falsche Werkzeug.
Du versuchst wahrscheinlich auch, einen Nagel mit dem Schraubendreher
einzuschlagen, und wunderst dich, dass das nicht vernünftig geht, und
beschließt, dass der ganze Werkzeugkasten deswegen Müll ist.
Aber bitte, deine Meinung sei dir unbenommen. Ich frage mich nur, warum
versuchst du hier zu missionieren?
vn nn schrieb:> Bullshit.>> Nochmal: std::array.> std::vector bietet dynamisches Anhängen von Elementen, das geht nunmal> nicht rein statisch.> std::list ist eine doppelt verkettete Liste, wenn du RAM-Bytes zählen> musst also ohnehin das falsche Werkzeug.
Was "x^2" verwenden möchte, ist bspw. ein std::vector mit variabler
size, aber konstanter, zur Compilezeit festgelegter capacity.
Entsprechdes kann man sich auch für andere Container, wie bspw.
std::deque vorstellen. Auch std::list ist mit statischem Speicher
möglich, wenn man man den Allocator so schreibt, dass er die Elemente
aus einem vorgegebenen Pool (bspw. als std::array implementiert) nimmt.
Das alles ist auch für kleine µC realisierbar, aber man muss eben etwas
Arbeit hineinstecken, die einem die Standardbibliothek nicht abnimmt.
Yalu X. schrieb:> Mehr von der> Sorte, dann erkennen vielleicht irgendwann sogar die Autobauer, dass es> eine modernere Alternative zu C89 gibt :)
Ach, das haben die schon vor einer ganzen Weile erkannt. Wirklich in
purem C programiert da heute kaum noch jemand.
guest schrieb:> Yalu X. schrieb:>> Mehr von der>> Sorte, dann erkennen vielleicht irgendwann sogar die Autobauer, dass es>> eine modernere Alternative zu C89 gibt :)>> Ach, das haben die schon vor einer ganzen Weile erkannt. Wirklich in> purem C programiert da heute kaum noch jemand.
Wirklich?
Ich meine jetzt nicht in Infotainmentsystemen, wo fette Prozessoren und
ausgewachsene Betriebssysteme zum Einsatz kommen, sondern in den
Motorsteuergeräten, einfachen Fahrassistenzsystemen und dergleichen, wo
das meiste bare-metal programmiert wird.
Das letzte Mal, als ich in dem Bereich zu tun hatte, wäre jemand
gesteinigt worden, der das Wort "C++" auch nur geflüstert hätte. Das ist
zwar schon ein paar Jahre her, aber ein paar Jahre sind in der
Autoindustrie eine kurze Zeit, da bewegt sich üblicherweise nicht so arg
viel.
vn nn schrieb:> Natürlich brauchen gewisse Datenstrukturen dynamischen Speicher, nämlich> dann, wenn ich z.B. Elemente dynamisch (na, merkst du was?) anhängen> will.
Nein, brauchen sie nicht. Man kann jede Datenstruktur für statischen
Speicher implementieren. Ich brauche da nichts merken, ich arbeite im
Embedded Bereich seit über 10 Jahren, wir machen das täglich. Haben
eigene Implementierungen für Queues, Maps, Trees, ... basierend auf
-statischem Speicher-
Yalu hat's oben erklärt.
> Will oder kann ich keinen dynamischen allozierten Speicher nutzen, muss> ich eine Datenstruktur verwenden, die auf statisch Verwendung ausgelegt> ist. Genau deswegen bietet die STL ja auch drölf verschiedene> Datenstrukturen.
Und genau diese drölf verschiedenen arbeiten mit dynamischem Speicher
und deshalb bräuchte man einen Allokator dafür. Und wie schon gesagt,
Exceptions kann man in Airbag-Steuergeräten und Co auch nicht
gebrauchen.
Mir ist bekannt, dass Linux auf C basiert, das war überhaupt nicht der
Zusammenhang: Großes Projekt = viel Anpassungsarbeit.
vn nn schrieb:> Natürlich ändert sich das Verhalten. Lies doch das PAper, bevor du dich> darüber auslässt.
Das ist ja noch schlimmer, wenn sich das Verhalten ändert: Dann reicht
ja noch nicht mal Textersetzung A->B, sondern man darf jede einzelne
Komponente überarbeiten und wieder die korrekte Funktion durchtesten
damit es mit der neuen C++ Version funktioniert.
Ich frage mich im übrigen, ob hier irgendwer nach Normen und
Zertifizierungen arbeitet: Als ob man das ganze Projekt jeden Freitag
auf 180 Grad zieht, um die neuen Features vom Hanswurst mit bedeutender
Funktion bei Apple einzupflegen, und dann Montag an den Kunden
ausliefert.
Vincent H. schrieb:> P0843:> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0843r3.html
Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded
gebrauchen.
x^2 schrieb:> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded> gebrauchen.
Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...
Yalu X. schrieb:> Ich meine jetzt nicht in Infotainmentsystemen, wo fette Prozessoren und> ausgewachsene Betriebssysteme zum Einsatz kommen, sondern in den> Motorsteuergeräten, einfachen Fahrassistenzsystemen und dergleichen, wo> das meiste bare-metal programmiert wird.
Da steckt am Ende zwar noch viel C Code drin, aber geschätzt 90% davon
fallen aus irgendwelchen Codegeneratoren ala Simulink/Matlab. So richtig
zu Fuß tut sich das kaum noch jemand an.
In den Infotainmentsystemen steckt dann eher Java :)
mh schrieb:> x^2 schrieb:>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>> gebrauchen.>> Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...
Nur um des Arguments willen: Was wären die vom Standard garantierten
Constraints bezgl. der Objektgröße? O(n)?
Heiko L. schrieb:> mh schrieb:>> x^2 schrieb:>>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>>> gebrauchen.>>>> Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...>> Nur um des Arguments willen: Was wären die vom Standard garantierten> Constraints bezgl. der Objektgröße? O(n)?
42?! Wovon redest du?
mh schrieb:> Heiko L. schrieb:>> mh schrieb:>>> x^2 schrieb:>>>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>>>> gebrauchen.>>>>>> Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...>>>> Nur um des Arguments willen: Was wären die vom Standard garantierten>> Constraints bezgl. der Objektgröße? O(n)?>> 42?! Wovon redest du?
Das könnte hinkommen.
Ich spreche davon, dass viele der STL Klassen für embedded ziemlich
ungeeignet sein dürften, da sie halt auf die häufigsten Use-Cases
getrimmt sind und daher ggf. keine ausreichenden Garantien bezgl. ihres
Speicherbedarfs machen.
Es gibt z.B. noch nicht einmal eine Wrapper-Klasse für (const) char*,
die wirklich einfach nur den einen Pointer verwaltet und ein wenig
syntaktischen Sugar für string-operationen bietet. Und das dann auch
immer noch als size_t. Jeder Container schleppt seinen Allocator mit
herum usw.
Wenn ich mir da so einen 2 Ct. Mikro mit 64 Byte Speicher vorstelle,
passt das nicht. Man sieht sofort, dass ein size_t reine Verschwendung
ist.
Edit: "Häufigster Use-Case" - bei den ganzen Embedded Geräten, müsste
man das evtl. neu definieren.
mh schrieb:> x^2 schrieb:>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>> gebrauchen.>> Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...
Sorry, hast recht: Hatte es überflogen und Kapital 4.4 Exception Safety
so verstanden und dann aufgehört. Er erläutert darin aber nur welche
Exceptions bei den Methoden denkbar -wären-, sagt aber erst am Ende
dazu, dass das so nicht sein soll. Gemein :-)
Heiko L. schrieb:> Ich spreche davon, dass viele der STL Klassen für embedded ziemlich> ungeeignet sein dürften, da sie halt auf die häufigsten Use-Cases> getrimmt sind und daher ggf. keine ausreichenden Garantien bezgl. ihres> Speicherbedarfs machen.
Welche Garantien? Was für ein Speicherbedarf? Wer ist schuld, wenn deine
Stdlib nicht für deinen Usecase optimiert ist? Der Standard, oder du
weil du nicht die richtige Lib ausgesucht hast?
Heiko L. schrieb:> Wenn ich mir da so einen 2 Ct. Mikro mit 64 Byte Speicher vorstelle,> passt das nicht. Man sieht sofort, dass ein size_t reine Verschwendung> ist.
1.) Wie groß ist ein std::size_t auf deinem 64 Byte Mikro?
2.) Warum ist das beim aktuellen Thema wichtig?
mh schrieb:> Heiko L. schrieb:>> Ich spreche davon, dass viele der STL Klassen für embedded ziemlich>> ungeeignet sein dürften, da sie halt auf die häufigsten Use-Cases>> getrimmt sind und daher ggf. keine ausreichenden Garantien bezgl. ihres>> Speicherbedarfs machen.> Welche Garantien? Was für ein Speicherbedarf? Wer ist schuld, wenn deine> Stdlib nicht für deinen Usecase optimiert ist? Der Standard, oder du> weil du nicht die richtige Lib ausgesucht hast?>> Heiko L. schrieb:>> Wenn ich mir da so einen 2 Ct. Mikro mit 64 Byte Speicher vorstelle,>> passt das nicht. Man sieht sofort, dass ein size_t reine Verschwendung>> ist.>> 1.) Wie groß ist ein std::size_t auf deinem 64 Byte Mikro?> 2.) Warum ist das beim aktuellen Thema wichtig?
Jetzt kommt Poker:
1
According to the 1999 ISO C standard (C99), size_t is an unsigned integer type of at least 16 bit (see sections 7.17 and 7.18.3).
Heiko L. schrieb:> Jetzt kommt Poker:> According to the 1999 ISO C standard (C99), size_t is an unsigned> integer type of at least 16 bit (see sections 7.17 and 7.18.3).>> Was glaubst du, wie groß der ist?
Ich kann dir ne untere Grenze geben ...
Was hat das mit dem Thema zu tun?
mh schrieb:> Heiko L. schrieb:>> Jetzt kommt Poker:>> According to the 1999 ISO C standard (C99), size_t is an unsigned>> integer type of at least 16 bit (see sections 7.17 and 7.18.3).>>>> Was glaubst du, wie groß der ist?>> Ich kann dir ne untere Grenze geben ...> Was hat das mit dem Thema zu tun?
War das eine Antwort?
Heiko L. schrieb:> mh schrieb:>> Heiko L. schrieb:>>> War das eine Antwort?>>>> Soll ich ne Zahl erfinden? Und warum muss ich auf Fragen antworten, du>> aber nicht?>> Oh je....
Was ist los? Ist der Groschen gefallen und du hast verstanden warum
size_t für einen Container irrelevant ist? Unwahrscheinlich ...
mh schrieb:> Heiko L. schrieb:>> mh schrieb:>>> Heiko L. schrieb:>>>> War das eine Antwort?>>>>>> Soll ich ne Zahl erfinden? Und warum muss ich auf Fragen antworten, du>>> aber nicht?>>>> Oh je....>> Was ist los? Ist der Groschen gefallen und du hast verstanden warum> size_t für einen Container irrelevant ist? Unwahrscheinlich ...
Welche?
vn nn schrieb:> x^2 schrieb:>> Die letzten Jahre und die Richtung zeigt aber, z.B. "Deprecating>> volatile">>>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r3.html>> Es handelt sich dabei um einen Vorschlag. Es steht dir völlig frei,> Gegenargumente einzureichen, wenn du ihn für Unsinn hälst.> Als "Trockenübung" kannst du ihn ja mal lesen, verstehen, und die> Gegenargumente hier auflisten.
Nein, wie man dem Protokoll
(http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/n4826.pdf)
entnehmen kann, wurde der Vorschlag bereits angenommen:
> Motion 19> Move to apply the changes in P1152R4 (Deprecating volatile) to the C++ working
paper.
> There are objections in the room.> In favour : 63> Opposed : 1> Abstain : 7> Motion passes.
Philipp Klaus K. schrieb:> Nein, wie man dem Protokoll> (http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/n4826.pdf)> entnehmen kann, wurde der Vorschlag bereits angenommen:>>> Motion 19>> Move to apply the changes in P1152R4 (Deprecating volatile) to the C++ working> paper.>> There are objections in the room.>> In favour : 63>> Opposed : 1>> Abstain : 7>> Motion passes.
Der Schritt kann rückgängig gemacht werden ...
mh schrieb:> Philipp Klaus K. schrieb:>> Nein, wie man dem Protokoll>> (http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/n4826.pdf)>> entnehmen kann, wurde der Vorschlag bereits angenommen:>>>>> Motion 19>>> Move to apply the changes in P1152R4 (Deprecating volatile) to the C++ working>> paper.>>> There are objections in the room.>>> In favour : 63>>> Opposed : 1>>> Abstain : 7>>> Motion passes.>> Der Schritt kann rückgängig gemacht werden ...
Ist im gcc-trunk (10) schon seit ca. 6 Wochen drin.
x^2 schrieb:> Jedenfalls, es war ursprünglich mal schön, dass C und C++ eine Familie> war, wobei C im Wesentlichen eine Untermenge von C++ abbildete. Es> ermöglichte Skalierung wobei man bei Projekten unterschiedlicher Größe> und Einsatzbereiche "in der Familie" bleiben konnte und den Code> wiederverwenden konnte.>> Die letzten Jahre und die Richtung zeigt aber, z.B. "Deprecating> volatile">> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r3.html>> dass das kaputt gemacht wurde und wird. Im Prinzip entsteht eine völlig> neue Sprache und man interessiert sich auch nicht mehr für das> "gestern". Das alte und morsche, es lebe das neue... Schlüsselworte> werden umgenutzt ("auto") oder entfernt ("volatile"), ständig neue> hinzugefügt.
Mit P1152 bin ich nicht vertraut. In R0 hieß es noch "WG14 should be
consulted"; da könnte man versuchen, herauszufinden, ob und mit welchem
Ergebnis das geschah.
Ansonsten ist mein Eindruck, dass WG14 und WG21 durchaus noch Interesse
haben, dass sich die Sprachen nicht unnötig auseinanderentwickeln;
insbesondere auf die Möglichkeit, Header zu schreiben, die man sowohl in
C als auch in C++ nutzen kann, wird Wert gelegt.
Dass C2X für Attribute die C++-Syntax übernommen hat, und _Static_assert
mit 2 Argumentes sind aktuelle Beispiele dafür.
Auch bei der Unterstützung von Unicode und bei memory model / pointer
provenance wird koordiniert.
Philipp
Wilhelm M. schrieb:> Ist im gcc-trunk (10) schon seit ca. 6 Wochen drin.
Ich sag nicht, dass das einfach ist. Aber falls jemand gute Argumente
hat, ist es möglich. Neue und gute Argumente gegen das Paper werden wir
hier siche nicht sehen.
Aber danke für den Hinweis. Ich werd nachher mal testen was der gcc mit
meinen 2 oder 3 volatiles macht.
mh schrieb:> Aber danke für den Hinweis. Ich werd nachher mal testen was der gcc mit> meinen 2 oder 3 volatiles macht.
Vermutlich betrifft es "nur" die compound-assignments.
Wilhelm M. schrieb:> mh schrieb:>> Aber danke für den Hinweis. Ich werd nachher mal testen was der gcc mit>> meinen 2 oder 3 volatiles macht.>> Vermutlich betrifft es "nur" die compound-assignments.
Die Doku sagt
mh schrieb:> Wilhelm M. schrieb:>> mh schrieb:>>> Aber danke für den Hinweis. Ich werd nachher mal testen was der gcc mit>>> meinen 2 oder 3 volatiles macht.>>>> Vermutlich betrifft es "nur" die compound-assignments.>> Die Doku sagt>
1
>SeveralC++20featureshavebeenimplemented:
2
>P1152R4,Deprecatingvolatile
3
>
> keine Einschränkung.
Schon. Ich bezog das nur auf Deinen Code. Es sei denn, Du hast UDT mit
volatile-Elementfunktionen.
x^2 schrieb:> vn nn schrieb:>> Natürlich brauchen gewisse Datenstrukturen dynamischen Speicher, nämlich>> dann, wenn ich z.B. Elemente dynamisch (na, merkst du was?) anhängen>> will.>> Nein, brauchen sie nicht. Man kann jede Datenstruktur für statischen> Speicher implementieren. Ich brauche da nichts merken, ich arbeite im> Embedded Bereich seit über 10 Jahren, wir machen das täglich. Haben> eigene Implementierungen für Queues, Maps, Trees, ... basierend auf> -statischem Speicher->> Yalu hat's oben erklärt.
Tja, und du wunderst dich nun, dass man Spezialfälle nicht mit
Standardlibraries abdecken kann? Ist ja nicht so, dass es sowas in C out
of the box gäbe...
x^2 schrieb:> Und genau diese drölf verschiedenen arbeiten mit dynamischem Speicher> und deshalb bräuchte man einen Allokator dafür. Und wie schon gesagt,> Exceptions kann man in Airbag-Steuergeräten und Co auch nicht> gebrauchen.
Ja dann nutz die doch einfach nicht? Du nutzt doch auch in C kein
malloc?
Und wenn du eine verlinkte Liste ohne dynamischen Speicher haben willst,
kannst du sie ja entweder komplett selbst implementieren wie in C, oder
du leitest dir halt was von std::list ab. Wo ist dein Problem?
Oder noch besser, du nutzt einfach gar kein C++.
x^2 schrieb:> Mir ist bekannt, dass Linux auf C basiert, das war überhaupt nicht der> Zusammenhang: Großes Projekt = viel Anpassungsarbeit.
Ja, die hab ich immer, wenn ich von einem Sprachstandard auf den anderen
wechsle. Will ich das nicht, wechsle ich halt nicht. Von C89 auf C11 mag
unter Umständen auch mit viel Anpassungsarbeit verbunden sein.
Viel schlimmer in dem Zusammenhang: dass du die Papers, die du
verlinkst, offensichtlich nicht mal weiter als bis zum Titel liest.
Vermutlich hast du auch nicht verstanden, dass "deprecated" nicht heißt,
dass es von jetzt auf gleich raus fliegt. Selbst wenn der Vorschlag es
also in C++20 schaffen würde, würde es erst mimt 23 oder noch später
wirklich rausfliegen.
x^2 schrieb:> vn nn schrieb:>> Natürlich ändert sich das Verhalten. Lies doch das PAper, bevor du dich>> darüber auslässt.>> Das ist ja noch schlimmer, wenn sich das Verhalten ändert: Dann reicht> ja noch nicht mal Textersetzung A->B, sondern man darf jede einzelne> Komponente überarbeiten und wieder die korrekte Funktion durchtesten> damit es mit der neuen C++ Version funktioniert.
Welchen Sinn hat ein neuer Sprachstandard, wenn sich nix ändert?
Entweder ich will Veränderung, oder eben nicht. Man wechselt ja auch
nicht einfach mitten in einem laufenden Projekt des wechselns willen.
x^2 schrieb:> Ich frage mich im übrigen, ob hier irgendwer nach Normen und> Zertifizierungen arbeitet: Als ob man das ganze Projekt jeden Freitag> auf 180 Grad zieht, um die neuen Features vom Hanswurst mit bedeutender> Funktion bei Apple einzupflegen, und dann Montag an den Kunden> ausliefert
Ich weiß ja nicht, ob du schonmal irgendwo nach Normen und
Zertifizierungen gearbeitet hast, aber kein Mensch wechselt einfach so
zum Spaß von jeden Freitag den Sprachstandard.
Man upgradet ja auch nicht einfach zum Spaß drei Tage vor Auslieferung
von C89 auf C99 oder von C99 auf C11, warum sollte man dann einfach so
zum Spaß von C++11 auf C++20 wechseln? Drei Tage vor Auslieferung würd
ich nicht mal ein Compilerupdate machen...
Ich frag mich echt, wo deine komplett praxisfernen Vorstellungen
herkommen?
mh schrieb:> x^2 schrieb:>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>> gebrauchen.>> Hast du dir das Paper angeguckt? Es werden keine Exceptions geworfen ...
Lesen ist nicht seine Stärke.
Heiko L. schrieb:> Ich spreche davon, dass viele der STL Klassen für embedded ziemlich> ungeeignet sein dürften, da sie halt auf die häufigsten Use-Cases> getrimmt sind und daher ggf. keine ausreichenden Garantien bezgl. ihres> Speicherbedarfs machen.
Ein komplett statischer Container wir std::array braucht natürlich
keinen Overhead, wofür auch? Auch std::static_vector wird nicht mehr
brauchen, als wenn du selbst sowas zu Fuß implementierst.
Aber natürlich braucht ein Container mit irgendwelchen dynamischen
Features mehr Overhead als ein klassiches C-Array[] oder ein std::array,
egal ob du es nun in C zu Fuß implementierst, oder dein Compilerbauer
für dich in die STL packt.
Wie so oft in C++ oder auch in C ist sowas natürlich vom Compilerbauer
und von der Zielplattform abhängig. Auch in C kann für viele Dinge nach
oben hin nicht garantiert werden. Aber man kann mal davon ausgehen, dass
weder beim gcc, noch clang oder MSVC anfänger sitzen, und sie die Dinge
schon mindestens so effizient implementieren wie du zu Fuß. Die
Compilerotimierung erledigt dann den Rest.
Und ja, Resourceneffizient ist bei C++ immer ein Thema gewesen, auf das
geachtet wurde. Natürlich hält dich aber keiner ab, einen absolut
ineffizienten Compiler zu bauen, tut in C aber auch keiner.
Heiko L. schrieb:> Jeder Container schleppt seinen Allocator mit> herum usw.> Wenn ich mir da so einen 2 Ct. Mikro mit 64 Byte Speicher vorstelle,> passt das nicht. Man sieht sofort, dass ein size_t reine Verschwendung> ist.
Was redest du? Nimm keinen dynamischen Container, dann hat er keinen
Overhead. Dynamik ohne Overhead geht halt nicht.
Heiko L. schrieb:> Jetzt kommt Poker:> According to the 1999 ISO C standard (C99), size_t is an unsigned> integer type of at least 16 bit (see sections 7.17 and 7.18.3).>> Was glaubst du, wie groß der ist?
Ja und nu? Was hat das nun mit C++ zu tun?
mh schrieb:> Was ist los? Ist der Groschen gefallen und du hast verstanden warum> size_t für einen Container irrelevant ist? Unwahrscheinlich ...
Was faselst du die ganze Zeit von size_t und Containern?
Philipp Klaus K. schrieb:> Nein, wie man dem Protokoll> (http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/n4826.pdf)> entnehmen kann, wurde der Vorschlag bereits angenommen:>>> Motion 19>> Move to apply the changes in P1152R4 (Deprecating volatile) to the C++ working> paper.>> There are objections in the room.>> In favour : 63>> Opposed : 1>> Abstain : 7>> Motion passes.
Oh, tatsächlich. Hoppala, mein Fehler. Na immerhin ist scheinbar nicht
nur "irgendein Depp bei Apple" dafür, um mal bei x^2's Wortlaut zu
bleiben. Aber sicher ist er der Meinung, dass auch die 62 anderen
Mitglieder des Komitees keine Ahnung haben, und er als einziger den
Durchblick hat.
vn nn schrieb:> Was faselst du die ganze Zeit von size_t und Containern?
Ich denke, er meint die compiletime-reflection, die wir von
std-containern gewohnt sind via size_type, value_type, und den anderen
traits.
Auf einem µC macht es bspw. durchaus Sinn, bei einer Array<T,
Size>-Implementierung für size_type nur uint8_t zu deklarieren, wenn
(Size < 256) ist, andernfalls uint16_t bzw. uint32_t bei Size > 65535.
Wilhelm M. schrieb:> vn nn schrieb:>> Was faselst du die ganze Zeit von size_t und Containern?>> Ich denke, er meint die compiletime-reflection, die wir von> std-containern gewohnt sind via size_type, value_type, und den anderen> traits.
Bei statischen Containern wird das ja eh wegoptimiert:
1
std::array<uint8_t,4>foo{{1,2,3,4}};
2
size_tbar=foo.size();
3
4
wirdzu
5
6
ldrr3,.L5
7
ldrr3,[r3]
8
strr3,[fp,#-12]
9
movr3,#4
10
strr3,[fp,#-8]
11
.L5:
12
.word.LC0
13
.LC0:
14
.byte1
15
.byte2
16
.byte3
17
.byte4
18
19
ARMgcc8.3.1
Dynamische Container machen bei so wenig RAM ohnehin keinen Sinn.
Wilhelm M. schrieb:> Auf einem µC macht es bspw. durchaus Sinn, bei einer Array<T,> Size>-Implementierung für size_type nur uint8_t zu deklarieren, wenn> (Size < 256) ist, andernfalls uint16_t bzw. uint32_t bei Size > 65535.
Wie stellst du dir vor, dass das Funktionieren soll? Damit würde man
sich jede Menge neuer Probleme aufreissen, für eine Standardbibliothek
völlig ungeeignet...
vn nn schrieb:> Wie stellst du dir vor, dass das Funktionieren soll? Damit würde man> sich jede Menge neuer Probleme aufreissen, für eine Standardbibliothek> völlig ungeeignet...
So zum Beispiel:
Welche Probleme sollen das sein?
size_type bleibt natürlich weiterhin size_t, nur wozu soll ein Container
mit weniger als 256 Elementen dessen Größe in einem size_t speichern?
Vincent H. schrieb:> vn nn schrieb:>> Wie stellst du dir vor, dass das Funktionieren soll? Damit würde man>> sich jede Menge neuer Probleme aufreissen, für eine Standardbibliothek>> völlig ungeeignet...>> So zum Beispiel:>>
Das enable_if kannst Du Dir bei Deinem uint sparen ;-)
> Welche Probleme sollen das sein?
es wäre halt ein nicht-ganz std konformer Container, der size_type
abhängig von der Größe deklariert.
Wilhelm M. schrieb:> Schon. Ich bezog das nur auf Deinen Code. Es sei denn, Du hast UDT mit> volatile-Elementfunktionen.
Ahh. Ich erwarte keine Probleme ;-)
> mh schrieb:>> x^2 schrieb:>>> Jetzt macht man noch die Exceptions raus, dann kann man's für Embedded>>> gebrauchen.
Ich versuche nur aus Heiko heruszukitzeln, was er mit seinen size_t
will. Aber er antwortet nicht ...
vn nn schrieb:> Wilhelm M. schrieb:>> Auf einem µC macht es bspw. durchaus Sinn, bei einer Array<T,>> Size>-Implementierung für size_type nur uint8_t zu deklarieren, wenn>> (Size < 256) ist, andernfalls uint16_t bzw. uint32_t bei Size > 65535.>> Wie stellst du dir vor, dass das Funktionieren soll? Damit würde man> sich jede Menge neuer Probleme aufreissen, für eine Standardbibliothek> völlig ungeeignet...
Für eine allgemeine Stdlib ist das sicher nicht geeignet. Aber für eine
auf sehr kleine CPUs optimierte Lib sieht das villeicht etwas anders
aus. Heiko ist sicher bereit nen Haufen Geld auszugeben, damit sein
std::vector ein oder zwie Byte weniger braucht auf seinem "64 Byte
Mikro" ... (falls der vector nicht aus 3 Pointern besteht)
mh schrieb:> Für eine allgemeine Stdlib ist das sicher nicht geeignet.
Stimmt bedingt.
Da es ja bspw. für die kleinen AVR 8-Bitter keine stdlibc++ gibt, habe
ich schon seit Jahren eine eigene Implementierung, die in diesen
Aspekten von der stdlib abweicht. Und hier kommt kann
compiletime-refection zur vollen Ausprägung, womit der Assembler-Code
immer optimal ist.
Wilhelm M. schrieb:> Da es ja bspw. für die kleinen AVR 8-Bitter keine stdlibc++ gibt
Ich hab ja schon lange nichts mehr mit AVR gemacht, aber wie siehts
eigentlich mit AVR-Support in LLVM aus, ist da was absehbar?
vn nn schrieb:> Wilhelm M. schrieb:>> Da es ja bspw. für die kleinen AVR 8-Bitter keine stdlibc++ gibt>> Ich hab ja schon lange nichts mehr mit AVR gemacht, aber wie siehts> eigentlich mit AVR-Support in LLVM aus, ist da was absehbar?
War mal im Gespräch, aber aktuell eher nichts ...
Wilhelm M. schrieb:> vn nn schrieb:>> Wilhelm M. schrieb:>>> Da es ja bspw. für die kleinen AVR 8-Bitter keine stdlibc++ gibt>>>> Ich hab ja schon lange nichts mehr mit AVR gemacht, aber wie siehts>> eigentlich mit AVR-Support in LLVM aus, ist da was absehbar?>> War mal im Gespräch, aber aktuell eher nichts ...
Wenn man Zugriff auf EDG hat, kann man C++ -> EDG -> C -> C-Compiler
machen, wobei der sdcc ja AVR auch nicht unterstützt. Aber so konnte ich
meinen Z80 schonmal bestücken ;-)
Wilhelm M. schrieb:> Wilhelm M. schrieb:>> vn nn schrieb:>>> Wilhelm M. schrieb:>>>> Da es ja bspw. für die kleinen AVR 8-Bitter keine stdlibc++ gibt>>>>>> Ich hab ja schon lange nichts mehr mit AVR gemacht, aber wie siehts>>> eigentlich mit AVR-Support in LLVM aus, ist da was absehbar?>>>> War mal im Gespräch, aber aktuell eher nichts ...>> Wenn man Zugriff auf EDG hat, kann man C++ -> EDG -> C -> /C-Compiler/> machen, wobei der sdcc ja AVR auch nicht unterstützt. Aber so konnte ich> meinen Z80 schonmal bestücken ;-)
Ohne EDG ginge noch http://www.colecovision.eu/llvm+sdcc/, aber das ist
noch experimentall.
Vincent H. schrieb:> vn nn schrieb:>> Wie stellst du dir vor, dass das Funktionieren soll? Damit würde man>> sich jede Menge neuer Probleme aufreissen, für eine Standardbibliothek>> völlig ungeeignet...>> So zum Beispiel:> using uint8 = std::numeric_limits<uint8_t>;> using uint16 = std::numeric_limits<uint16_t>;> using uint32 = std::numeric_limits<uint32_t>;>> template<uint64_t Max, typename = std::enable_if_t<Max >= 0u>>> using smallest_unsigned_t = std::conditional_t<> Max <= uint8::max(),> uint8_t,> std::conditional_t<> Max <= uint16::max(),> uint16_t,> std::conditional_t<Max <= uint32::max(), uint32_t, uint64_t>>>;>> Welche Probleme sollen das sein?> size_type bleibt natürlich weiterhin size_t, nur wozu soll ein Container> mit weniger als 256 Elementen dessen Größe in einem size_t speichern?
Natürlich ist es machbar, mag auch durchaus sinnvoll sein. Als
allgemeines Verhalten in einer Standardbibliothek allerdings ungeeignet,
da ist es wesentlich sinnvoller, wenn standardmäßig einfach ein size_t
zurückkommt.
Man kann von der STL-Implementierung ja leicht eine eigene ableiten, und
diese auf die eigenen Bedürfnisse zuschneiden, ohne sie komplett per
Hand stricken zu müssen wie in C.
size_t oder so ein Verhalten ist ja auch keine Spezialität von C++, ist
ja auch in C so, dass für Speichergrößen standardmäßig mal size_t
verwendet wird, auch wenn in konkreten Anwendungen weniger reichen
würde.
Viel mehr noch, in C wäre derartige Template-Zauberei nicht mal möglich.
Lustig, wie hier C++ Dinge angekreidet werden, die in C genau so oder
ähnlich sind, oder dass Dinge nicht zu 100% auf embedded getrimmt sind,
die in C nicht mal verfügbar sind und sowieso erst per Hand
implementiert werden müssen.
Ja klar ist std::list nicht Embedded-optimiert, aber gegenüber C, wo ich
die komplette Implementierung per Hand erledigen muss, hab ich immer
noch einen Vorteil.
vn nn schrieb:> Natürlich ist es machbar, mag auch durchaus sinnvoll sein. Als> allgemeines Verhalten in einer Standardbibliothek allerdings ungeeignet,> da ist es wesentlich sinnvoller, wenn standardmäßig einfach ein size_t> zurückkommt.
Nein, bei einem std::array<> wäre es m.E. in der Tat sinnvoller, man
würde den Typ bspw. von size() adaptiv gestalten. Egal, welchen unsinged
Typ man dort dann nimmt, er ist in jedem Fall kleiner als size_t, und
damit wieder zuweisungskompatibel.
M.E. ist die starre Festlegung von array<>::size() auf size_t ein
design-flaw. Aber man kann auch anderer Meinung sein aus Gründen der
Kongruenz zu sizeof(). Außerdem hätte man sich dann auch den nested
typ-alias size_type sparen können, wenn Größenangeben immer size_t
sind. Aus Rückwärtskompatibilitätsgründen wird daran aber (im Moment)
nichts geändert. Derartige Ungereimtheiten findet man auch an anderen
Stellen.
vn nn schrieb:> Lustig, wie hier C++ Dinge angekreidet werden, die in C genau so oder> ähnlich sind, oder dass Dinge nicht zu 100% auf embedded getrimmt sind,> die in C nicht mal verfügbar sind und sowieso erst per Hand> implementiert werden müssen.
Oh, Du bist noch nicht lange in diesem Form, oder?
Wilhelm M. schrieb:> Außerdem hätte man sich dann auch den nested> typ-alias size_type sparen können, wenn Größenangeben immer size_t> sind.
Ist der size_type nicht notwendig, weil std::array ein Container ist?
Ich hab grad nicht in den Standard geguckt, aber cppreference sagt, dass
es eine named requirement "Container" gibt mit size_type als
requirement.
Wilhelm M. schrieb:> vn nn schrieb:>> Lustig, wie hier C++ Dinge angekreidet werden, die in C genau so oder>> ähnlich sind, oder dass Dinge nicht zu 100% auf embedded getrimmt sind,>> die in C nicht mal verfügbar sind und sowieso erst per Hand>> implementiert werden müssen.>> Oh, Du bist noch nicht lange in diesem Form, oder?
LOL stimmt, optionale Features, welche in einem bestimmten
Anwendungsfall suboptimal sind (oder aus irgendwelchen Gründen auch
immer abgelehnt werden), sind in diesem Forum ein handfester Nachteil.
Das letzte Mal trat dieser Fall bei Rust mit Cargo zu, aber regelmäßig
bei C++ wie auch hier.
mh schrieb:> Wilhelm M. schrieb:>> Außerdem hätte man sich dann auch den nested>> typ-alias size_type sparen können, wenn Größenangeben immer size_t>> sind.>> Ist der size_type nicht notwendig, weil std::array ein Container ist?> Ich hab grad nicht in den Standard geguckt, aber cppreference sagt, dass> es eine named requirement "Container" gibt mit size_type als> requirement.
Naja, wenn alle(!) Container ihn zu size_t deklarieren, braucht man die
Deklaration strenggenommen ja nicht (unabhängig davon, ob andere
Metafunktionen das benutzen). Hier war m.E. schon die Absicht, das
adaptiv gestalten zu können, indem bspw. size_type bei statischen
Containern abhängig von der Größe deklariert wird. Hat man aber - aus
für mich nicht ganz schlüssigen Gründen - nicht gemacht.
Natürlich kann man auch eine Meta-Funktion etwa std:size_type_t<...>
einführen, auch als customization-point, und die spezialisieren.
Trotzdem wäre es anders m.E. besser.
Wilhelm M. schrieb:> M.E. ist die starre Festlegung von array<>::size() auf size_t ein> design-flaw. Aber man kann auch anderer Meinung sein aus Gründen der> Kongruenz zu sizeof(). Außerdem hätte man sich dann auch den nested> typ-alias size_type sparen können, wenn Größenangeben immer size_t> sind. Aus Rückwärtskompatibilitätsgründen wird daran aber (im Moment)> nichts geändert. Derartige Ungereimtheiten findet man auch an anderen> Stellen.
Vermutlich sind die historischen Gründe wie so oft in C oder C++ die
ausschlaggebenden. Dinge die schon immer so waren, oder die man
einheitlich mit anderen Dingen gestaltet hat, die wiederum immer schon
so waren, sind dann meistens schwer zu ändern.
Hätten die einzelnen Container untereinander unterschiedliche
Verhaltensweisen, würde sicher wieder wer jammern. Würde sich das
Verhalten von Containern von sizeof() oder anderen Funktionen, die
größen zurückgeben, unterscheiden, würde wahrscheinlich auch gejammert.
Würde das Verhalten von std::array im nächsten Standard geändert, würde
man sicher auch jammern.
Ein Grund zum jammern findet sich ja immer. Einerseits wird gejammert,
dass C++ zu umfangreich wird und sich keiner mehr auskennt, andererseits
wird gejammert, dass Spezialfälle wie dynamische Container mit
statischer Maximalgröße nicht in der Standardlibrary enthalten sind.
Wilhelm M. schrieb:> Hier war m.E. schon die Absicht, das> adaptiv gestalten zu können, indem bspw. size_type bei statischen> Containern abhängig von der Größe deklariert wird.
Ich vermute, dass sie erlauben wollten, dass std::vector und std::map
unterschiedliche size_type haben können. Aktuell ist std::array der
einzige Container, bei dem deine Idee nutzbar wäre(, wenn
array::size_type nicht fix wäre)?
vn nn schrieb:> Dynamische Container machen bei so wenig RAM ohnehin keinen Sinn.
Globale statische Container stehen immer zu x% leer.
Ein einfacher Use-Case, von dem ich halbwegs überzeugt bin:
1
void INThandlerX() {
2
queueSomeMessage();
3
}
4
5
main() {
6
while(1) processMessageQueue();
7
}
Was soll die Obergrenze an Messages da sein? Eine artifizielle
Beschränkung der maximal auflaufenden Nachrichten schadet nur der
Allgemeinheit des Programentwurfs.
vn nn schrieb:> size_t oder so ein Verhalten ist ja auch keine Spezialität von C++, ist> ja auch in C so, dass für Speichergrößen standardmäßig mal size_t> verwendet wird, auch wenn in konkreten Anwendungen weniger reichen> würde.
Ja, nee. Der Punkt ist genau, dass die C-Definition von size_t die von
C++ in der Praxis ungünstig festlegt. Allerdings möchte ich mir DAS
Chaos, wenn man mal in der STL std::size_t mit size_t inkompatibel
definiert, lieber bei jemand anderem anschauen. Ist beides mal der Typ,
den sizeof() zurückgibt. Das gibt bestimmt ein paar lustige
Makro-Effekte. Je nach Front-End und dann mit Text-Ersetzung, mal dies
mal jenes...
Und dann einfach mal Gentoo mit KDE durchbauen lassen.
vn nn schrieb:> Ja klar ist std::list nicht Embedded-optimiert, aber gegenüber C, wo ich> die komplette Implementierung per Hand erledigen muss, hab ich immer> noch einen Vorteil.vn nn schrieb:> Man kann von der STL-Implementierung ja leicht eine eigene ableiten, und> diese auf die eigenen Bedürfnisse zuschneiden, ohne sie komplett per> Hand stricken zu müssen wie in C.
Ich fürchte, dass genau das eben nicht geht. Da müsste man schon den
Code komplett duplizieren und - "leicht" würde die Anpassung eher nicht
werden, wenn ich mir so einen typischen STL-Quelltext anschaue.
Andererseits ist so eine einfache "Buffer"-Klasse schnell eben
hingeschrieben. "T*, malloc, free, begin(), end() - fertig?"
Wilhelm M. schrieb:> Hat man aber - aus> für mich nicht ganz schlüssigen Gründen - nicht gemacht.
Ich könnte mir vorstellen, dass zu viel Varianz in den std-Klassen wohl
dazu führt, dass noch viel mehr als aktuell nur noch header-only
implementiert werden kann. Es ist zwar suboptimal Container(-Referenzen)
an Funktionen zu übergeben, aber so hat man wenigstens etwas, was nicht
an 2000-Stellen jedesmal neu übersetzt werden muss und die
Implementierung mit allen Details die Schnittstelle bildet.
Heiko L. schrieb:> Globale statische Container stehen immer zu x% leer.
Bei µC sagt man gerne: für unbenutztes RAM bekommt man kein Geld zurück.
Wenn Du verstehst was ich meine. Natürlich haben wir auch bei OS-support
eine Obergrenze.
Heiko L. schrieb:> Ich könnte mir vorstellen, dass zu viel Varianz in den std-Klassen wohl> dazu führt, dass noch viel mehr als aktuell nur noch header-only> implementiert werden kann.
Nein, das hat ja nichts miteinander zu tun. Außerdem hat header-only
viele Vorteile.
> Es ist zwar suboptimal Container(-Referenzen)> an Funktionen zu übergeben,
Was meinst Du denn da mit? Was ist an pass-by-const-ref suboptimal?
> aber so hat man wenigstens etwas, was nicht> an 2000-Stellen jedesmal neu übersetzt werden muss und die> Implementierung mit allen Details die Schnittstelle bildet.
Da werden modules helfen.
Wilhelm M. schrieb:> Was ist an pass-by-const-ref suboptimal?
Man sollte Iteratoren übernehmen, um die Verwendung nicht
einzuschränken.
Wilhelm M. schrieb:> Da werden modules helfen.
Teilweise. Einfach nur eine shared lib im System austauschen geht mit
templates halt konzeptionell nicht.
Aber wenn man sowieso immer alles neu baut, was man ausliefert, sollten
die natürlich schon einiges bringen.
Wilhelm M. schrieb:> Heiko L. schrieb:>> Man sollte Iteratoren übernehmen, um die Verwendung nicht>> einzuschränken.
Ich verstehe den Satz einfach nicht. Für mich ist das sinnfrei.
Vielleicht kannst Du es mir "übersetzen"?
Man sollte aus Gründen der Flexibilität bevorzugen, seine Funktionen so
zu schreiben, dass sie nicht eine Referenz auf den Container als
Parameter wollen, sondern ein Iterator-Paar, eben so wie es die ganzen
Standard-Algorithmen auch tun.
Rolf M. schrieb:> Man sollte aus Gründen der Flexibilität bevorzugen, seine Funktionen so> zu schreiben, dass sie nicht eine Referenz auf den Container als> Parameter wollen, sondern ein Iterator-Paar, eben so wie es die ganzen> Standard-Algorithmen auch tun.
Das kann ich aus dem ursprünglichen Satz wirklich nicht entnehmen, es
hat mit dem eigentlichen Problem rein gar nichts zu tun, und liegt in
der Natur der Sache. Summa summarum: völlig sinnfrei.
Wilhelm M. schrieb:> Summa summarum: völlig sinnfrei.
Na Moment mal, du hattest doch gefragt, warum man nicht Containter per
Referenz an Funktionen übergeben soll:
Wilhelm M. schrieb:>> Es ist zwar suboptimal Container(-Referenzen)>> an Funktionen zu übergeben,>> Was meinst Du denn da mit? Was ist an pass-by-const-ref suboptimal?
Das war die Antwort darauf, und jetzt beschwerst du dich dann, das das
nichts mit dem Thema zu tun hat…
Rolf M. schrieb:> Wilhelm M. schrieb:>> Summa summarum: völlig sinnfrei.>> Na Moment mal, du hattest doch gefragt, warum man nicht Containter per> Referenz an Funktionen übergeben soll:
Genau.
> Heiko L. schrieb:>> Man sollte Iteratoren übernehmen, um die Verwendung nicht>> einzuschränken.
Und das soll die Antwort sein? Der Satz ist doch vollkommen sinnfrei.
Rolf M. schrieb:> Das war die Antwort darauf, und jetzt beschwerst du dich dann, das das> nichts mit dem Thema zu tun hat…
Ich beschwere mich gar nicht.
Ich pflege nur den hier üblichen Umgangston, sollte ich mich mal
beschweren, dann hört sich das anders an.
vn nn schrieb:> Oh, tatsächlich. Hoppala, mein Fehler. Na immerhin ist scheinbar nicht> nur "irgendein Depp bei Apple" dafür, um mal bei x^2's Wortlaut zu> bleiben.
Ich habe "Hanswurst" gesagt, nicht "Depp". Bitte zitiere mich nicht auch
noch falsch. Der Rest deiner Argumente besteht meist ebenfalls darin
meine Aussagen absichtlich falsch zu replizieren und diesen Strohmann
dann lustvoll zu bekämpfen. Mir ist sowas wirklich zu anstrengend und
unseriös.
Ich möchte nur bzgl. Standard Wechsel noch etwas hier beitragen und
würde mich dann ausklinken:
Es ist kein Automatismus, dass man Code z.B. für C++11 nicht mehr mit
C++20 nutzen könnte oder umgekehrt. Ob das so ist, darüber entscheiden
die Art der Änderungen, die zwischen den Standards existieren.
Problematisch ist, wenn man Code gar nicht mehr so konstruieren KANN,
dass er für beide Standards funktioniert.
Sobald ich ein C++20 Feature bewußt nutze, kann ich diesen Code
natürlich nicht mehr direkt in C++11 nutzen. Darin besteht nicht das
Problem: Man hat ein Problem wenn man Code schreiben MÖCHTE, der SOWOHL
mit C++11 und C++20 verwendbar sein soll, und das geht nicht mehr mit
vertretbarem Aufwand wegen der Art der Änderungen im neuen Standard.
Das durchbricht die Wiederverwendbarkeit des Codes in BEIDE Richtungen:
Der neue Code funktioniert nicht mehr mit dem alten Standard, und der
alte Code funktioniert nicht mehr mit dem neuem Standard.
(Wenn C++ diesen Weg einschlagen möchte, kann es sich dieses
"Erfolgsrezept" ja bei Python abgucken, wo jedes Stückchen Code für eine
spezifische Version geschrieben werden muss - von denen es unzählige
gibt und die in vielen Details auch noch inkompatibel sind.)
Wir halten unseren Code absichtlich so, dass es keinen Unterschied
macht, ob ein C89, C99 bis C17 Compiler am Werk ist. Dies erreichen wir,
indem wir auf unbedeutende Features bewußt verzichten (die den Code aber
an einen spezifischen Standard koppeln würden) und wichtige neue
Features so kapseln, dass alte Standards alternative Implementierungen
erhalten. Beispielsweise indem das Feature in einem Modul od Klasse
gekapselt und dort per Präprozessor notwendige Unterscheidungen gemacht
werden. Die Motivation ist, dass nicht für jedes Projekt immer der
neuste Standard/Compiler verfügbar ist, man aber Code über möglichst
viele Projekte wiederverwenden muss. Es gibt z.B. weitergepflegte
Uralt-Projekte, deren IDE/Uralt-Compiler läuft nur noch in einer VM, da
sie der Hersteller schon lange aufgegeben hat (und sogar auf neuen
Windows Versionen gar nicht mehr lauffähig wäre). Aber auch diese
Projekte möchten weitergepflegt und mit den aktuelle Versionen unserer
Libraries versorgt werden.
x^2 schrieb:> Wir halten unseren Code absichtlich so, dass es keinen Unterschied> macht, ob ein C89, C99 bis C17 Compiler am Werk ist.
Das ist gut so und in Eurem Fall sicher notwendig.
Allerdings hat das nichts mit dem von Dir auch angeführten
Anpassungsvorschlag zu tun, "volatile" in bestimmten Situation wie etwa
compound-assignments in C++20 als deprecated zu kennzeichnen. Denn:
schon jetzt ist jedes(!) Programm, was volatile benutzt,
implementation-defined, also vom Compiler / Core abhängig.
Das sollte Dir bewusst sein. Du / Ihr müsst also sowieso entsprechende
Vorkehrungen treffen, dort wo ihr volatile benutzt. Die in gcc-10
eingebaute Warnung ist daher extrem hilfreich, die entsprechenden
Stellen zu finden und - wie Du ja auch schreibst - entsprechend zu
handeln. Diesmal aber nicht wegen der Sprachversion aka abstrakte
Maschine, sondern wegen implementation-defined behaviour, was schon
lange in Eurem Code schlummert. Es kommt also nur etwas hinzu, was ihr
hättet eh berücksichtigen müssen.
Also: freut Euch auf gcc-10! (im übrigen ist ja volatile an sich
deprecated (das wäre auch falsch) sondern nur bestimmte, fragwürdige,
nicht vollständig spezifizierte Operationen damit).
zitter_ned_aso schrieb:> Warum kann man aber nicht genauso Variablen in einem Funktionskopf> definieren?> void do_something (int x, y, z, int* p, int another_integer){>> //code>> }>> Ich verstehe schon, dass C das nicht unterstützt. Und darum geht das> nicht. Aber warum hat man das so nicht implementiert?
Die ursprüngliche Syntax vor C89 war sowieso eine ganz andere
(K&R-Stil). Da hat man die Typen dort gar nicht angegeben, sondern erst
danach. Das sah etwa so aus:
1
voiddo_something(x,y,z,p,another_integer)
2
intx,y,z;
3
int*p;
4
intanother_integer;
5
{
6
}
Erst später kam man dann zu der heutigen Syntax, wo das nicht so geht.
Das ist auch ganz gut so, denn in C++ macht man es quasi umgekehrt zu
deiner Idee. Wenn nur ein Name für den Parameter angegeben ist statt
zwei, dann ist das nicht der Name des Parameters, sondern seines Typs.
Ein
1
voiddo_something(intx,y,z)
bedeutet dort also, dass der erste Parameter vom Typ int ist und x
heißt, der zweite vom Typ y und keinen Namen hat und der dritte vom Typ
z und auch namenlos ist.
zitter_ned_aso schrieb:> Warum kann man aber nicht genauso Variablen in einem Funktionskopf> definieren?
Zum Glück kann man das nicht, sonst würden wir wahrscheinlich noch mehr
von solchem "unglücklichen" Code sehen:
1
autodate=Date{1,2,3};// mmh?
Die Parametertypen von mehrstellige Funktionen sollten sich immer
unterscheiden und domänenspezifisch sein: