【问题标题】:Can you invert the order of argument-expansion in an initializer-list?你能颠倒初始化列表中参数扩展的顺序吗?
【发布时间】:2021-05-23 14:07:33
【问题描述】:

我正在编写一种自定义解释语言,它使用 LIFO 堆栈进行数据操作。在两个地方,我需要能够从存储在堆栈中的值构造一个元组。原则上,这段代码应该是这样的:

template<typename... Args>
[[nodiscard]] inline std::tuple<Args...> popTupleFromStack(Stack& stack)
{
    return { stack.Pop<Args>()... };
}

但是,堆栈的 LIFO 排序存在一个基本问题:初始化列表顺序规定调用从左到右发生,这意味着它实际上会尝试以完全相反的顺序弹出元素.有什么简单的方法可以颠倒这个顺序吗?

我知道折叠表达式允许您指定左折叠或右折叠,但是当您需要使用结果初始化对象时,您似乎不能使用折叠表达式。

我的结局是手动为元组中的潜在参数数量指定重载:

template<typename Arg0>
[[nodiscard]] inline std::tuple<Arg0> popStackTuple(Stack& stack)
{
    return { stack.Pop<Arg0>() };
}

template<typename Arg0, typename Arg1>
[[nodiscard]] inline std::tuple<Arg0, Arg1> popStackTuple(Stack& stack)
{
    Arg1 arg1 = stack.Pop<Arg1>();
    Arg0 arg0 = stack.Pop<Arg0>();

    return { arg0, arg1 };
}

但这显然限制了我可以支持的参数数量,和/或导致大量“不必要的”代码。而现代 C++ 似乎无法完成这样一件小事(我拥有一切,包括 C++20,如果有什么不同的话,我可以随意使用)。

【问题讨论】:

  • 为什么不使用dequeue 而不是stack
  • @πάνταῥεῖ 堆栈不仅仅包含该元组中的元素。正如我所说,我几乎正在为基于字节码的语言(想想 Java)编写解释器,当我调用 popStackTuple 时,元组元素下方是大量其他数据,所以我不能只使用 PopFront。

标签: c++ variadic-templates


【解决方案1】:

之后你可能会反转元组

template <std::size_t ... Is, typename Tuple>
auto reverse_tuple_impl(std::index_sequence<Is...>, Tuple& tuple)
{
    using res_type = std::tuple<std::tuple_element_t<sizeof...(Is) - 1 - Is, std::decay_t<Tuple>>...>;
Is, std::decay_t<Tuple>>>;
    return res_type(std::get<sizeof...(Is) - 1 - Is>(tuple)...);
}

template <typename ... Ts>
auto reverse_tuple(std::tuple<Ts...>& tuple)
{
    return reverse_tuple_impl(std::index_sequence_for<Ts...>(), tuple);
}

Demo

【讨论】:

  • 这似乎可行。我只需要使用反参数顺序创建一个参数包,但我应该能够解决这个问题 - 所以我一定会尝试的!
【解决方案2】:

不是一个很大的改进,但是...如果你可以使用 C++20,所以模板 lambdas,你可以在 reverse_tuple() 中嵌入帮助函数

template <typename ... Ts>
auto reverse_tuple (std::tuple<Ts...> & tuple)
 {
   return [&]<std::size_t ... Is> (std::index_sequence<Is...>)
      { return std::make_tuple(std::get<sizeof...(Is)-1u-Is>(tuple)...); }
    (std::index_sequence_for<Ts...>{});
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2015-06-21
    • 2021-06-10
    相关资源
    最近更新 更多