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));
精彩评论