I have a class template which is based on a std::tuple
and only consist of that tuple.
How can I concatenate two object of this class template in order to have all the tuple member of both class as an object of the same class template.
Using tuple_cat
does not works, probably because the types are not tuple
template<typename...Ts>
class foo : private std::tuple<Ts...> {
public:
foo(Ts...vs) : std::tuple<Ts...>(vs...){}
// .
// .
// .
};
template<typename...T1s, typename...T2s>
foo<T1s..., T2s...> operator+(const foo<T1s...>& foo1, const foo<T2s...>& foo2){
// return std::tuple_cat(foo1, foo2); // this does not work
// what should be here?
}
foo<int, float, const char*> obj1(1, 1.23, "string1");
foo<const char*, float, int> obj2("string2" , 1.23, 1);
foo<int, float, const char*, const char*, float, int> obj3 = obj1 + obj2;// I want to do this by overloading of operator +
Because you inherit privately, the std::tuple
base is not accessible to operator+
, so you need to fix that one way or another. I think the easiest way is to make operator+
a friend of foo
. Then, with the addition of a (private) constructor from std::tuple
, you can just use std::tuple_cat
on the correct types (through references or static_cast
):
template<typename... Ts>
class foo : private std::tuple<Ts...> {
explicit foo(std::tuple<Ts...>&& tuple) : std::tuple<Ts...>(std::move(tuple)) {}
public:
foo(Ts...vs) : std::tuple<Ts...>(vs...){}
template<typename... T1s, typename... T2s>
friend foo<T1s..., T2s...> operator+(foo<T1s...> const& foo1, foo<T2s...> const& foo2);
};
template<typename... T1s, typename... T2s>
foo<T1s..., T2s...> operator+(foo<T1s...> const& foo1, foo<T2s...> const& foo2) {
std::tuple<T1s...> const& tuple1 = foo1;
std::tuple<T2s...> const& tuple2 = foo2;
return foo(std::tuple_cat(tuple1, tuple2));
}
If you don't want the additional constructor, you can use std::apply
to pass all the elements to the main constructor instead:
template<typename... T1s, typename... T2s>
foo<T1s..., T2s...> operator+(foo<T1s...> const& foo1, foo<T2s...> const& foo2) {
std::tuple<T1s...> const& tuple1 = foo1;
std::tuple<T2s...> const& tuple2 = foo2;
auto make_foo = [](auto&&... arg) { return foo(std::move(arg)...); };
return std::apply(make_foo, std::tuple_cat(tuple1, tuple2));
}