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

标签 c++ c++11

我有一个可变参数函数 zoo,它接受 N 个参数,其中 N 在编译时是已知的(它是包含该函数的类的模板参数)。

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

我有另一个可变参数函数 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
    }
};

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

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

最佳答案

您可以像这样创建一个帮助器来提取 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
  }
};

然后调用

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)...);
  }
};

如果您使用的是 C++11,则可以轻松滚动自己的 integer_sequence

关于c++ - 如何提取可变参数函数的一组选定参数并使用它们调用另一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34836104/

相关文章:

c++ - 给定两个点,找到直线上的第三个点

c++ - 计算任意多边形的符号距离变换

c++ - 在我的 STL 容器映射中找不到特定键

c++ - system ("command") 产生错误;但它在直接从 Bash 提示符调用时有效

c++ - 如何将 vector 的 vector 传递给期望指向指针的(原始)指针的函数

c++ - 如何使用 cxx crate 调用 C++ 构造函数?

c++ - 在 C++ 中,我们如何使用执行函数的有效 X(Args...) 语法调用所有内容?

c++ - atomic_compare_exchange 大于而不是等于?

c++ - pthread_create 没有参数?

c++ - 异常的 C++ 链接器错误 - 'Defined in discarded section'