#include <cstddef>
#include <array>
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
template<typename T>
auto wrap_value(T&& value)
{
return std::tuple<T&&>(std::forward<T>(value));
}
template<typename T, std::size_t N>
std::array<T, N>& wrap_value(std::array<T, N>& value)
{
return value;
}
template<typename T, std::size_t N>
std::array<T, N> const& wrap_value(std::array<T, N> const& value)
{
return value;
}
template<typename T, std::size_t N>
std::array<T, N>&& wrap_value(std::array<T, N>&& value)
{
return std::move(value);
}
template<std::size_t... Is, typename... Ts>
std::array<std::common_type_t<Ts...>, sizeof...(Is)>
join_arrays_impl(std::index_sequence<Is...>, std::tuple<Ts...>&& parts)
{
return {std::get<Is>(std::move(parts))...};
}
template<typename... Ts>
auto join_arrays(Ts&&... parts)
{
auto wrapped_parts = std::tuple_cat((wrap_value)(std::forward<Ts>(parts))...);
constexpr auto size = std::tuple_size<decltype(wrapped_parts)>::value;
std::make_index_sequence<size> seq;
return (join_arrays_impl)(seq, std::move(wrapped_parts));
}
int main()
{
std::array<std::string, 2> strings = { "a", "b" };
std::array<std::string, 2> more_strings = { "c", "d" };
std::string another_string = "e";
auto result = join_arrays(strings, more_strings, another_string);
for (auto const& i : result) {
std::cout << i << '\n';
}
// Making sure old strings are valid.
std::cout << '\n';
std::cout << strings[0] << ' ' << strings[1] << '\n';
std::cout << more_strings[0] << ' ' << more_strings[1] << '\n';
std::cout << another_string << '\n';
}
I2luY2x1ZGUgPGNzdGRkZWY+CiNpbmNsdWRlIDxhcnJheT4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KI2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgphdXRvIHdyYXBfdmFsdWUoVCYmIHZhbHVlKQp7CiAgICByZXR1cm4gc3RkOjp0dXBsZTxUJiY+KHN0ZDo6Zm9yd2FyZDxUPih2YWx1ZSkpOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCBzdGQ6OnNpemVfdCBOPgpzdGQ6OmFycmF5PFQsIE4+JiB3cmFwX3ZhbHVlKHN0ZDo6YXJyYXk8VCwgTj4mIHZhbHVlKQp7CiAgICByZXR1cm4gdmFsdWU7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHN0ZDo6c2l6ZV90IE4+CnN0ZDo6YXJyYXk8VCwgTj4gY29uc3QmIHdyYXBfdmFsdWUoc3RkOjphcnJheTxULCBOPiBjb25zdCYgdmFsdWUpCnsKICAgIHJldHVybiB2YWx1ZTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgc3RkOjpzaXplX3QgTj4Kc3RkOjphcnJheTxULCBOPiYmIHdyYXBfdmFsdWUoc3RkOjphcnJheTxULCBOPiYmIHZhbHVlKQp7CiAgICByZXR1cm4gc3RkOjptb3ZlKHZhbHVlKTsKfQoKdGVtcGxhdGU8c3RkOjpzaXplX3QuLi4gSXMsIHR5cGVuYW1lLi4uIFRzPgpzdGQ6OmFycmF5PHN0ZDo6Y29tbW9uX3R5cGVfdDxUcy4uLj4sIHNpemVvZi4uLihJcyk+CmpvaW5fYXJyYXlzX2ltcGwoc3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4sIHN0ZDo6dHVwbGU8VHMuLi4+JiYgcGFydHMpCnsKICAgIHJldHVybiB7c3RkOjpnZXQ8SXM+KHN0ZDo6bW92ZShwYXJ0cykpLi4ufTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHM+CmF1dG8gam9pbl9hcnJheXMoVHMmJi4uLiBwYXJ0cykKewogICAgYXV0byB3cmFwcGVkX3BhcnRzID0gc3RkOjp0dXBsZV9jYXQoKHdyYXBfdmFsdWUpKHN0ZDo6Zm9yd2FyZDxUcz4ocGFydHMpKS4uLik7CiAgICBjb25zdGV4cHIgYXV0byBzaXplID0gc3RkOjp0dXBsZV9zaXplPGRlY2x0eXBlKHdyYXBwZWRfcGFydHMpPjo6dmFsdWU7CiAgICBzdGQ6Om1ha2VfaW5kZXhfc2VxdWVuY2U8c2l6ZT4gc2VxOwogICAgcmV0dXJuIChqb2luX2FycmF5c19pbXBsKShzZXEsIHN0ZDo6bW92ZSh3cmFwcGVkX3BhcnRzKSk7Cn0KCmludCBtYWluKCkKewogICAgc3RkOjphcnJheTxzdGQ6OnN0cmluZywgMj4gc3RyaW5ncyA9IHsgImEiLCAiYiIgfTsKICAgIHN0ZDo6YXJyYXk8c3RkOjpzdHJpbmcsIDI+IG1vcmVfc3RyaW5ncyA9IHsgImMiLCAiZCIgfTsKICAgIHN0ZDo6c3RyaW5nIGFub3RoZXJfc3RyaW5nID0gImUiOwoKICAgIGF1dG8gcmVzdWx0ID0gam9pbl9hcnJheXMoc3RyaW5ncywgbW9yZV9zdHJpbmdzLCBhbm90aGVyX3N0cmluZyk7CiAgICBmb3IgKGF1dG8gY29uc3QmIGkgOiByZXN1bHQpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgaSA8PCAnXG4nOwogICAgfQoKICAgIC8vIE1ha2luZyBzdXJlIG9sZCBzdHJpbmdzIGFyZSB2YWxpZC4KICAgIHN0ZDo6Y291dCA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IHN0cmluZ3NbMF0gPDwgJyAnIDw8IHN0cmluZ3NbMV0gPDwgJ1xuJzsKICAgIHN0ZDo6Y291dCA8PCBtb3JlX3N0cmluZ3NbMF0gPDwgJyAnIDw8IG1vcmVfc3RyaW5nc1sxXSA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IGFub3RoZXJfc3RyaW5nIDw8ICdcbic7Cn0K