Reputation: 355
I am not using std::transform often, however I found it very useful and I am starting replacing some for loops with this algorithm.
What is wrong here? I want to keep all the elements of the vector vec that have code > 100. I would expect to have a new std::vector with 3 elements: 133, 144 and 155. But after the algorithm the size is 0. What is wrong?
TEST_CASE("testing trasf1", "[tras1]") {
std::vector<Test2> vec {
{1,1},
{3,3},
{11,11},
{12,12},
{133,133},
{19,19},
{21,21},
{22,22},
{23,23},
{144,144},
{155,155}
};
std::vector<uint32_t> final_v {};
final_v.reserve(vec.size());
transform(begin(vec), end(vec), begin(final_v), [] (const Test2& elem) {
if ( elem.getCode() > 100)
return elem.getCode();
});
//REQUIRE(final.size() == 3);
cout << final_v.size() << endl;
for (const auto i : final_v) {
cout << i << endl;
}
}
Upvotes: 0
Views: 1366
Reputation: 5085
Doing filter and transform in one operation:
template<class Container>
struct optional_inserter_iterator: std::back_insert_iterator //convenience
{
using std::back_insert_iterator::*;
optional_inserter_iterator(Container &c) : std::back_insert_iterator(c)
{}
optional_inserter_iterator & operator=(std::optional<Container::value_type> &&opt)
{
if(opt)
std::back_insert_iterator::operator=(*std::move(opt))
return *this;
}
}
Use this in transform and let your lambda return an optional
(untested)
EDIT: There are some reasons not to inherit from std::back_insert_iterator
. If someone is interested in a really correct version, I can do one.
Upvotes: 1
Reputation: 68591
transform
doesn't insert elements into the output sequence, it just writes to the *iter
and increments the iterator.
If you want to insert to the sequence, use std::back_inserter(final)
as the output iterator.
Alternatively, call final.resize(vec.size())
first, to set the output vector to the correct size. Note that this will intialize the vector elements to zero, so for large vectors will incur a noticeable time overhead.
Upvotes: 4