【发布时间】:2020-02-18 21:06:11
【问题描述】:
我正在尝试编写一个函数,该函数从现有的std::tuple 创建一个新的std::tuple,并跳过给定索引上的元素。例如:
我有一个元组 t 定义如下:
constexpr auto t = std::tuple(1, 2, 3, 4);
我想将它复制到另一个元组。但是,我想跳过 nth 元素。假设在这种情况下,我想跳过的 nth 元素是 3(这意味着我想跳过索引为 2 的元素)。这将导致一个新的元组定义为:
std::tuple(1, 2, 4);
这是迄今为止我得到的最接近的:
template<std::size_t N, typename T, std::size_t ... is>
constexpr auto fun(T&& tp, std::index_sequence<is...>&& i) noexcept {
return std::tuple((is != N ? std::get<is>(tp) : 0) ...);
}
template<std::size_t N, std::size_t... elems>
constexpr auto fun2() noexcept {
constexpr auto t = std::tuple(elems...);
return fun<N>(std::forward_as_tuple(elems...), std::make_index_sequence<sizeof...(elems)>());
}
但是,我没有删除 nth 元素,而是将其设置为 0。
理想情况下,我会更改函数fun() 中的返回参数,以使用多个临时元组创建一个新元组:
return std::tuple_cat((is != N ? std::tuple(std::get<is>(tp)) : std::tuple()) ...);
但是,这个问题是三元运算符必须在两边都有匹配的类型。
我尝试的另一种方法是基于递归:
template<std::size_t N, std::size_t head, std::size_t... tail>
constexpr auto fun3() noexcept {
if constexpr(!sizeof...(tail))
return std::tuple(head);
if constexpr(sizeof...(tail) - 1 == N)
return std::tuple_cat(fun3<N, tail...>());
if constexpr(sizeof...(tail) - 1 != N)
return std::tuple_cat(std::tuple(head), fun3<N, tail...>());
}
然而,这更加不成功。在这种情况下,如果 N 等于 0,则 nth 元素(也是这里的第一个元素)仍将用于新元组中。此外,这甚至不会编译,因为第二个语句存在问题:
if constexpr(sizeof...(tail) - 1 == N)
我在这里缺少什么?如何复制元组并在复制过程中跳过其中一个元素?
我使用的是 C++17,我需要在编译时评估函数。
【问题讨论】:
标签: algorithm templates c++17 variadic-templates template-meta-programming