Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use std::transform with container without push_back?

Tags:

c++

iterator

I have a container that has no push_back() method. But this container has an iterator on begin()and end().

I would like to use std::transform() to output into that container. But std::back_inserter needs to call push_back() on the output container.

Is it possible to use std::transform() to output into a container that just supports direct assignment? Like:

for (auto item : containerNoPushBack)
{
    item = calculateValue();
}

Or indexed assignment like:

for (size_t i = 0; i < containerNoPushBack.size(); ++i)
{
    item[i] = calculateValue();
}
like image 901
VisorZ Avatar asked Nov 16 '25 18:11

VisorZ


2 Answers

Just use a plain std::transform with begin and end iterators. No need for std::back_inserter or even an std::inserter.

For example, std::array does not support the push_back method, but std::transform works on it:

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

int main() {
    std::vector<int> data = {1, 2, 3, 4, 5};

    std::array<int, 5> arr{};

    // note the lack of std::back_inserter just below
    std::transform(data.cbegin(), data.cend(), arr.begin(),
            [](auto i) {
                return i * i;
            });

    for (const auto i : arr) {
        std::cout << i << ' '; // prints 1, 4, 9, 16, 25
    }
}
like image 119
Fureeish Avatar answered Nov 18 '25 10:11

Fureeish


If you can do item[i] (i.e. your container has enough elements in it), then you can simply use your_container.begin() in std::transform, no need for std::back_inserter. std::back_inserter is just a nice way to avoid explicitly resizing containers before applying it.

The following snippets will both fill my_output with contents of my_input:

std::vector<int> my_output;
std::transform(my_input.begin(), my_input.end(), std::back_inserter(my_output), [](const auto& arg){return arg;});

std::vector<int> my_output;
my_output.resize(my_input.size());
std::transform(my_input.begin(), my_input.end(), my_output.begin(), [](const auto& arg){return arg;});
like image 38
Yksisarvinen Avatar answered Nov 18 '25 08:11

Yksisarvinen