我有一个可变参数函数 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,其中包含要传递给 zoo 的 foo 参数的索引。
从 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/