Verfall des statischen Schlüsselworts… nicht mehr?

87

In C ++ ist es möglich, das staticSchlüsselwort innerhalb einer Übersetzungseinheit zu verwenden, um die Sichtbarkeit eines Symbols (entweder Variablen- oder Funktionsdeklaration) zu beeinflussen.

In n3092 war dies veraltet:

Anhang D.2 [depl.static]
Die Verwendung des statischen Schlüsselworts ist veraltet, wenn Objekte im Namespace-Bereich deklariert werden (siehe 3.3.6).

In n3225 wurde dies entfernt.

Der einzige Artikel, den ich finden konnte, ist etwas informell.

Es wird jedoch unterstrichen, dass aus Gründen der Kompatibilität mit C (und der Fähigkeit, C-Programme als C ++ zu kompilieren) die Ablehnung ärgerlich ist. Das direkte Kompilieren eines C-Programms als C ++ kann jedoch bereits eine frustrierende Erfahrung sein, daher bin ich mir nicht sicher, ob dies eine Überlegung erfordert.

Weiß jemand, warum es geändert wurde?

Matthieu M.
quelle
3
Sie deklarieren Objekte im Namespace-Bereich in C?
Etienne de Martel
heh, thx, fand heraus, wo man es bekommen kann. Versucht, einen Kommentar zu löschen, aber du hast mich dort geschlagen.
Edward Strange
Frage entstand von stackoverflow.com/questions/4725204/…
Fred Nurk
1
Dies gibt dem C ++ - Komitee auch die Möglichkeit, in der nächsten Version des Standards etwas zu unterschätzen :-)
James McNellis

Antworten:

74

In C ++ Standard Core Language-Fehlerberichten und akzeptierten Problemen, Revision 94 unter 1012. Nicht veraltete statische `sie beachten:

Obwohl 7.3.1.1 [namespace.unnamed] besagt, dass die Verwendung des statischen Schlüsselworts zum Deklarieren von Variablen im Namespace-Bereich veraltet ist, da der unbenannte Namespace eine überlegene Alternative darstellt, ist es unwahrscheinlich, dass die Funktion in absehbarer Zukunft zu irgendeinem Zeitpunkt entfernt wird .

Grundsätzlich zu sagen, dass die Abwertung von staticnicht wirklich Sinn macht. Es wird niemals aus C ++ entfernt und ist dennoch nützlich, da Sie nicht den Boilerplate-Code benötigen, den Sie für unbenannte Namespaces benötigen, wenn Sie nur eine Funktion oder ein Objekt mit interner Verknüpfung deklarieren möchten.

Johannes Schaub - litb
quelle
2
Nun, es scheint, als würde eine Abwertung die Leute dazu ermutigen, stattdessen unbenannte Namespaces zu verwenden, was eine gute Sache wäre.
sbi
1
@unaperson: Wenn aus keinem anderen Grund, dann, weil unbenannte Namespaces denselben Mechanismus zum Erstellen von Variablen, Konstanten, Funktionen und Typen innerhalb ihrer TU bieten. static class ... , OTOH, wird nicht funktionieren.
sbi
2
@nbt: Weil Sie statische Symbole nicht als Vorlagenargumente verwenden können und weil viele Neulinge die Verwendung von Statik einfacher finden und dann nicht versucht sind, <funktional> und <algorithmus> et al. auszuprobieren. Nur ein kurzer Gedanke.
Sebastian Mach
2
"weil Sie nicht den Boilerplate-Code benötigen, den Sie für unbenannte Namespaces benötigen"? Welcher "Boilerplate-Code"? Etwas jenseits von " namespace {" und " }"?
Towi
1
@ErikAronesty Wenn Sie eine "lokale Klasse" in einer anderen Datei mit demselben Namen haben, begehen Sie eine ODR-Verletzung.
LF
32

Ich werde versuchen , Ihre Frage zu beantworten, obwohl es sich um eine alte Frage ist, und es sieht nicht sehr wichtig (es ist wirklich nicht sehr wichtig , in sich selbst ), und es hat schon recht gute Antworten erhalten. Der Grund, warum ich darauf antworten möchte, ist, dass es sich um grundlegende Fragen der Standardentwicklung und des Sprachdesigns handelt, wenn die Sprache auf einer vorhandenen Sprache basiert: Wann sollten Sprachfunktionen auf inkompatible Weise veraltet, entfernt oder geändert werden?

In C ++ ist es möglich, das statische Schlüsselwort innerhalb einer Übersetzungseinheit zu verwenden, um die Sichtbarkeit eines Symbols (entweder Variablen- oder Funktionsdeklaration) zu beeinflussen.

Die Verknüpfung eigentlich.

In n3092 war dies veraltet:

Die Abschreibung zeigt an:

  • Die Absicht , einige Funktionen in Zukunft zu entfernen; Dies bedeutet nicht, dass veraltete Features in der nächsten Standardrevision entfernt werden oder dass sie "bald" oder überhaupt entfernt werden müssen. Nicht veraltete Funktionen können in der nächsten Standardversion entfernt werden.
  • Ein formeller Versuch, von seiner Verwendung abzuraten .

Letzterer Punkt ist wichtig. Obwohl es nie ein formelles Versprechen gibt, dass Ihr Programm nach dem nächsten Standard nicht manchmal stillschweigend gebrochen wird, sollte das Komitee versuchen, zu vermeiden, dass "vernünftiger" Code gebrochen wird. Die Ablehnung sollte Programmierern mitteilen, dass es nicht zumutbar ist, sich auf eine Funktion zu verlassen .

Es wird jedoch unterstrichen, dass aus Gründen der Kompatibilität mit C (und der Fähigkeit, C-Programme als C ++ zu kompilieren) die Ablehnung ärgerlich ist. Das direkte Kompilieren eines C-Programms als C ++ kann jedoch bereits eine frustrierende Erfahrung sein, daher bin ich mir nicht sicher, ob dies eine Überlegung erfordert.

Insbesondere für Header-Dateien ist es sehr wichtig, eine gemeinsame C / C ++ - Teilmenge beizubehalten. staticGlobale Deklarationen sind natürlich Symboldeklarationen mit interner Verknüpfung, was in einer Header-Datei nicht sehr nützlich ist.

Das Problem ist jedoch nie nur die Kompatibilität mit C, sondern auch die Kompatibilität mit vorhandenem C ++: Es gibt Unmengen vorhandener gültiger C ++ - Programme, die staticglobale Deklarationen verwenden. Dieser Code ist nicht nur formal legal, er ist auch solide, da er eine genau definierte Sprachfunktion verwendet , wie sie verwendet werden soll .

Nur weil es jetzt (nach Ansicht einiger) einen "besseren Weg" gibt, etwas zu tun, werden die auf die alte Weise geschriebenen Programme nicht "schlecht" oder "unvernünftig". Die Fähigkeit, das staticSchlüsselwort für Deklarationen von Objekten und Funktionen im globalen Bereich zu verwenden, ist sowohl in C- als auch in C ++ - Communitys gut bekannt und wird am häufigsten korrekt verwendet.

In ähnlicher Weise, ich werde ändern C-Casts nicht doubleauf , static_cast<double>nur weil „C-Casts sind schlecht“, so static_cast<double>fügen Null Information und null Sicherheit.

Die Idee, dass alle Programmierer sich beeilen würden, ihren vorhandenen, genau definierten Arbeitscode neu zu schreiben, wenn eine neue Art erfunden wird, etwas zu tun, ist einfach verrückt. Wenn Sie alle ererbten Probleme und Probleme beseitigen möchten, ändern Sie C ++ nicht, sondern erfinden eine neue Programmiersprache. Das halbe Entfernen einer Verwendung von staticmacht C ++ kaum weniger C-hässlich.

Codeänderungen müssen begründet werden, und "alt ist schlecht" ist niemals eine Rechtfertigung für Codeänderungen.

Brechende Sprachänderungen bedürfen einer sehr starken Begründung. Die Sprache etwas einfacher zu machen, ist niemals eine Rechtfertigung für eine bahnbrechende Veränderung.

Die Gründe, warum dies staticschlecht ist, sind nur bemerkenswert schwach, und es ist nicht einmal klar, warum nicht sowohl Objekte als auch Funktionsdeklarationen zusammen veraltet sind. Eine unterschiedliche Behandlung macht C ++ kaum einfacher oder orthogonaler.

Es ist also wirklich eine traurige Geschichte. Nicht wegen der praktischen Konsequenzen, die es hatte: Es hatte genau null praktische Konsequenzen. Aber weil es einen klaren Mangel an gesundem Menschenverstand seitens des ISO-Komitees zeigt.

Neugieriger
quelle
5
Wie Sie selbst betonen, besteht der Grund für die Ablehnung darin, die Verwendung zu unterbinden. Sie machen jedoch kein Argument dafür, dass es falsch ist, von seiner Verwendung abzuraten. Ich hoffe auf jeden Fall, dass niemand da draußen Leute dazu ermutigt, statische Deklarationen mit Namespace-Gültigkeitsbereich über anonyme Namespaces zu verwenden. Nicht, wenn sie nicht speziell C.
Nicol Bolas
2
Ich interessiere mich nicht so sehr für Leute, die globalen Bereich staticoder anonyme Namespaces verwenden, ich ermutige oder entmutige auch nicht. Mein Punkt ist, dass, wenn Sie Leute wirklich davon abhalten wollen, anonyme Namespaces zu verwenden, Sie ihnen gute Argumente geben müssen. In der Praxis glaube ich, dass in den meisten Implementierungen Entitäten, die in einem unbenannten Namespace deklariert sind, Symbole sind, die mit einem zufälligen Namen exportiert werden, wodurch die Exporttabelle vergrößert wird. Als staticOTOH deklarierte Unternehmen werden in keiner Weise exportiert. Daher entscheiden sich viele Menschen aufgrund dieser Beobachtung für die Verwendung static.
Neugieriger
2
Wie Sie selbst betonen, besteht der Grund, es zu missbilligen, darin, von seiner Verwendung abzuraten . “ Der Grund, von seiner Verwendung abzuraten, besteht darin, dass es eines Tages verschwinden könnte. Mein Punkt ist, dass der Namespace-Bereich staticniemals verschwinden wird, daher ist es falsch, ihn zu verwerfen. " Sie machen jedoch kein Argument dafür, dass es falsch ist, von seiner Verwendung abzuraten. " Ich habe kein überzeugendes Argument gesehen, das zeigt, dass die Verwendung des Namespace-Bereichs static"falsch" ist. Es zu verachten, nur um von seiner Verwendung abzuraten, ist falsch, weil niemand wirklich glaubt, dass es verschwinden wird, und weil es die Leute nicht davon überzeugt, dass es "falsch" ist.
Neugieriger
5
Die ganze Sprache wird "eines Tages verschwinden". Lassen Sie uns C ++ ablehnen.
Leichtigkeitsrennen im Orbit
2
"In ähnlicher Weise werde ich C-artige Casts nicht in" static_cast <double> "ändern, nur weil" C-style-Casts schlecht sind ", da static_cast <double> null Informationen und null Sicherheit hinzufügt." Mein ewiger Kampf mit vielen Software-Ingenieuren, die sich immer wieder über meine freizügige Verwendung von Casts im C-Stil von einem Grundelement zum anderen beschweren.
Makogan
14

Veraltet oder nicht, das Entfernen dieser Sprachfunktion würde vorhandene Codes beschädigen und Menschen ärgern.

Die ganze Sache mit der statischen Abwertung war nur Wunschdenken im Sinne von "anonyme Namespaces sind besser als statische" und "Referenzen sind bessere Zeiger". Lol.

Maxim Egorushkin
quelle
1
"Referenzen sind bessere Hinweise"? Nein, intelligente Zeiger sind intelligentere Zeiger. Sie können keine Referenzen für den vom Heap, Err, Free Store zugewiesenen Speicher verwenden.
Dan Breslau
3
Entschuldigung, ich habe vergessen, es mit einem ironischen Smiley zu beenden.
Maxim Egorushkin
2
@ Dan: Genau das sagt diese Antwort: "Wunschdenken" entlang einer ähnlichen fehlerhaften Denkrichtung. Unbenannte Namespaces sind ein wichtiges Merkmal, genau wie Global-Scope-Static, wenn auch aus leicht unterschiedlichen Gründen, und obwohl sie sich in ihrer Anwendbarkeit teilweise überschneiden.
Fred Nurk
@Fred, @Maxim: Entschuldigung, wenn ich falsch verstanden habe oder wenn mein Gedächtnis fehlerhaft ist. Aber ich kategorisiere "Referenzen sind bessere Zeiger" nicht als äquivalent zu "anonyme Namespaces sind besser als statische" als Fall von Wunschdenken. Ich bin mir des Versuchs bewusst, letzteres zum Stehen zu bringen, aber ich erinnere mich nicht, dass jemand einen ernsthaften Vorschlag gemacht hat, Zeiger durch Referenzen zu ersetzen. Auch hier fehlt vielleicht mein eigenes Bewusstsein.
Dan Breslau
1
@DanBreslau: char* foo = new char; char& ref = *foo;Nur weil Sie einen Zeiger erhalten, sagt dies zunächst nichts über Ihre Fähigkeit aus, Referenzen zu verwenden.
Leichtigkeitsrennen im Orbit