Например, если у меня есть 2 контейнера a,b
, с индексами {0,1,2}
и {0,1,2,3}
, расширение должно выглядеть как A(a[0],a[1],a[2], b[0],b[1],b[2],b[3])
.
Я знаю, что могу сделатьэто рекурсивно, распаковка одного контейнера за раз, и рекурсивное делегирование конструкторам, ожидающим последовательность только плоских элементов в начале. Мой вопрос заключается в том, возможно ли это более изящным, эффективным и менее многословным способом.
Принимаете ли вы решение, при котором расширение даст вам std::tuple
с a[0],a[1],a[2], b[0],b[1],b[2],b[3]
?
В этом случае вы можете следовать предложению Игоря, распаковать значения в контейнерах и упаковать их в кортежи и использовать std::tuple_cat()
для объединения кортежей.
Я имею в виду ... учитывая контейнер /Преобразователь кортежей выполняется следующим образом:
template <template<typename, std::size_t...> typename C,
typename T, std::size_t... Is>
auto getTpl (C<T, Is...> const & v)
{ return std::make_tuple(v.data[Is]...); }
. Вы можете начать писать свой конструктор, вызывая конструктор делегата, следующим образом
template <typename ... Ts>
A (Ts const & ... ts) : A{ std::tuple_cat( getTpl(ts)... ) }
{ }
, а конечный конструктор будет
template <typename ... Ts>
A (std::tuple<Ts...> const & tpl)
{ /* do something with values inside tpl */ }
Ниже приводится полный пример компиляции
#include <iostream>
#include <string>
#include <tuple>
template <typename T, std::size_t ... Is>
struct Vec
{
T data [sizeof...(Is)] = { Is... };
T const & operator[] (std::size_t i) const
{ return data[i]; }
T & operator[] (std::size_t i)
{ return data[i]; }
};
template <template<typename, std::size_t...> typename C,
typename T, std::size_t... Is>
auto getTpl (C<T, Is...> const & v)
{ return std::make_tuple(v.data[Is]...); }
struct A
{
template <typename ... Ts>
A (std::tuple<Ts...> const & tpl)
{ /* do something with values inside tpl */ }
template <typename ... Ts>
A (Ts const & ... ts) : A{ std::tuple_cat( getTpl(ts)... ) }
{ }
};
int main ()
{
A a(Vec<int, 0>{}, Vec<double, 0>{}); // ok
A b(Vec<int, 0, 1>{}, Vec<double, 0, 1>{}); // ok
A c(Vec<int, 0>{}, Vec<double, 0, 1>{}); // ok, now
}