Is there a way to concatenate multiple vectors simply?

Viewed 1013

There currently exist ways to concatenate or merge two vectors with one function.

But, it seems that there's no way to concatenate or merge more than three vectors with one function.

For example,

vector<string> a = {"a", "b"};
vector<string> b = {"c", "d"};
vector<string> c = {"e", "f"};
vector<string> d = {"g", "h"};

// newVector has to include {"a", "b", "c", "d", "e", "f", "g", "h"}
vector<string> newVector = function(a, b, c, d);

If there is not, it seems that this can be implemented by using variadic template.

But, I can't imagine how it can be implemented by variadic template.

Are there any solutions?

3 Answers

If you can use range v3, you can simply do this:

std::vector<std::string> allVec = ranges::view::concat(a, b, c, d);

See demo here.

You can use this with any vector type.

Here is solution with variadic templates

template<typename T, typename ...Args>
void appendVector(vector<T>& v1, vector<T>& v2, Args... args)
{
     v1.insert(v1.end(), v2.begin(), v2.end());
     appendVector(v1, args...);
}

template<typename T>
void appendVector(vector<T>& v1, vector<T>& v2)
{
    v1.insert(v1.end(), v2.begin(), v2.end());
}

You just need to append your vectors:

vector<string> newVector;
newVector.reserve(a.size()+b.size()+c.size()+d.size());
appendVector(newVector, a, b, c, d);

Try something like this:

template<typename T>
std::vector<T> merge(std::initializer_list<std::vector<T>*> vecs)
{
    size_t size = 0;
    for(auto v : vecs) { size += v->size(); }
    std::vector<T> ret;
    ret.reserve(size);
    for(auto v : vecs) { ret.insert(ret.end(), v->begin(), v->end()); }
    return ret;
}

std::vector<std::string> a = {"a", "b"};
std::vector<std::string> b = {"c", "d"};
std::vector<std::string> c = {"e", "f"};
std::vector<std::string> d = {"g", "h"};

std::vector<std::string> newVector = merge({&a, &b, &c, &d});

Live Demo

Alternatively:

template<typename T>
std::vector<T> merge(std::initializer_list<std::reference_wrapper<const std::vector<T>>> vecs)
{
    size_t size = 0;
    for(auto &v : vecs) { size += v.get().size(); }
    std::vector<T> ret;
    ret.reserve(size);
    for(auto &v : vecs) { ret.insert(ret.end(), v.get().begin(), v.get().end()); }
    return ret;
}

std::vector<std::string> a = {"a", "b"};
std::vector<std::string> b = {"c", "d"};
std::vector<std::string> c = {"e", "f"};
std::vector<std::string> d = {"g", "h"};

std::vector<std::string> newVector = merge({std::cref(a), std::cref(b), std::cref(c), std::cref(d)});

Live Demo

Related