This is a C++17
solution using std::apply
.
NOTE: my usage of auto
and requires
pushes this into C++20
.
This is actually possible by leveraging the fact that std::apply
is constexpr
meaning that you can access and tuple-type, including arrays, in terms of their underlying parameter pack:
#include <tuple>
#include <array>
#include <iostream>
//helper function:
//create array without the last element provided
//used to remove '\0' in concat
template <std::size_t N>
constexpr std::array<const char, N> trim(
auto head, auto... chars
) requires (sizeof...(chars) == N) {
if constexpr (sizeof...(chars) == 0) {
return std::array<const char, 0>{}; //ignore last element
} else {
return std::apply([&head](auto... trim_chars){
return std::array<const char, N>{head, trim_chars...}; //recurse
}, trim<N - 1>(chars...));
}
}
//concatonate 2 arrays by converting them into param backs using std::apply
//this works because std::apply is a constexpr function
template <std::size_t N, std::size_t M>
constexpr std::array<const char, N + M + 1> concat(
const std::array<const char, N + 1>& n,
const std::array<const char, M + 1>& m
) {
std::array<const char, N> trim_n = std::apply([](auto... args){return trim<N>(args...);}, n);
return std::apply([&](auto... n_chars){
return std::apply([&](auto... m_chars){
return std::array<const char, N + M + 1>{n_chars..., m_chars...};
}, m);
}, trim_n);
}
//example strings
constexpr std::array<const char, 4> x{"abc"};
constexpr std::array<const char, 4> y{"def"};
constexpr std::array<const char, 7> z = concat<3, 3>(x, y);
int main() {
std::cout << &x[0] << " + " << &y[0] << " = " << &z[0];
}
This outputs:
abc + def = abcdef