有没有办法将旧 class 模板中的所有类型模板参数传递到新 class 模板中?

Is there a way to pass all type template parameters in an old class template into a new class template?

我创建了一个名为 tuple_tag 的简单模板 class,它与 std::tuple 相同,但仅用作 标签

// tuple_tag
template <typename...> struct tuple_tag {};

// tuple_tag_element
template <size_t I, typename T>
struct tuple_tag_element;

template <size_t I, typename Head, typename... Tail>
struct tuple_tag_element<I, tuple_tag<Head, Tail...>>
: tuple_tag_element<I - 1, tuple_tag<Tail...>> {};

template <typename Head, typename... Tail>
struct tuple_tag_element<0, tuple_tag<Head, Tail...>>
: std::type_identity<Head> {};

// tuple_tag_element_t
template <size_t I, typename T>
using tuple_tag_element_t = tuple_tag_element<I, T>::type;

// tuple_tag_size
template <typename T>
struct tuple_tag_size;

template <typename T> requires (std::is_reference_v<T> || std::is_const_v<T>)
struct tuple_tag_size<T> : tuple_tag_size<std::remove_cvref_t<T>> {};

template <typename... Ts>
struct tuple_tag_size<tuple_tag<Ts...>>
: std::integral_constant<size_t, sizeof...(Ts)> {};

// tuple_tag_size_v
template <typename T>
inline constexpr size_t tuple_tag_size_v = tuple_tag_size<T>::value;

这里:

using new_type_1 = to_tuple_type<tuple_tag<int, double>>::type; 
// new_type_1 = std::tuple<int, double>;
using new_type_2 = to_tuple_tag_type<std::tuple<int, double>>::type;
// new_type_2 = tuple_tag<int, double>;

其中 to_tuple_type 采用类型模板参数 tuple_tag<...> 将被转换为类型 std::tuple<...>,而 to_tuple_tag_type 采用类型模板参数 std::tuple<...>将转换为 tuple_tag<...>.

类型

我在这里试图实现的是将所有类型模板参数从 tuple_tag 传递到 std::tuple,反之亦然。

这是我的 to_tuple_type 原型,但它失败了:

template <typename TupleTag>
struct to_tuple_type {
    using type = std::tuple<...>;
};

其中 type 别名将扩展为:

using type = std::tuple<tuple_tag_element_t<Index, TupleTag>...>;
...
using type = std::tuple<
    tuple_tag_element_t<0, TupleTag>,
    tuple_tag_element_t<1, TupleTag>,
    ...,
    tuple_tag_element_t<N - 1, TupleTag>
>;

其中 N 等于 tuple_tag_size_v<TupleTag>

我只能想到用std::index_sequence,但我不知道在哪里引入包。

有一个应用部分模板特化的简单解决方案:

// to_tuple_type
template <typename Tup>
struct to_tuple_type;

template <typename... Ts>
struct to_tuple_type<tuple_tag<Ts...>> : std::type_identity<std::tuple<Ts...>> {};

// to_tuple_type_t
template <typename Tup>
using to_tuple_type_t = to_tuple_type<Tup>::type;

// to_tuple_tag_type
template <typename Tup>
struct to_tuple_tag_type;

template <typename... Ts>
struct to_tuple_tag_type<std::tuple<Ts...>> : std::type_identity<tuple_tag<Ts...>> {};

// to_tuple_tag_type_t
template <typename Tup>
using to_tuple_tag_type_t = to_tuple_tag_type<Tup>::type;

3 个步骤。首先,做一个包

using indexes=std::make_index_sequence<tuple_tag_size<TupleTag>;

然后有一个扩展包的助手。我喜欢这个:

template<auto x>
using constant_t=std::integral_constant<decltype(x),x>;
template<auto x>
constexpr constant_t<x> constant={};  
template<std::size_t...Is>
constexpr auto all_indexes( std::index_sequence<Is...> ){
  return [](auto f){
    return f(constant<Is>...);
  };
}

现在我们可以

template<class T>
struct tag_t{using type=T;};
template<class T>
constexpr tag_t<T> tag={};
using type=typename decltype(all_indexes(indexes{})([](auto...Is){
  return tag<std::tuple<tuple_tag_element_t<Is, TupleTag>...>;
}))::type;

如果没有tpyos。