Generic function to flatten a container of containers

Viewed 4267

I am trying to get a better hold on iterators and generic functions. I thought it would be a useful exercise to write a function that converts container1 < container2 <type> > to container3 <type>. For example, it should be able to convert vector< deque<int> > to list<int>.

I figured all the container access should be through iterators, like the functions in <algorithm>.

Here is my code:

#include <iterator>
#include <algorithm>

// COCiter == Container of Containers Iterator
// Oiter == Output Iterator
template <class COCiter, class Oiter>
void flatten (COCiter start, COCiter end, Oiter dest)
{
    using namespace std;

    while (start != end) {
        dest = copy(start->begin(), start()->end(), dest);
        ++start;
    }
}

But when I try to call it in the following code:

int main ()
{
    using namespace std;

    vector< vector<string> > splitlines;
    vector<string> flat;

    /* some code to fill SPLITLINES with vectors of strings */

    flatten(splitlines.begin(), splitlines.end(), back_inserter(flat));
}

I get a huge C++ template error message, undefined reference to void flatten< ... pages of templates ...

I feel like my code was too easy to write, and I must need some more stuff to ensure that the data type in the inner containers matches the data type in the output container. But I don't know what to do.

2 Answers

std::accumulate can do it for you. You need to gather up the contents of each of the inside vectors into the outside vector.

vector<vector<int>> v_of_v;
vector<int> v = std::accumulate(
    v_of_v.begin(), v_of_v.end(),
    vector<int>(),
    [](vector<int> a, vector<int> b) {
        a.insert(a.end(), b.begin(), b.end());
        return a;
    });
Related