Folgendes wird nicht kompiliert:
#include <iostream>
int main()
{
int a{},b{},c{},d{};
for (auto& s : {a, b, c, d}) {
s = 1;
}
std::cout << a << std::endl;
return 0;
}
Compilerfehler ist: error: assignment of read-only reference 's'
In meinem aktuellen Fall besteht die Liste nun aus Mitgliedsvariablen einer Klasse.
Dies funktioniert jetzt nicht, da der Ausdruck zu einem wird initializer_list<int>
, der tatsächlich a, b, c und d kopiert - und daher auch keine Änderung zulässt.
Meine Frage ist zweifach:
Gibt es eine Motivation, auf diese Weise keine bereichsbasierte for-Schleife schreiben zu dürfen? z.B. Vielleicht könnte es einen Sonderfall für nackte Zahnspangen geben.
Was ist eine syntaktisch saubere Methode, um diese Art von Schleife zu reparieren?
Etwas in dieser Richtung wäre vorzuziehen:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Ich halte Zeiger-Indirektion nicht für eine gute Lösung (das heißt {&a, &b, &c, &d}
) - jede Lösung sollte die Elementreferenz direkt angeben, wenn der Iterator de-referenziert wird .
quelle
{ &a, &b, &c, &d }
.initializer_list
ist meistens eine Ansicht aufconst
Array.{ &a, &b, &c, &d }
, wollen Sie auch nicht:for (auto& s : std::initializer_list<std::reference_wrapper<int>>{a, b, c, d}) { s.get() = 1; }
Antworten:
Bereiche sind nicht so magisch, wie die Leute es gerne hätten. Am Ende muss es ein Objekt geben, mit dem der Compiler entweder eine Mitgliedsfunktion oder eine freie Funktion
begin()
und aufrufen kannend()
.Am nächsten kommen Sie wahrscheinlich:
quelle
std::vector<int*>
.auto s
oderauto* s
nichtauto& s
.Nur eine weitere Lösung innerhalb einer Wrapper-Idee:
Dann:
Ausgänge
quelle
Gemäß dem Standard §11.6.4 Listeninitialisierung / p5 [dcl.init.list] [ Emphasis Mine ]:
Daher beschwert sich Ihr Compiler zu Recht (dh
auto &s
zieht abint const& s
und Sie können nichts
in der for-Schleife für den Bereich zuweisen ).Sie können dieses Problem beheben, indem Sie einen Container anstelle einer Initialisiererliste (z. B. "std :: vector") mit "std :: reference_wrapper" einführen:
Live-Demo
quelle
for (auto& s : {a, b, c, d})
nicht funktioniert. Warum der Standard diese Klausel enthält ..... Sie müssten die Mitglieder des Standardisierungsausschusses fragen. Wie bei vielen solchen Dingen könnte die Argumentation zwischen "Wir haben Ihren speziellen Fall nicht als nützlich genug angesehen, um uns darum zu kümmern" und "Zu viele andere Teile des Standards müssten geändert werden, um Ihren Fall zu unterstützen, und wir haben die Prüfung verschoben." von all dem, bis wir einen zukünftigen Standard entwickeln ".std::array<std::reference_wrapper>>
?Um diese Syntax zu erfüllen
Sie könnten einen Wrapper erstellen:
Demo
quelle
std::reference_wrapper
?std::reference_wrapper
würde erforderns.get() = 1;
.Lösung: Verwenden Sie einen Referenz-Wrapper
Dann verwendet als:
Dies versucht jedoch nicht, die erste Frage zu beantworten.
quelle
Sie können eine Wrapper-Klasse zum Speichern von Referenzen erstellen, die über einen Zuweisungsoperator verfügt, um diesen Wert zu aktualisieren:
Live-Demo
quelle