изменить каждый элемент коллекции - PullRequest
2 голосов
/ 06 января 2011

Есть ли какой-нибудь общий способ избавиться от пользовательского функтора 'assign'? std :: transform может быть великолепным, но в соответствии со стандартом c ++ запрещает модификацию исходных элементов

Цель состоит в том, чтобы изменить элементы коллекции, используя как можно более декларативный подход

template <typename T>
struct assign : std::binary_function<T, T, void> {
    void operator()( const T& source, T& dest ) {
        dest = source;
    }
};

int main() {
    static boost::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::for_each( arr.begin(), arr.end(), 
        boost::bind( assign<int>(), boost::bind( std::plus<int>(), _1, 3 ), _1 ) );
    return 0;
}

Ответы [ 3 ]

3 голосов
/ 06 января 2011

std :: transform () позволяет выходному итератору указывать на тот же элемент, что и на начало вашего входного диапазона.Смотрите здесь .Пример кода демонстрирует это по существу в строке, демонстрирующей преобразование с двумя входными диапазонами.Выходной итератор такой же, как первый входной итератор.Это делает его более приемлемым?

2 голосов
/ 06 января 2011

Попробуйте Boost.Lambda:

int main() {
    using namespace boost::lambda;
    static boost::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::for_each( arr.begin(), arr.end(), _1 += 3 );
    return 0;
}

Однако, как насчет просто цикла for_each:

int main() {
    static boost::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    BOOST_FOREACH(int& n, arr) {
        n += 3;
    }
    return 0;
}
1 голос
/ 06 января 2011

Что сказал @gregg плюс:

Формулировка в стандарте (параграф 2 N1905 25.2.3) запрещает функции преобразования напрямую изменять элементы в заданных диапазонах, то есть не может записывать в итератор ввода.Предполагается только вычислить значение, которое функция transform затем присваивает итератору result.Фактически, пункт 5 явно разрешает result быть равным first.

Полагаю, это может позволить реализациям выполнять проверки безопасности или оптимизации в определенных случаях.

Например, предположим, что transform были специализированы для std::vector<char>.На 32-битной машине реализация могла бы развернуть основной цикл 4 раза и выполнить 32-битные загрузки и сохранения вместо 8-битных.Понятно, что это не сработает, если первый вызов функции преобразования изменил диапазон ввода (оставшиеся 3 вызова перед сохранением будут затем работать с грязными данными).

Вот C ++ 03 для добавления одной строки3 для каждого значения отключено arr:

std::transform(arr.begin(), arr.end(), arr.begin(), std::bind1st(std::plus<int>(), 3));

...