Gibt es irgendwelche tricks, die Sie verwenden std::cin zur Initialisierung einer const-variable?
Gemeinsame std::cin Nutzung
int X;
cin >> X;
Der größte Nachteil dieser ist, dass X nicht const
. Es kann sich leicht vorstellen, bugs, und ich bin auf der Suche nach irgendeinem trick, um der Lage sein, erstellen Sie einen const-Wert, und schreiben Sie es nur einmal.
Die naive Lösung
//Naive
int X_temp;
cin >> X_temp;
const int X = X_temp;
Könnte man natürlich verbessern, indem Sie X, um const&
; dennoch sind die original-variable verändert werden können.
Ich bin auf der Suche nach einem kurzen und clevere Lösung, wie dies zu tun. Ich bin sicher, ich bin nicht der einzige, profitieren von einer guten Antwort auf diese Frage.
//EDIT: möchte ich die Lösung einfach erweiterbar auf andere Arten (sagen wir mal, alle PODs, std::string
und beweglich-kopierbar Klassen mit trivialen Konstruktor) (wenn es nicht sinnvoll ist, bitte lassen Sie mich wissen in den Kommentaren).
- ist die variable, die Sie wünschen zu initialisieren einer Klasse?
- Die ersten zwei Zeilen einer Funktion zurückgeben
int
🙂const int X = read_cin();
- nicht unbedingt, Nein.
- Setzen ersten 2 Zeilen deiner Lösung in eine Funktion und zurück
X_temp
. - Ändern
const int
zuconst int&
nicht noch etwas verbessern. Zweite ist fast genau das gleiche wieconst int * const
so werden Sie kopierensizeof(int*)
und inconst int
Sie kopierensizeof(int)
, also wahrscheinlich genau die gleiche Menge an Daten. Mit Verweis aufint
hat keinen Sinn - sollten Sie wahrscheinlich nicht verwenden Referenz auf die leb-en. - Dies erfordert eine Funktion, die für jede Art, die ich Lesen möchte.
- Bitte Lesen Sie den zu Bearbeiten.
- Ich persönlich mag die "naive Lösung", die Sie setzen. Der Wert, den Sie Lesen in der user ist offensichtlich NICHT eine Konstante ist, dann sind Sie ausdrücklich kopieren Sie den Wert in einen anderen Wert was Sie Versprechen wird sich nicht ändern, indem Sie es markieren const. Es ist etwas hässlich, aber scheint genau zu passen, was passiert.
- Ihre "naive" Lösung ist, wie es getan werden sollte. Niemand profitiert von einer riesigen, bombastischen Klasse Schnittstelle für die Durchführung einer so einfachen, banalen Aufgabe. Wenn Sie finden, sich selbst das schreiben lange, komplizierte Funktionen, nur um eine variable zu setzen, das ist ein Sicheres Zeichen sagen, dass etwas gründlich schief gegangen in das Programm-design.
- Aber mit der naiven Weise, ich habe zum erstellen einer temp-variable für jede Art werde ich aus dem stream gelesen:
string TempString; int TempInt;
und so weiter... ich dachte nur, man könnte Kapseln in einer Funktion, so wird es sein, die Unbenannt ist. - erfordert eine Funktion, die für jede Art, die ich Lesen möchte." Machen Sie es eine
read_cin<int>()
dann 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde wahrscheinlich entscheiden Sie sich für die Rückkehr eine
optional
, da die streaming-scheitern könnte. Um zu testen, ob es auch (im Fall, dass Sie wollen, um die Zuweisung eines Wert), verwenden Sieget_value_or(default)
, wie im Beispiel gezeigt.Live-Beispiel.
Weiter sicherzustellen, dass der Benutzer bekommt keine wall-of-überlast angezeigt, wenn
T
ist nicht input-streamable, Sie können schreiben Sie eine Eigenschaft der Klasse, die prüft, obstream >> T_lvalue
gültig ist undstatic_assert
wenn es ' s nicht:Live-Beispiel.
Ich bin mit einem
detail::do_stream
Funktion, da sonsts >> x
würden noch analysiert werden, innerhalbget_stream
und Sie möchten bekommen noch die wall-of-überlastungen, die wir wollten vermeiden, wenn diestatic_assert
feuert. Delegieren Sie diesen Vorgang, um eine andere Funktion macht diese Arbeit.weird
, genauso wie die post ist ein gutes Beispiel füroverkill
🙂const
Objekte? Ich denke nicht, dass das bisschen übertrieben ist.static_assert
? Wenn ja, empfehle ich Ihnen die Fehlermeldung wenn IhrT
macht nicht - support-input-streaming. Ich sehr viel halte, diesen nicht zu viel des guten, aber man könnte vielleicht die Schuld der Implementierung spuckt diese riesige Liste an Erster Stelle... würde ich nicht tun, dass, obwohl, denn hier können Sie entdecken, wenn man nur einen Tippfehler gemacht hat oder etwas anderes, wenn Sie die Implementierung einer überladenen Funktion (man sagt auch warum, die Funktion war SFINAE würde, wenn das passiert).X
hatte ausgefällt 🙂Nutzen Sie lambdas für solche Fälle:
(Beachten Sie die extra () am Ende).
Anstelle des Schreibens einen separaten Funktionen, dies hat den Vorteil, dass Sie nicht herumhüpfen in der Quell-Datei, beim Lesen den code.
Edit: Da in den Kommentaren hieß es, dass dies geht gegen die TROCKENE Regel, Sie könnten sich die Vorteileauto
und5.1.2:4
zu reduzieren, Typ-Wiederholung:5.1.2:4
Staaten:So könnten wir ändern den code wie folgt Aussehen:
ich kann mich nicht entscheiden ob das besser ist, aber, da der Typ nun "versteckt" innerhalb des lambda-body...Edit 2: In den Kommentaren wurde darauf hingewiesen, dass nur das entfernen der name des Typs, wo es möglich ist, nicht in einem "TROCKEN-richtigen" code.
Auch die trailing-return-type-Abzug in diesem Fall ist derzeit tatsächlich eine Erweiterung der MSVC++ sowie g++ und (noch) nicht standard.
()
nur nach der[]
?auto
, aber das würde nur sparen Sie sich eine Wiederholung.{ attribute-specifier-seqopt return expression ;}
.const auto i = extract<int>(std::cin);
nicht, dass Sie das Muster kürzer.Einem leichten zwicken zu lx.'s lambda-Lösung:
Deutlich weniger TROCKEN Verletzung; kann vollständig eliminiert werden, durch ändern
const int x
zuconst auto x
:Einer weiteren Verbesserung; Sie können konvertieren Sie die Kopie in einen Zug, da sonst der Komma-operator unterdrückt die Optimierung in 12,8:31 (Move-Konstruktor unterdrückt durch den Komma-operator):
Beachten Sie, dass dies potenziell noch weniger effizient als die lx.'s lambda, als profitieren können NRVO in der Erwägung, dass dies immer noch ein move-Konstruktor. Auf der anderen Seite eine Optimierung der compiler sollte in der Lage sein, zu optimieren, eine nicht-Nebeneffekt-Lager bewegen.
Können Sie eine Funktion aufrufen, um das Ergebnis zurückzugeben, und initialisieren Sie in der gleichen Anweisung:
Beispiel: http://ideone.com/kFBpT
Wenn Sie C++11, können Sie angeben, den Typ nur einmal, wenn Sie die
auto&&
Stichwort.in_get(T temp = T())
?auto
statt neu-die Angabe der Art.auto&&
überconst auto
?Gehe ich davon aus, das Sie initialisieren möchten, eine globalen variable, da für eine lokale variable, es scheint nur, wie eine sehr ungeschickte Wahl auf drei Linien der einfachen und verständlichen Anweisungen, um eine Konstante von zweifelhaftem Wert.
Auf globaler Ebene, wir können keine Fehler in der Initialisierung, also müssen wir mit Ihnen umgehen irgendwie. Hier sind einige Ideen.
Erste, eine vorgefertigte kleine Bau-Helfer:
Beachten Sie, dass die globalen Initialisierungen dürfen keine Ausnahmen auslösen (unter Schmerzen
std::terminate
), und dass die Eingabe-Vorgang möglicherweise fehl. Alle sagten, es ist wahrscheinlich ziemlich schlecht design zum initialisieren der globalen Variablen aus Benutzereingaben in einer solchen Weise. Vielleicht ein fataler Fehler wäre, die angezeigt werden:Genau zu klären, meine position nach einiger Diskussion in den Kommentaren: In einem lokalen Bereich würde ich nie resort, um solch eine peinliche Krücke. Da wir verarbeiten externen, vom Benutzer gelieferten Daten, wir haben im Grunde zu Leben, scheitern als Teil der normalen Ablaufsteuerung:
Ich lasse es bis zu Ihnen zu entscheiden, ob das ist zu viel zu schreiben oder zu schwer zu Lesen.
-1
durchT()
(das wäre auch besser in derint
version, da-1
ist nur ein spezieller Wert, ohne sinnvolle Bedeutung. Ok,0
ist nicht viel besser, aber zumindest ist es das Ergebnis null/Wert-Initialisierung).std::terminate
); und es gibt keine Anzeichen dafür, dass die OP will Sie initialisieren globals auf diese Weise.operator>>
sowieso.&&
wo ich kann. Zeigen Sie?std::exit
ist in der Tat viel besser als einstd::terminate
von einer "uncaught exception".Sicher, dass Sie tun können dieses nur den Bau einer temporären
istream_iterator
. Zum Beispiel:Es ist erwähnenswert, hier, dass Sie ' re Verzicht auf alle Hoffnung auf Fehler überprüfen, wenn Sie dies tun. Die in der Regel in der Einnahme von Eingaben von einem Benutzer würden nicht als die Klügste... aber hey, vielleicht haben Sie kuratierte diese Eingabe irgendwie?
Live Beispiel
istringstream
s undifstream
s, die ich kontrollieren kann. Aber... ja ich weiß nich es scheint, wie die naheliegendste Antwort?