如何从 std::tuple 中删除元素?
How to drop element from std::tuple?
给定一个
struct A{}; struct B{}; struct C{};
std::tuple<A,B,C> tabc;
如何从中删除第二个元素 B
以获得 tuple<A,C>
,如
std::tuple<A,C> tac = drop<B>(tabc);
或相同
std::tuple<A,C> tac = drop<1>(tabc);
我假设这会产生一个带有元素副本的新类型。
std::tuple 是不可变的,您不能删除或移除。
std::tuple is a fixed-size collection of heterogeneous values
根据您的 C++ 品味,使用 std::get(std::tuple) and std::make_tuple
创建一个新元组
auto tac = std::make_tuple(std::get<0>(tabc), std::get<2>(tabc));
或者使用 C++14
auto tac = std::make_tuple(std::get<A>(tabc), std::get<C>(tabc));
如果您知道元组中对象 A 和 C 的索引,那么您可以使用带有模板参数 size_t
的函数 std::get
。否则,您可以使用带有类型模板参数的函数 std::get
。
这是一个演示程序
#include <iostream>
#include <tuple>
struct A
{
};
struct B
{
};
struct C
{
};
int main()
{
auto t1 = std::make_tuple( A(), B(), C() );
auto t2 = std::make_tuple( std::get<A>( t1 ), std::get<C>( t1 ) );
auto t3 = std::make_tuple( std::get<0>( t1 ), std::get<2>( t1 ) );
return 0;
}
查看这个如何制作子元组的答案:
Creating a sub-tuple starting from a std::tuple<some_types...>
阅读。通过制作子例程,您可以制作 drop
的通用版本:
template<size_t index, typename Tuple>
auto Drop(const Tuple& t)
{
return std::tuple_cat(
subtuple_v2<0,index>(t),
subtuple_v2<index+1, std::tuple_size<Tuple>::value>(t));
}
其中 subtuple_v2<a,b>
是 post 的扩展版本,它从索引 a
到 b
生成子元组。
这相当简单,足以使用元编程技术进行编码:
template<size_t drop, size_t ...ixs>
constexpr auto calc_drop_sequence_dropper(std::index_sequence<ixs...>)
{
return std::index_sequence<(ixs >= drop ? ixs + 1 : ixs)...>{};
}
//Creates a monotonically increasing sequence on the range [0, `count`), except
//that `drop` will not appear.
template<size_t count, size_t drop>
constexpr auto calc_drop_copy_sequence()
{
static_assert(count > 0, "You cannot pass an empty sequence.");
static_assert(drop < count, "The drop index must be less than the count.");
constexpr auto count_sequence = std::make_index_sequence<count - 1>();
return calc_drop_sequence_dropper<drop>(count_sequence);
}
template<typename Tuple, size_t ...ixs>
constexpr auto copy_move_tuple_by_sequence(Tuple &&tpl, std::index_sequence<ixs...>)
{
using TplType = std::remove_reference_t<Tuple>;
return std::tuple<std::tuple_element_t<ixs, TplType>...>(
std::get<ixs>(std::forward<Tuple>(tpl))...);
}
template<size_t drop, typename Tuple>
constexpr auto drop_tuple_element(Tuple &&tpl)
{
using TplType = std::remove_reference_t<Tuple>;
constexpr size_t tpl_size = std::tuple_size<TplType>::value;
constexpr auto copy_seq = calc_drop_copy_sequence<tpl_size, drop>();
return copy_move_tuple_by_sequence(std::forward<Tuple>(tpl), copy_seq);
}
主要功能是 drop_tuple_element
,它执行您假设的 drop
功能的功能。当然,如果您要删除多个元素,您希望一次性删除它们,而不是单独删除。所以你需要修改代码。
给定一个
struct A{}; struct B{}; struct C{};
std::tuple<A,B,C> tabc;
如何从中删除第二个元素 B
以获得 tuple<A,C>
,如
std::tuple<A,C> tac = drop<B>(tabc);
或相同
std::tuple<A,C> tac = drop<1>(tabc);
我假设这会产生一个带有元素副本的新类型。
std::tuple 是不可变的,您不能删除或移除。
std::tuple is a fixed-size collection of heterogeneous values
根据您的 C++ 品味,使用 std::get(std::tuple) and std::make_tuple
创建一个新元组auto tac = std::make_tuple(std::get<0>(tabc), std::get<2>(tabc));
或者使用 C++14
auto tac = std::make_tuple(std::get<A>(tabc), std::get<C>(tabc));
如果您知道元组中对象 A 和 C 的索引,那么您可以使用带有模板参数 size_t
的函数 std::get
。否则,您可以使用带有类型模板参数的函数 std::get
。
这是一个演示程序
#include <iostream>
#include <tuple>
struct A
{
};
struct B
{
};
struct C
{
};
int main()
{
auto t1 = std::make_tuple( A(), B(), C() );
auto t2 = std::make_tuple( std::get<A>( t1 ), std::get<C>( t1 ) );
auto t3 = std::make_tuple( std::get<0>( t1 ), std::get<2>( t1 ) );
return 0;
}
查看这个如何制作子元组的答案:
Creating a sub-tuple starting from a std::tuple<some_types...>
阅读。通过制作子例程,您可以制作 drop
的通用版本:
template<size_t index, typename Tuple>
auto Drop(const Tuple& t)
{
return std::tuple_cat(
subtuple_v2<0,index>(t),
subtuple_v2<index+1, std::tuple_size<Tuple>::value>(t));
}
其中 subtuple_v2<a,b>
是 post 的扩展版本,它从索引 a
到 b
生成子元组。
这相当简单,足以使用元编程技术进行编码:
template<size_t drop, size_t ...ixs>
constexpr auto calc_drop_sequence_dropper(std::index_sequence<ixs...>)
{
return std::index_sequence<(ixs >= drop ? ixs + 1 : ixs)...>{};
}
//Creates a monotonically increasing sequence on the range [0, `count`), except
//that `drop` will not appear.
template<size_t count, size_t drop>
constexpr auto calc_drop_copy_sequence()
{
static_assert(count > 0, "You cannot pass an empty sequence.");
static_assert(drop < count, "The drop index must be less than the count.");
constexpr auto count_sequence = std::make_index_sequence<count - 1>();
return calc_drop_sequence_dropper<drop>(count_sequence);
}
template<typename Tuple, size_t ...ixs>
constexpr auto copy_move_tuple_by_sequence(Tuple &&tpl, std::index_sequence<ixs...>)
{
using TplType = std::remove_reference_t<Tuple>;
return std::tuple<std::tuple_element_t<ixs, TplType>...>(
std::get<ixs>(std::forward<Tuple>(tpl))...);
}
template<size_t drop, typename Tuple>
constexpr auto drop_tuple_element(Tuple &&tpl)
{
using TplType = std::remove_reference_t<Tuple>;
constexpr size_t tpl_size = std::tuple_size<TplType>::value;
constexpr auto copy_seq = calc_drop_copy_sequence<tpl_size, drop>();
return copy_move_tuple_by_sequence(std::forward<Tuple>(tpl), copy_seq);
}
主要功能是 drop_tuple_element
,它执行您假设的 drop
功能的功能。当然,如果您要删除多个元素,您希望一次性删除它们,而不是单独删除。所以你需要修改代码。