你能在初始化列表中反转参数扩展的顺序吗?
我正在编写一种自定义解释语言,它使用 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,如果它有任何不同的话)。
回答
之后你可能会反转元组
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);
}
演示