更新时间:2023-11-30 19:18:34
自从您提到C ++ 14以来,这是另一个使用std::index_sequence
的人.我认为该解决方案值得一提的主要原因是使用constexpr
映射函数将类型放置在结果List
中的位置.这使实现相对简单.
Since you mentioned C++14, here's another one making use of std::index_sequence
. The main reason for which I think the solution is worth mentioning is the use of constexpr
mapping functions to place the types in their positions in the resulting List
. This makes the implementation relatively straightforward.
#include <cstddef>
#include <tuple>
#include <utility>
template<typename...> struct List;
constexpr std::size_t map_ins(std::size_t i, std::size_t from, std::size_t to)
{
return i < to ? i : i == to ? from : i - 1;
}
template<typename, typename, std::size_t, typename...> struct ins_hlp;
template<std::size_t... Is, typename U, std::size_t N, typename... Ts>
struct ins_hlp<std::index_sequence<Is...>, U, N, Ts...>
{
static_assert(N <= sizeof...(Ts), "Insert index out of range");
using type = List<std::tuple_element_t<map_ins(Is, sizeof...(Ts), N), std::tuple<Ts..., U>>...>;
};
constexpr std::size_t map_rem(std::size_t i, std::size_t idx)
{
return i < idx ? i : i + 1;
}
template<typename, std::size_t, typename...> struct rem_hlp_2;
template<std::size_t... Is, std::size_t N, typename... Ts>
struct rem_hlp_2<std::index_sequence<Is...>, N, Ts...>
{
using type = List<std::tuple_element_t<map_rem(Is, N), std::tuple<Ts...>>...>;
};
template<std::size_t N, typename... Ts> struct rem_hlp
{
static_assert(N < sizeof...(Ts), "Remove index out of range");
using type = typename rem_hlp_2<std::make_index_sequence<sizeof...(Ts) - 1>, N, Ts...>::type;
};
template<typename... Ts> struct List
{
template<typename U, std::size_t N> using Insert = typename ins_hlp<std::make_index_sequence<sizeof...(Ts) + 1>, U, N, Ts...>::type;
template<std::size_t N> using Remove = typename rem_hlp<N, Ts...>::type;
};
很抱歉,但我没有找到另一种有意义的方式来格式化这些参数列表.
Sorry for the long lines, but I didn't find another meaningful way to format those argument lists.
为Remove
附加辅助程序的唯一原因是边界检查.如果不需要,Remove
可以使用与Insert
相同的模式.
The only reason for having an additional helper for Remove
is bounds checking; if that's not needed, Remove
can use the same pattern as Insert
.