Как использовать локальные переменные C ++ 0x lambdas для std :: fill ()? - PullRequest
4 голосов
/ 10 июля 2011

Итак, я пытался проверить лямбду, обращающуюся к локальным переменным в той области, в которой он используется, примерно на простом примере Бьярне на странице часто задаваемых вопросов по C ++ 0x по адресу: http://www2.research.att.com/~bs/C++0xFAQ.html#lambda

Когда я попробую этот простой тестовый код:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

//Test std::fill() with C++0x lambda and local var
void f (int v) { 
    vector<int> indices(v);
    int count = 0;
    fill(indices.begin(), indices.end(), [&count]() {
        return ++count;
    });

    //output test indices
    for (auto x : indices) {
        cout << x << endl;
    }
}

int main() {
    f(50);
}

Я получаю ошибку:

required from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, _Tp = f(int)::<lambda()>]'

Я предполагаю, что это errmsg указывает на то, что для подписи std :: fill () требуется const Type & для использования в новом назначении элемента значения.

Но если я смогу использовать fill () для этой цели, как указано в примере Бьярне, мне не нужно будет использовать ссылку '[& count]' внутри предложения лямбда-захвата, чтобы иметь возможность переназначить исходное значение элемента индексов с увеличивающимся счетчиком var через 'return ++ count;' Блок лямбда-операторов?

Признаюсь, я пока не совсем понимаю все об этих лямбдах! :)

Ответы [ 3 ]

16 голосов
/ 10 июля 2011

Пример Бьярне не компилируется.Он не может скомпилироваться, если только они не определяют std::fill по-разному в C ++ 0x.Возможно, это было из задуманной версии std::fill, которая могла бы принимать функцию, но фактическая версия (согласно разделу 25.1 N3242) принимает объект , а не функцию.Он копирует этот объект в каждый элемент списка.Вот что пытается сделать этот человек.

Функция, которую вы ищете: std::generate.

1 голос
/ 10 июля 2011

Я надеюсь, что все в порядке, чтобы добавить ответ в стиле «обновление», для будущих читателей, у которых может возникнуть тот же вопрос. Пожалуйста, дайте мне знать, так как я здесь новенький.

Итак, вот моя последняя переработанная форма кода, которая делает то, что я хочу:

#include <iostream>
#include <vector>
#include <algorithm>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    int index{ base };
    std::generate(ints.begin(), ints.end(), [&index]() {
        return index++;  //post-incr.
    });
}

//Default wrapper to overwrite a vector<int> 
// with incrementing values, base-0.
void init_integers(std::vector<int>& ints) {
    init_integers(ints, 0);
}

//Test lambda-based vector<int> initialization.
int main() {
    std::vector<int> indices( 50 );
    init_integers(indices);

    //test output loaded indices.
    for (auto x : indices) {
        std::cout << x << std::endl;
    }
}

Спасибо за полезные ответы, я считаю, что это намного проще. Вполне вероятно, что теперь я буду использовать лямбда-выражения для алгоритмов, которые принимают объект функции!



Обновление 2:

На основании комментария ildjarn к оригинальному сообщению выше: «Обратите внимание, что точная функциональность здесь реализована с помощью нового алгоритма C ++ 0x - std :: iota.»

После тестирования я изменил соответствующий код:

...
#include <numeric>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    std::iota(ints.begin(), ints.end(), base);
}
...

и работает нормально. ("Йота", с26.7.6, из N3242).

Чем проще и чище (хотя и немного непонятно), тем легче читать и, что более важно, поддерживать.

Спасибо, ildjarn! (Хотя лично мне было полезно пройти через этот процесс, чтобы узнать больше о лямбдах на C ++ 0x!) :) -Буд Алверсон

1 голос
/ 10 июля 2011

Попробуйте это:

for_each(indices.begin(), indices.end(), [&count](int& it) 
{        
    it = ++count;    
});

it в настоящее время повторяется содержание вектора и приходит по ссылке.

...