当前位置: 首页 > 知识库问答 >
问题:

std::元组获得除了最后一个元素之外的所有内容

云开诚
2023-03-14

我试图返回所有元素,除了std::tuple中的最后一个元素,如果tuple中只有两个元素,则返回第一个。由于std::tuple有很多编译时工具,所以应该可以使用双返回类型。以下是我目前掌握的情况:

// Behavior
// init(std::make_tuple(1,2)) = 1
// init(std::make_tuple(1,2,3)) = (1,2)

// First case
template<class T1, class T2>
inline static T1 init(Tuple<T1, T2> t) {
    return std::get<0>(t);
}

// Second case
template<class ...Args, class S = std::make_index_sequence<sizeof...(Args) - 1>>
inline static decltype(auto) init(Tuple<Args...> t) {
    return std::apply([](const auto &item...) {
        return std::tuple_cat(std::make_tuple(std::get<S>) ... std::tuple<>);
    }, t);
}

如果我能以c 17友好的方式来做这件事,那就太好了。我在上述实现中遇到以下错误:

/元组。cpp:36:55:错误:包扩展不包含任何未扩展的参数
返回std::tuple_cat(std::make_tuple(std::get)。。。std::tuple

~~~~~~~~~~~~~~~~~~~~~~~~~~~^
1生成错误。

共有2个答案

孟祯
2023-03-14

其想法是实现一个helper函数,该函数将包含要复制的源元组项的索引列表:

#include <tuple>
#include <utility>
#include <cstddef>

template<typename x_Tuple, ::std::size_t... x_index> auto
make_tuple_helper(x_Tuple const & other, ::std::index_sequence<x_index...>)
{
    return ::std::make_tuple(::std::get<x_index>(other)...);
}

template<typename... x_Field> inline auto
cut_last_item(::std::tuple<x_Field...> const & other)
{
    return make_tuple_helper(other, ::std::make_index_sequence<sizeof...(x_Field) - ::std::size_t{1}>{});
}

template<> inline auto
cut_last_item(::std::tuple<> const & other)
{
    return other;
}

int main()
{
    ::std::tuple<int, short, float, double> t4{};
    ::std::tuple<int, short, float> t3{cut_last_item(t4)};
    ::std::tuple<int, short> t2{cut_last_item(t3)};
    ::std::tuple<int> t1{cut_last_item(t2)};
    ::std::tuple<> t0{cut_last_item(t1)};
    ::std::tuple<> t00{cut_last_item(t0)};
}

在线编译器

赵镜
2023-03-14

与您的问题无关,但模板意味着内联,您不需要静态。实际上,我认为使用static会违反ODR。你为什么用它们?您还可以使函数constexpr。进一步的改进是使用(转发)引用和std::forward_as_tuple。以下是一个基本实现:

template <class... Args, std::size_t... Is>
constexpr auto init_helper(std::tuple<Args...> tp, std::index_sequence<Is...>)
{
    return std::tuple{std::get<Is>(tp)...};
}

template <class... Args>
constexpr auto init(std::tuple<Args...> tp)
{
    return init_helper(tp, std::make_index_sequence<sizeof...(Args) - 1>{});
}
auto test()
{
    static_assert(init(std::tuple{1})       == std::tuple{});
    static_assert(init(std::tuple{1, 2})    == std::tuple{1});
    static_assert(init(std::tuple{1, 2, 3}) == std::tuple{1, 2});
}

你在评论中说,你想看看是否有可能init(std::tuple{1,2})直接返回值,而不是一个值的元组。请注意,我不建议这样做,因为这会使函数的行为不一致。是的,这是可能的。而C17则使这一点非常干净:

template <class... Args>
constexpr auto init(std::tuple<Args...> tp)
{
    if constexpr (sizeof...(Args) == 2)
        return std::get<0>(tp);
    else
        return init_helper(tp, std::make_index_sequence<sizeof...(Args) - 1>{});
}

auto test()
{
    static_assert(init(std::tuple{1})       == std::tuple{});
    static_assert(init(std::tuple{1, 2})    == 1);
    static_assert(init(std::tuple{1, 2, 3}) == std::tuple{1, 2});
}
 类似资料:
  • 假设我有这样的html: 我只想获得之前的 。有没有办法用JSOUP做到这一点呢?我知道我可以把所有的宠物都弄成这样: 但这也包括额外的宠物。我想知道我是只能选择上面的宠物还是只是删除下面的宠物然后使用那个代码?

  • 我试图将JSON中的数据保存到数组中,但最后一项覆盖了前面的值。我有一个用于存储学生信息的学生类和一个用于存储学生技能的技能类。 学生班 我在技能数组上循环,并将其附加到我的数组,并打印最后一个附加的值,正确的值被打印出来。 在循环中,从上述

  • 问题内容: 如何使用CSS3选择器选择除最后一个子项之外的所有子项? 例如,只得到最后一个孩子第N个子项(1) 是的。。 问题答案: 您可以使用否定伪类:not()对:last-child伪类。正在被引入CSS选择器3级,它不适用于IE8或更低版本:

  • 为了缩短一些名字,但仍然保持它们的可读性,我想删除字符串中的所有元音,除了第一个和最后一个。例如,我希望“明尼苏达”变成“明斯塔”。 我已经尝试使用Perl的零宽度查找正则表达式语法,如下所示: 然而,尽管这适当地处理了第一个元音,但它删除了最后一个元音。为了解决这个问题,我试着保留最后一个元音,如下所示: 这也不起作用,大概是因为“$”将整个正则表达式锚定在字符串的末尾。 当然,我可以查找第一个

  • 问题内容: 提取切片的最后一个元素的Go方法是什么? 上面的解决方案有效,但看起来很尴尬。 问题答案: 仅读取切片的最后一个元素: 要删除它: 参见此页面有关切片技巧

  • 本文向大家介绍js获取数组的最后一个元素,包括了js获取数组的最后一个元素的使用技巧和注意事项,需要的朋友参考一下 在js里面如何获取一个数组的最后一个元素呢?这里总结了两种方法,有需要的朋友可以看看。 (1)js内置pop方法 pop() 方法用于删除并返回数组的最后一个元素,注意这里在获取了数组的最后一个元素的同时也将原数组的最后一个元素给删除了。如果数组已经为空,则该方法不改变数组,并返回