Vit*_*meo 5 c++ templates metaprogramming variadic-templates c++14
在可变参数模板类型列表(参数包)中实现基于索引的插入和删除类型的最佳方法是什么?
期望的代码/行为:
template<typename...> struct List { /* ... */ };
static_assert(is_same
<
List<int, char, float>::Insert<int, 0>,
List<int, int, char, float>
>());
static_assert(is_same
<
List<int, char, float>::Insert<int, 2>,
List<int, char, int, float>
>());
static_assert(is_same
<
List<int, char, float>::Remove<0>,
List<char, float>
>());
static_assert(is_same
<
List<int, char, float>::Remove<1>,
List<int, float>
>());
Run Code Online (Sandbox Code Playgroud)
我尝试了一个基于在最初为空的列表中推回参数的实现,但是它很难读取/维护.参数类似于:
template<typename T, int I, int ITarget, typename TResult> struct InsertImpl;
Run Code Online (Sandbox Code Playgroud)
我不断增加I
直到它等于ITarget
,推回现有的类型TResult
,这是一个List<...>
.当I
等于ITarget
,我推回T
的TResult
为好.
删除类型有一个类似的实现 - 而不是在索引相等时两次推回,我只是跳过了类型.
我的繁琐解决方案将在推送和弹出方面实现插入和删除.我相信推到前面等于Insert<0>
并推到后面等于更优雅Insert<size>
.这同样适用于从前面和后面弹出.
有没有更好的方法呢?C++ 14功能有用吗?
既然您提到了 C++14,那么这里是另一个使用std::index_sequence
. 我认为该解决方案值得一提的主要原因是使用constexpr
映射函数将类型放置在结果中的位置List
。这使得实现相对简单。
#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;
};
Run Code Online (Sandbox Code Playgroud)
很抱歉这么长的行,但我没有找到另一种有意义的方法来格式化这些参数列表。
需要额外助手的唯一原因Remove
是边界检查;如果不需要,Remove
可以使用与 相同的模式Insert
。
归档时间: |
|
查看次数: |
1691 次 |
最近记录: |