开发者

modify every element of collection

Is there any common way to get rid of custom 'assign' functor? std::transform could be great but according to c++ standard it prohibits modification of the source elements

The goal is to modify collection elements using as more declarative approach as possible

template <typename T>
struct assign : std::binary_function<T, T, void开发者_C百科> {
    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;
}


std::transform() does allow the output iterator to point to the same element as the beginning of your input range. See here. The code example shows essentially this in the line demonstrating a transform with two input ranges. The output iterator is the same as the first input iterator. Does that make it more palatable?


Try 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;
}

However, what about just a "for_each" loop:

int main() {
    static boost::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    BOOST_FOREACH(int& n, arr) {
        n += 3;
    }
    return 0;
}


What @gregg said plus:

The wording in the standard (N1905 25.2.3 paragraph 2) forbids the transformation function from directly modifying elements in the given ranges, i.e. it cannot write to an input iterator. It is only supposed to calculate a value, which the transform function then assigns to the result iterator. In fact, paragraph 5 explicitly allows result to be equal to first.

I guess this may allow implementations to perform safety-checks or optimizations in specific cases.

For instance, suppose transform were specialized for std::vector<char>. On a 32 bit machine, the implementation could unroll the main loop 4 times and perform 32 bit loads and stores instead of 8 bit ones. Clearly this would not work, if the first call to the transformation function modified the input range (the remaining 3 calls before the store would then operate on dirty data).

Here's C++03 one-liner to add 3 to each value off arr:

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜