std :: transform с использованием лямбда-выражения C ++ 0x - PullRequest
29 голосов
/ 07 октября 2010

Как это делается в C ++ 0x?

std::vector<double> myv1;
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
               std::bind1st(std::multiplies<double>(),3));

Оригинальный вопрос и решение: здесь .

Ответы [ 6 ]

34 голосов
/ 07 октября 2010
std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
   [](double d) -> double { return d * 3; });
28 голосов
/ 08 октября 2010

Основной исходной мотивацией для использования этого функционального стиля для этих случаев в C ++ было «aaagh! Iterator loops!», А C ++ 0x удаляет эту мотивацию с помощью оператора for, основанного на диапазоне.Я знаю, что часть вопроса заключалась в том, чтобы выяснить синтаксис лямбды, но я думаю, что ответ на вопрос «Как это делается в C ++ 0x?»is:

for(double &a : myv1) { a *= 3; }

Там нет реального функционального объекта, но если это поможет, вы можете притвориться, что { a *= 3; } - это очень сокращенная лямбда.Что касается удобства использования, то это в любом случае равносильно тому, что в проекте стандарта определяется диапазон на основе эквивалентного цикла for.

28 голосов
/ 08 октября 2010

Просто сделайте, как говорит Дарио:

for_each(begin(myv1), end(myv1), [](double& a) { a *= 3; });

for_each разрешено изменять элементы, говоря, что это не может быть мифом.

8 голосов
/ 08 октября 2010

Используя изменяемый подход, мы можем использовать for_each для непосредственного обновления элементов последовательности посредством ссылок.

for_each(begin(myv1), end(myv1), [](double& a) { a *= 3; });


Происходят споры о том, действительно ли for_each разрешено изменять элементы, так как это называется "не мутирующим" алгоритмом.

Это означает, что for_each не разрешено изменять последовательность , с которой он работает (это относится к изменениям последовательности структура - т.е. делает итераторы недействительными). Это не означает, что мы не можем модифицировать неконстантные элементы вектора как обычно - сама структура не затрагивается этими операциями.

5 голосов
/ 07 октября 2010

Как это:

vector<double> myv1;
transform(myv1.begin(), myv1.end(), myv1.begin(), [](double v)
{
    return v*3.0;
});
1 голос
/ 23 апреля 2016

Я использую VS2012, который поддерживает адаптер привязки C ++ 11. Чтобы связать первый элемент бинарной функции (как это делает bind1st), вам нужно добавить _1 (аргумент-заполнитель). Нужно включить функционал для привязки.

using namespace std::placeholders;
std::transform( myv1.begin(), myv1.end(), myv1.begin(),
                 std::bind( std::multiplies<double>(),3,_1));
...