Я предлагаю следующую структуру и используя
template <typename T0, typename...>
struct flatt_helper
{ using type = T0; };
template <typename ... Ts1, typename T0, typename ... Ts2>
struct flatt_helper<pack<Ts1...>, T0, Ts2...>
: flatt_helper<pack<Ts1..., T0>, Ts2...>
{ };
template <typename ... Ts1, template <typename ...> class C,
typename ... Ts2, typename ... Ts3>
struct flatt_helper<pack<Ts1...>, C<Ts2...>, Ts3...>
: flatt_helper<pack<Ts1...>, Ts2..., Ts3...>
{ };
template <typename T>
using flatt = typename flatt_helper<pack<>, T>::type;
Таким образом, вы можете сгладить pack
и другие шаблоны-шаблоны, как std::tuple
, а также более сложные примеры (pack<int, pack<int, int>, int>
, предложенныйХолт, к примеру).
Если вы хотите только плоскую pack
, избегая того, чтобы все шаблоны-шаблоны были сплющены ..., я имею в виду ... если вы хотите, чтобы
pack<int, pack<int, std::tuple<int, long>>>
уплощено как
pack<int, int, std::tuple<int, long>>
вместо
pack<int, int, int, long>
Вы должны удалить параметр шаблона-шаблона в последней специализации flatt_helper
и упростить его следующим образом
template <typename ... Ts1, typename ... Ts2, typename ... Ts3>
struct flatt_helper<pack<Ts1...>, pack<Ts2...>, Ts3...>
: flatt_helper<pack<Ts1...>, Ts2..., Ts3...>
{ };
Ниже приведен пример полной компиляции (с полным выравниванием)
#include <tuple>
#include <type_traits>
template <typename...>
struct pack
{ };
template <typename T0, typename...>
struct flatt_helper
{ using type = T0; };
template <typename ... Ts1, typename T0, typename ... Ts2>
struct flatt_helper<pack<Ts1...>, T0, Ts2...>
: flatt_helper<pack<Ts1..., T0>, Ts2...>
{ };
template <typename ... Ts1, template <typename ...> class C,
typename ... Ts2, typename ... Ts3>
struct flatt_helper<pack<Ts1...>, C<Ts2...>, Ts3...>
: flatt_helper<pack<Ts1...>, Ts2..., Ts3...>
{ };
template <typename T>
using flatt = typename flatt_helper<pack<>, T>::type;
int main()
{
using T0 = pack<int, pack<int, pack<int, pack<int>>>>;
using T1 = pack<int, int, int, int>;
using T2 = flatt<T0>;
using T3 = pack<int, pack<int, long>, std::tuple<pack<int, char>, long>>;
using T4 = pack<int, int, long, int, char, long>;
using T5 = flatt<T3>;
static_assert( std::is_same<T1, T2>::value, "!" );
static_assert( std::is_same<T4, T5>::value, "!" );
}