单个函数中有多个参数包? [英] Multiple parameter packs in a single function?

查看:60
本文介绍了单个函数中有多个参数包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个带有两个对象参数包的函数.有两个模板化的基类,我想将派生类的实例传递给此函数.考虑这个例子.

I'm trying to create a function that takes two parameter packs of objects. There are two templated base classes and I'd like to pass instances of derived classes to this function. Consider this example.

template <int N>
struct First {};

template <int N>
struct Second {};

// there are a few of these
struct FirstImpl : First<5> {};
struct SecondImpl : Second<7> {};

template <int... firstInts, int... secondInts>
void function(float f, First<firstInts> &... first, Second<secondInts> &... second) {
  // ...
}

我想做的就是这样调用 function

What I would like to do is call function like this

FirstImpl firstImpl;
OtherFirstImpl otherFirstImpl;
SecondImpl secondImpl;
OtherSecondImpl otherSecondImpl;
function(9.5f, firstImpl, otherFirstImpl, secondImpl, otherSecondImpl);

,但此示例无法编译.编译器似乎正在尝试将所有内容打包到第二个参数包中,并失败了,因为 FirstImpl 不能隐式转换为 Second< N> .

but this example won't compile. The compiler seems to be trying to pack everything into the second parameter pack and failing because FirstImpl can't be implicitly converted Second<N>.

我该如何解决?

推荐答案

让我们首先编写一个变量模板,该模板确定一个类型是否源自 First :

Let's first code a variable template which determines whether a type derives from First or not:

template <int N>
constexpr std::true_type is_first(First<N> const &) { return {}; }
template <int N>
constexpr std::false_type is_first(Second<N> const &) { return {}; }

template <class T>
constexpr bool is_first_v = decltype( is_first(std::declval<T>()) )::value;

还有一个结构 Split ,该结构收集 First Second 类型的索引:

And a struct Split which collects the indices of the First and Second types:

template <class, class, class, std::size_t I = 0> struct Split;

template <
    std::size_t... FirstInts,
    std::size_t... SecondInts,
    std::size_t N
>
struct Split<
    std::index_sequence<FirstInts...>,
    std::index_sequence<SecondInts...>,
    std::tuple<>,
    N
> {
    using firsts = std::index_sequence<FirstInts...>;
    using seconds = std::index_sequence<SecondInts...>;
};

template <
    std::size_t... FirstInts,
    std::size_t... SecondInts,
    std::size_t I, 
    typename T,
    typename... Tail
>
struct Split<
    std::index_sequence<FirstInts...>,
    std::index_sequence<SecondInts...>,
    std::tuple<T, Tail...>,
    I
> : std::conditional_t<
    is_first_v<T>,
    Split<std::index_sequence<FirstInts..., I>,
          std::index_sequence<SecondInts...>,
          std::tuple<Tail...>,
          I + 1
    >,
    Split<std::index_sequence<FirstInts...>,
          std::index_sequence<SecondInts..., I>,
          std::tuple<Tail...>,
          I + 1
    >
> {};

就像我在评论中告诉您的那样,在 First Second 中添加成员 value (或从

And like I told you in the comments, adding a member value to First and Second (or inheriting from std:integral_constant), this allows us to write the following:

template <std::size_t... FirstIdx, std::size_t... SecondIdx, typename Tuple>
void function_impl(float f, std::index_sequence<FirstIdx...>, std::index_sequence<SecondIdx...>, Tuple const & tup) {
    ((std::cout << "firstInts: ") << ... << std::get<FirstIdx>(tup).value) << '\n';
    ((std::cout << "secondInts: ") << ... << std::get<SecondIdx>(tup).value) << '\n';
    // your implementation
}

template <class... Args>
void function(float f, Args&&... args)  {
    using split = Split<std::index_sequence<>,std::index_sequence<>, std::tuple<std::decay_t<Args>...>>;
    function_impl(f, typename split::firsts{}, typename split::seconds{}, std::forward_as_tuple(args...));
}

演示

这篇关于单个函数中有多个参数包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆