压入和弹出 std::tuple 的第一个元素

Pushing and popping the first element of a std::tuple

我正在用这种方式用可变数量的参数(和不同类型)在 C++ 中编写一个函数

template<typename ...Ts>
void myFunction(Ts ...args)
{
    //create std::tuple to access and manipulate single elements of the pack
    auto myTuple = std::make_tuple(args...);    

    //do stuff

    return;
}

我想做的是从元组中压入和弹出元素,尤其是第一个元素...类似

//remove the first element of the tuple thereby decreasing its size by one
myTuple.pop_front()

//add addThis as the first element of the tuple thereby increasing its size by one
myTuple.push_front(addThis)

这可能吗?

您不能通过添加元素来 'lengthen' 元组 - 这不是元组所代表的。元组的点是组成它的不同值之间的绑定连接,如 'firstname'、'lastname'、'phone'.

您似乎想要的通过使用向量更容易实现 - 您可以轻松地向它添加和删除元素 - 它的大小可以根据需要任意更改。

std::tuple 的长度和类型在编译时确定。没有 运行 时间弹出或推送是可能的。您可以使用 std::vector 来提供 运行 次修改。

向量的数据类型可以是 std::variant (C++17) 或 boost::variant。两种类型都在编译时获取支持的类型列表,并且可以填充任何匹配类型的值。

或者,您可以使用 std::any(也是 C++17)或 boost::any 来存储 any 类型,但具有不同的访问语义。

typedef boost::variant<int, std::string, double> value;
std::vector<value> data;
data.push_back(value(42));
data.psuh_back(value(3.14));

你可以这样做

template <typename T, typename Tuple>
auto push_front(const T& t, const Tuple& tuple)
{
    return std::tuple_cat(std::make_tuple(t), tuple);
}

template <typename Tuple, std::size_t ... Is>
auto pop_front_impl(const Tuple& tuple, std::index_sequence<Is...>)
{
    return std::make_tuple(std::get<1 + Is>(tuple)...);
}

template <typename Tuple>
auto pop_front(const Tuple& tuple)
{
    return pop_front_impl(tuple,
                          std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
}

Demo

请注意,它非常基础,不处理引用元组或 const 限定类型的元组,但它可能就足够了。

使用通用的 lambda 表达式,你可以做得非常优雅:

template<typename Tuple>
constexpr auto pop_front(Tuple tuple) {
    static_assert(std::tuple_size<Tuple>::value > 0, "Cannot pop from an empty tuple");
    return std::apply(
        [](auto, auto... rest) { return std::make_tuple(rest...); }, 
        tuple);
}