如何提取可变参数函数的一组选定参数并使用它们来调用另一个函数

Fab*_*bio 13 c++ c++11

我有一个可变函数动物园,它带有N个参数,其中N在编译时是已知的(它是包含该函数的类的模板参数).

template <int N>
struct B
{
    template <typename... Args>
    static void zoo(Args... args)
    {
        static_assert(size of...(args) == N, "");
       // do something
    }
};
Run Code Online (Sandbox Code Playgroud)

我有另一个可变函数foo,它接受M个参数,其中M> N并且在编译时是已知的(它是包含该函数的类的模板参数).我有一个静态index_array,其中包含我要传递给zoofoo参数的索引.

foo的主体我想调用zoo传递foo参数的选定子集.

做这个的最好方式是什么?理想情况下实现完美的内联,即所有内容都只编译成一条没有函数指针间接指令的指令?

template<int...I>
struct indices
{
    static constexpr int N = sizeof...(I);
};

template <int M, typename...X>
struct A
{
    // here I am simplifying, in reality IS will be built at compile time based on X
    typedef indices<0,2,3> IS;

    template <typename... Args>
    static void foo(Args... args)
    {
        static_assert(size of...(args) == M, "");
       // do some magic to achieve the function call described in pseudo-code
       // B<IS::N>::zoo(args(IS(0),IS(1),IS(2)))
       // ideally this should be perfectly inlined to just have the call above
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意上面的代码是我的问题的简化,旨在说明问题.

编辑:如下所述,我描述了用例:我正在使用基于模板的库来驱动微控制器引脚.微控制器有几个端口(可以作为存储器中的字节访问),每个端口最多有8个引脚(位).A类是通过模板参数X的一组引脚,其中每个引脚都定义为Pin.B类操纵同一端口上的所有引脚.A :: foo是一个修改某些引脚的函数,其参数的顺序与X模板参数包中指定引脚的顺序相同.foo需要通过端口对参数进行分组并调度到代表各个端口的B类,其中所有参数都融合并在单个指令中写入控制器.

Rum*_*rak 7

您可以创建一个帮助器来提取nth_arg如下:

template <int I>
struct ignore
{
  template <typename T>
  ignore(T&&) // This constructor accepts anything
  {
  }
};

template <typename T>
struct nth_arg;

template <size_t... DropIndexes>
struct nth_arg<std::integer_sequence<size_t, DropIndexes...>>
{
  template <typename Arg, typename... Rest>
  static decltype(auto) get(ignore<DropIndexes>..., // ignore args 0...n-1
                            Arg&& arg,
                            Rest&&...) // also ignore the rest
  {
    return std::forward<Arg>(arg); // return nth arg
  }
};
Run Code Online (Sandbox Code Playgroud)

然后打电话

template <int... Is, typename... Args>
static void call_zoo(indices<Is...>, Args&&... args)
{
  B<sizeof...(Is)>::zoo(nth_arg<std::make_index_sequence<Is>>::get(
      std::forward<Args>(args)...)...);
}

template <int M>
struct A
{
  typedef indices<0, 2, 3> IS;

  template <typename... Args>
  static void foo(Args... args)
  {
    static_assert(sizeof...(args) == M, "");
    call_zoo(IS{}, std::forward<Args>(args)...);
  }
};
Run Code Online (Sandbox Code Playgroud)

如果你正在使用C++ 11,你可以轻松地自己动手integer_sequence.


T.C*_*.C. 6

将参数打包到引用元组中,然后使用std::get索引和包扩展来检索它们.

template<class Tuple, int... Is>
static void magic(Tuple&& args, indices<Is...>){
    B<IS::N>::zoo(std::get<Is>(std::forward<Tuple>(args))...);
}

template <typename... Args>
static void foo(Args... args)
{
    static_assert(sizeof...(args) == M, "");
    magic(std::forward_as_tuple(args...), IS{});
}
Run Code Online (Sandbox Code Playgroud)

(您可能想要foo转发参考.)