C ++如何通过其索引替换可变参数模板中的类型

C++ how to replace type in variadic template by its index

如何用索引替换可变参数模板中的 1 种类型? 例如我有:

//-------------static_list-------------
template<class ...Elements>
struct static_list {};

struct execute_command<index, static_list<Commands...>> {
    static constexpr int value = execute_s<index + 1, static_list<Commands...>>::value;
}

我想重写它,所以在 Commands 中它会将例如索引 5 处的类型替换为 variable<0, 0> 类型,如下所示:

struct execute_command<false, true, false, false, false, index, static_list<Commands...>> {
    static constexpr int value = execute_s<index + 1, static_list_replace<5, variable<0, 0>, Commands...>>::value;
}

我尝试了很多不同的方法,但没有任何效果。例如:

//-------------static_list_replace-------------
template<std::size_t N, typename T, typename Tuple, class IndexSequence>
struct static_list_replace;

template<std::size_t N, typename T, typename Tuple, std::size_t... Idx>
struct static_list_replace<N, T, Tuple, std::index_sequence<Idx ...>> {
    using type = std::tuple<std::conditional_t<N == Idx, T, std::tuple_element_t<N, Tuple>>...>;
};

namespace detail {
    template<std::size_t N, typename T, typename Tuple, std::size_t... Idx>
    auto replace(std::index_sequence<Idx...>) ->
        std::tuple<std::conditional_t<N == Idx,
        T,
        std::tuple_element_t<N, Tuple>>...>;
}

template <std::size_t N, typename T, typename... Args>
using Replace = decltype(detail::replace<N, T, std::tuple<Args...>>
    (std::index_sequence_for<Args...>{}));

或者我试图获取列表的开头并在没有一个元素的情况下结束然后将其打包为 static_list<list_beginning<index, Commands...>, element, list_ending<index, Commands...>>>

没有任何效果。

我想有很多方法...

例如,给定一个助手 class 作为 slrh(静态列表替换助手)

template <std::size_t, typename...>
struct slrh;

template <std::size_t N, typename R, std::size_t ... Is, typename ... Ts>
struct slrh<N, R, std::index_sequence<Is...>, Ts...>
 { using type = static_list<std::conditional_t<(N == Is), R, Ts>...>; };

你的static_list_replace可以简单写成如下

template <std::size_t, typename R, typename SL>
struct static_list_replace;

template <std::size_t N, typename R, typename ... Ts>
struct static_list_replace<N, R, static_list<Ts...>>
   : public slrh<N, R, std::make_index_sequence<sizeof...(Ts)>, Ts...>
 { };

下面是一个完整的编译示例

#include <utility>
#include <type_traits>

template <typename ...>
struct static_list
 { };

template <std::size_t, typename...>
struct slrh;

template <std::size_t N, typename R, std::size_t ... Is, typename ... Ts>
struct slrh<N, R, std::index_sequence<Is...>, Ts...>
 { using type = static_list<std::conditional_t<(N == Is), R, Ts>...>; };

template <std::size_t, typename R, typename SL>
struct static_list_replace;

template <std::size_t N, typename R, typename ... Ts>
struct static_list_replace<N, R, static_list<Ts...>>
   : public slrh<N, R, std::make_index_sequence<sizeof...(Ts)>, Ts...>
 { };

template <int...>
struct variable
 { };

int main()
 {
   using T1 = static_list<char, short, int, long, long long>;
   using T2 = static_list<char, short, char, long, long long>;
   using T3 = typename static_list_replace<2u, char, T1>::type;

   using T4 = static_list_replace<4, variable<16, 16>,
                static_list<char, short, int, long, long long>>::type;
   using T5 = static_list<char, short, int, long, variable<16, 16>>;

   static_assert( std::is_same_v<T2, T3> );
   static_assert( std::is_same_v<T4, T5> );
 }