简体   繁体   中英

C++ template function to concatenate both std::vector and std::array types

I have project where I am working with both fixed and variable length arrays of bytes. I want to have a function that can concatenate two arbitrary containers of bytes and return a single vector. Currently I am using

std::vector<uint8_t> catBytes(uint8_t const* bytes1, size_t const len1, 
                              uint8_t const* bytes2, size_t const len2) {
    std::vector<uint8_t> all_bytes;
    all_bytes.reserve(len1 + len2);
    all_bytes.insert(all_bytes.begin(), bytes1, bytes1 + len1);
    all_bytes.insert(all_bytes.begin() + len1, bytes2, bytes2 + len2);
    return all_bytes;
} // catBytes

However, I would like more generic way to do this, which better uses the capabilities of C++. I do not want to just accept iterators. I am trying to figure out how to accept two arbitrary containers and return a vector containing their contents. Ideally I would also not like to have to know the type inside the vector.

Something like

std::vector<unit_8> v1 = { 1, 2, 3, 4 };
std::array<unit_8, 4> a1 = { 1, 2, 3, 4 };
std::array<unit_8, 2> a2 = { 1, 2 };
auto res1 = concat(v1, a1); // std::vector<uint_8> of size 8
auto res2 = concat(a1, a2); // std::vector<uint_8> of size 6

// or

std::vector<char> v2 = { 1, 2, 3, 4 };
std::array<char, 4> a3 = { 1, 2, 3, 4 };
auto res3 = concat(v1, a1); // std::vector<char> of size 8

I think there is a templated approach to this but I just have not been able to figure it out.

std::array , std::vector and other contiguous_ranges can be converted to a lightweight std::span , which you can use for type erasure.

#include <cstdint>
#include <span>
#include <vector>

std::vector<uint8_t> 
catBytes(std::span<const uint8_t> x, std::span<const uint8_t> y) {
  std::vector<uint8_t> all_bytes;
  all_bytes.reserve(x.size() + y.size());
  all_bytes.insert(all_bytes.begin(), x.begin(), x.end());
  all_bytes.insert(all_bytes.end(), y.begin(), y.end());
  return all_bytes;
}

Demo

In general, generic + arbitrary, means templates.

Something like this?

template<class SizedRange1, class SizedRange2>
auto concat(SizedRange1 const& r1, SizedRange2 const& r2) {
    std::vector<typename SizedRange1::value_type> ret;
    ret.reserve(r1.size() + r2.size());

    using std::begin; using std::end;
    ret.insert(ret.end(), begin(r1), end(r1));
    ret.insert(ret.end(), begin(r2), end(r2));

    return ret;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM