【问题标题】:Get a new tuple containing all but first element of a tuple获取一个新元组,其中包含元组的除第一个元素之外的所有元素
【发布时间】:2018-11-27 15:39:10
【问题描述】:

给定一个std::tuple<A, B, ...> foo,C++14 中是否有任何通用(模板化)函数或技术来获得一个新元组std::tuple<B, ...> bar,它包含除foo 的第一个元素之外的所有元素?或者,也许是 Boost 中的一些东西?

我已经使用参数包和一些模板元编程编写了一个辅助函数来执行此操作,但我很想把所有这些东西都扔掉!

这是我目前正在做的事情。我定义了一个辅助函数unshift_tuple(),它返回一个元组,其中包含传递给函数的元组的第一个元素以外的所有元素。 unshift_tuple() 的实现使用了一个辅助函数unshift_tuple_with_indices(),它接受一个包含要提取的元组索引的参数包; sequential_integer_list 帮助器类型用于使用模板元编程生成适当的索引列表参数包。丑!

#include <tuple>

template <size_t... Integers>
struct integer_list {};

template <size_t N, size_t... Args>
struct sequential_integer_list : sequential_integer_list<N - 1, N - 1, Args...> {};

template <size_t... Args>
struct sequential_integer_list<0, Args...> { typedef integer_list<Args...> type; };

template <typename FirstElement, typename... Elements, size_t... Indices>
static std::tuple<Elements...> unshift_tuple_with_indices(
    const std::tuple<FirstElement, Elements...>& tuple,
    integer_list<Indices...> index_type)
{
    return std::make_tuple(std::get<Indices + 1>(tuple)...);
}

template <typename FirstElement, typename... Elements>
std::tuple<Elements...>
unshift_tuple(const std::tuple<FirstElement, Elements...>& tuple)
{
    return unshift_tuple_with_indices(tuple,
        typename sequential_integer_list<sizeof...(Elements)>::type());
}

int main(int, char *[])
{
    std::tuple<int, std::string, double> foo(42, "hello", 3.14);

    std::tuple<std::string, double> bar = unshift_tuple(foo);
}

明确地说,这段代码运行良好。我只是非常希望删除它(或它的任何部分)并使用内置的东西,如果可能的话!


编辑

Jarod42 指出 C++14 中存在 std::integer_list,这将实现简化为:

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

template <typename T1, typename... T, size_t... Indices>
std::tuple<T...> unshift_tuple_with_indices(
    const std::tuple<T1, T...>& tuple, std::index_sequence<Indices...>)
{
    return std::make_tuple(std::get<Indices + 1>(tuple)...);
}

template <typename T1, typename... T> std::tuple<T...>
unshift_tuple(const std::tuple<T1, T...>& tuple)
{
    return unshift_tuple_with_indices(tuple,
        std::make_index_sequence<sizeof...(T)>());
}

【问题讨论】:

  • codereview.stackexchange.com 是否有关于工作代码的反馈请求。
  • std::index_sequence 在 C++14 中可用。
  • @FrançoisAndrieux 没错,虽然我不是在寻找对现有代码的反馈(尽管这是受欢迎的),而是在寻找标准库技术来做同样的事情。我将工作代码显示为 MCVE,以清楚地说明我正在尝试做什么。
  • 用 C++14 编写的看起来并不难看:Demo
  • How to split a tuple?的可能重复

标签: c++ tuples c++14 template-meta-programming


【解决方案1】:

在 C++14 中,有一个名为 std::integer_sequence 的类模板,其作用类似于您对 sequential_integer_list 所做的事情。您可以在here 中找到参考。

根据您的代码,可以减少并依赖纯元编程。

template <typename First, typename ... Elements>
struct unshift_tuple_impl
{
    using type = std::tuple<Elements...>;
};

template <typename First, typename ... Elements>
std::tuple<Elements...>
unshift_tuple(const std::tuple<First, Elements...>& tuple)
{
    return typename unshift_tuple_impl<First, Elements...>::type{};
}

【讨论】:

  • 这似乎创建了一个 empty 元组,而不复制传递给unshift_tuple()tuple 的元素,但除此之外,该技术似乎是合理的。谢谢!
  • 相当于template &lt;typename T, typename ... Ts&gt; std::tuple&lt;Ts...&gt; unshift_tuple(const std::tuple&lt;T, Ts...&gt;&amp;) { return {};}
【解决方案2】:

在 C++17 中,您可能会这样做

template <typename T1, typename... Ts>
std::tuple<Ts...> unshift_tuple(const std::tuple<T1, Ts...>& tuple)
{
    return std::apply([](auto&&, const auto&... args) {return std::tie(args...);}, tuple);
}

std::apply 可能在 C++14 中实现。

否则,在 C++14 中,std::index_sequence 避免了编写您自己的版本,从而将您的代码简化为:

namespace details
{
    template <typename Tuple, size_t... Indices>
    auto unshift_tuple_with_indices(
        const Tuple& tuple,
        std::index_sequence<Indices...> index_type)
    {
        return std::make_tuple(std::get<Indices + 1>(tuple)...);
    }
}

template <typename T, typename... Ts>
std::tuple<Ts...> unshift_tuple(const std::tuple<T, Ts...>& tuple)
{
    return details::unshift_tuple_with_indices(tuple, std::index_sequence_for<Ts...>());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多