This is fairly simple enough to code with meta-programming techniques:
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);
}
The principle function is drop_tuple_element
, which does what your hypothetical drop
function does. Of course, if you're dropping multiple elements, you want to drop them all at once, rather than individually. So you'll need to modify the code.