Следующее не компилируется:
#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;
}
Ошибка компилятора: error: assignment of read-only reference 's'
Теперь в моем реальном случае список состоит из переменных-членов класса.
Теперь это не работает, потому что выражение становится a, initializer_list<int>
которое на самом деле копирует a, b, c и d - следовательно, также не допускает изменения.
У меня вопрос двоякий:
Есть ли какая-то мотивация за то, что мы не позволяем писать цикл for на основе диапазона таким образом? например. возможно, может быть особый случай для выражений «голые скобки».
Что такое синтаксический аккуратный способ исправления этого типа петли?
Что-то в этом направлении было бы предпочтительным:
for (auto& s : something(a, b, c, d)) {
s = 1;
}
Я не считаю косвенное {&a, &b, &c, &d}
указание хорошим решением (то есть ) - любое решение должно давать ссылку на элемент непосредственно, когда итератор разыменовывается .
источник
{ &a, &b, &c, &d }
.initializer_list
в основном вид наconst
массив.{ &a, &b, &c, &d }
, вы не захотите ни:for (auto& s : std::initializer_list<std::reference_wrapper<int>>{a, b, c, d}) { s.get() = 1; }
Ответы:
Диапазоны не так волшебны, как хотелось бы людям. В конце концов, должен существовать объект, на который компилятор может генерировать вызовы либо функции-члена, либо свободной функции,
begin()
иend()
.Ближайший, вероятно, вы сможете прийти это:
источник
std::vector<int*>
.auto s
илиauto* s
нетauto& s
.Просто еще одно решение в рамках идеи обертки:
Затем:
выходы
источник
Согласно стандарту §11.6.4 List-initialization / p5 [dcl.init.list] [ Выделение шахты ]:
Таким образом, ваш компилятор жалуется на законных основаниях (т.
auto &s
Е. Вычитает,int const& s
а вы не можете назначить егоs
в цикле for).Вы можете решить эту проблему, введя контейнер вместо списка инициализатора (например, `std :: vector ') с помощью' std :: reference_wrapper ':
Live Demo
источник
for (auto& s : {a, b, c, d})
не работаете. Относительно того, почему в стандарте есть такой пункт ... вам нужно спросить членов комитета по стандартизации. Подобно многим таким вещам, аргументация может быть чем-то между: «Мы не посчитали, что ваш конкретный случай был достаточно полезен, чтобы его беспокоить», - «слишком много других частей стандарта пришлось бы изменить, чтобы поддержать ваш случай, и мы отложили рассмотрение всего этого, пока мы не разработаем будущий стандарт ".std::array<std::reference_wrapper>>
?Чтобы удовлетворить этот синтаксис
Вы можете создать обертку:
демонстрация
источник
std::reference_wrapper
?std::reference_wrapper
потребуетсяs.get() = 1;
.Решение: используйте справочную обертку
Затем используется как:
Это не пытается ответить на первый вопрос.
источник
Вы можете создать класс-обертку для хранения ссылки, который будет иметь оператор присваивания для обновления этого значения:
Live демо
источник