Nie można skompilować:
#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;
}
Błąd kompilatora to: error: assignment of read-only reference 's'
Teraz w moim przypadku lista składa się ze zmiennych składowych w klasie.
Teraz to nie działa, ponieważ wyrażenie staje się initializer_list<int>
tym, które faktycznie kopiuje a, b, c i d - stąd też nie zezwala na modyfikację.
Moje pytanie jest dwojakie:
Czy kryje się za tym jakaś motywacja, by nie pisać w ten sposób pętli bazującej na zakresie? na przykład. być może mógłby istnieć specjalny przypadek nagich wyrazów nawiasów klamrowych.
Jaki jest porządny składni sposób naprawy tego typu pętli?
Preferowane byłoby coś wzdłuż tej linii:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Nie uważam pośrednictwa wskaźnika za dobre rozwiązanie (to znaczy {&a, &b, &c, &d}
) - każde rozwiązanie powinno dawać odwołanie do elementu bezpośrednio, gdy iterator jest usunięty z odniesienia .
źródło
{ &a, &b, &c, &d }
.initializer_list
jest głównie widokiemconst
tablicy.{ &a, &b, &c, &d }
, nie będziesz chciał:for (auto& s : std::initializer_list<std::reference_wrapper<int>>{a, b, c, d}) { s.get() = 1; }
Odpowiedzi:
Zasięg nie jest tak magiczny, jak ludzie by chcieli. Na koniec musi istnieć obiekt, który kompilator może generować wywołania funkcji członkowskiej lub funkcji swobodnej
begin()
iend()
.Najbliżej prawdopodobnie będziesz w stanie przyjść to:
źródło
std::vector<int*>
.auto s
lubauto* s
nieauto& s
.Kolejne rozwiązanie w ramach idei opakowania:
Następnie:
wyjścia
źródło
Zgodnie ze standardowym §11.6.4 Inicjalizacja listy / p5 [dcl.init.list] [ Emphasis Mine ]:
Zatem twój kompilator narzeka zgodnie z prawem (tzn.
auto &s
Odejmujeint const& s
i nie możesz przypisywać dos
w pętli dystansowej dla).Możesz rozwiązać ten problem, wprowadzając kontener zamiast listy inicjalizującej (np. `Std :: vector ') z opcją' std :: reference_wrapper ':
Demo na żywo
źródło
for (auto& s : {a, b, c, d})
nie działa. Co do tego, dlaczego norma ma tę klauzulę ..... trzeba by zapytać członków komitetu normalizacyjnego. Podobnie jak wiele takich rzeczy, rozumowanie może być cokolwiek pomiędzy: „Nie uważaliśmy, że Twój konkretny przypadek był wystarczająco użyteczny, aby zawracać sobie głowę” aż do „Zbyt wiele innych części standardu musiałoby się zmienić, aby poprzeć twoją sprawę, i odłożyliśmy rozpatrzenie tego wszystkiego, dopóki nie opracujemy przyszłego standardu ”.std::array<std::reference_wrapper>>
?Aby spełnić tę składnię
możesz utworzyć opakowanie:
Próbny
źródło
std::reference_wrapper
?std::reference_wrapper
wymagałobys.get() = 1;
.Rozwiązanie: użyj opakowania referencyjnego
Następnie używany jako:
Nie próbuje to jednak odpowiedzieć na pierwsze pytanie.
źródło
Możesz utworzyć klasę opakowania do przechowywania referencji, która będzie miała operatora przypisania do aktualizacji tej wartości:
Demo na żywo
źródło