如何在C ++中生成一个从0到N的size_t包,其中N在编译时是已知的

时间:2018-05-12 15:13:46

标签: c++ variadic-templates

背景:我编写了一个带有一些可调用对象和一个元组的函数,并将元组解压缩到一个可以传递给函数的参数包中。您可以想象这涉及一些模板递归。但是,我的大多数同事都不是C ++的母语使用者,所以他们可以理解代码的问题,以及在错误调用函数时得到的编译错误。

如果我可以生成一个size_t的包,从0到大小为1的大小,我可以使用以下单行:

template <class Function, class... TupleArgs>
auto UnpackTuple(Function fn, std::tuple<TupleArgs>&& t)
-> decltype(fn(std::declval<TupleArgs>()...)) {
  return fn(std::get<{my size_t pack}>(std::forward(t))...);
}

有什么东西可以替代“我的size_t包”来完成这项工作吗?我知道如果我认为TupleArgs中的每种类型都是独一无二的,我可以一起破解一些东西,但这是一个非常具体的案例对我没用。

1 个答案:

答案 0 :(得分:3)

好像您正在寻找std::apply,这将完全符合您对UnpackTuple的要求。

话虽如此,如果你需要手动执行这个奇怪的原因(你可能不应该这样做,除非你想做一些完全不同于调用函数的东西), std::make_index_sequence 几乎你想要的东西(除了你的size_t序列被包装在一个类型中,所以你需要一个额外的间接级别)。您可以在cppreference.com上的std::apply示例实现中看到它是如何使用的: 1)

template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
{
    return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}

template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t)
{
    return apply_impl(
        std::forward<F>(f),
        std::forward<Tuple>(t),
        std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{}
    );
}

由于您提到您仍在使用C ++ 14,因此您需要使用正常的函数调用替换std::invoke(保留std::forward,但是,如果有人生气足以实现operator() &&

1)(CC-BY-SA 3.0)