std :: for_each поверх std :: set, C ++ 11 - PullRequest
7 голосов
/ 15 ноября 2011

Итерации по вектору работают:

std::vector<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});

но не более набора (ошибка компиляции):

std::set<int> collection = {2, 3, 4, 5435345, 2};
std::for_each(collection.begin(), collection.end(), [](int& i){cout << i << endl;});

Почему я не могу перебрать std::set с std::for_each?

Бонусный вопрос: Кроме того, я хотел бы изменить int& в аргументе лямбды на auto&, почему это не может быть автоматически выведено?

Ответы [ 4 ]

19 голосов
/ 15 ноября 2011

std::set<T>::value_type - это T const, а не T;следовательно, аргумент вашей лямбды должен быть типом значения (то есть, копировать) или int const& (и технически, или int const volatile&), а не int&.То есть, это работает:

std::set<int> collection{2, 3, 4, 5435345, 2};
std::for_each(
    collection.begin(),
    collection.end(),
    [](int const& i) { std::cout << i << std::endl; }
);

Бонусный вопрос: Также я хотел бы изменить int& в аргументе лямбды на auto&, почему это не может быть автоматическивыведено?

Потому что стандарт говорит, что не может;исторически, я считаю, что это было связано с чрезмерно сложным взаимодействием между лямбдами и понятиями (до того, как понятия были удалены из проекта). Тем не менее, я слышал слухи о том, что первые сообщения о дефектах в новый стандарт (C ++ 11) будут адресованы именно этому, так что, возможно, вы увидите поддержку этого, добавленную в выбранный вами компилятор, в следующем году илидва. РЕДАКТИРОВАТЬ : О, смотри, в C ++ 14 теперь есть полиморфные лямбды ...

3 голосов
/ 15 ноября 2011

Относительно вопроса о бонусе: аргумент функции "auto" не является специфическим для лямбд.Вы также можете спросить, почему мы не допускаем, чтобы все функции были объявлены как f(auto x, auto y).Но это просто означает, что вы по сути хотите заменить все функции на шаблоны функций.Считалось, что это не очень хорошо работает с существующим языком C ++ и системой типов в частности.Если вам нужен шаблон функции, уже существует синтаксис и механизм, и объявление «автоматических» аргументов - не самый лучший способ.

1 голос
/ 15 ноября 2011

Итератор с разыменованным set<int> является const int&. Так что вы не можете передать его как int& параметр без const. Попробуйте либо просто (int i), либо (const int& i).

И это действительно не то место, которое вам разрешено использовать auto. Я думаю, что auto работает только в объявлении с инициализатором или в качестве заполнителя для конечного типа возврата.

0 голосов
/ 15 ноября 2011

Вы должны иметь возможность перебирать набор. Однако обратите внимание, что, поскольку элемент в наборе является также его ключом, он не может быть изменен. Измените свой код, чтобы взять ссылку const, и используйте вместо нее cbegin/cend, независимо от того, является ли он набором или нет, когда вы не собираетесь изменять элементы.

...