我正在尝试编写一个函数,该函数std::tuple
从现有的函数创建一个新函数,并跳过给定索引上的元素。例如:
我有一个元组t
定义如下:
constexpr auto t = std::tuple(1, 2, 3, 4);
我想将其复制到另一个元组。但是,我想跳过第n个元素。假设在这种情况下,我要跳过的第n个元素为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)>());
}
但是,我没有删除第n个元素,而是将其设置为0。
理想情况下,我将在函数中更改return参数以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,则第n个元素(这里也是第一个元素)仍将在新元组中使用。另外,它甚至不会编译,因为第二条语句存在问题:
if constexpr(sizeof...(tail) - 1 == N)
我在这里想念什么?如何复制元组并在复制过程中跳过其元素之一?
我正在使用C ++ 17,我需要在编译时评估函数。
关于什么
return std::tuple_cat( foo<is, N>::func(std::get<is>(tp)) ...);
foo
具有以下专门化的结构在哪里?
template <std::size_t, std::size_t>
struct foo
{
template <typename T>
static auto func (T const & t)
{ return std::make_tuple(t); }
}
template <std::size_t N>
struct foo<N, N>
{
template <typename T>
static std::tuple<> func (T const &)
{ return {}; }
}
(警告:代码未经测试)。
这几乎是您的三元运算符的主意,但没有在两侧匹配类型的问题:仅实例化正确的类型。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句