转发成员函数参数
事情很简单,我想转发成员函数的调用及其参数,如以下代码段所述。
请注意,这不是这个问题的重复,也不是这个。
#include <iostream>
#include <functional>
template<class Function, class ... Args>
auto forward_args(Function&& f, Args&& ... args)
{
return f(std::forward<Args>(args)...);
}
int f(int i) { return i; }
struct A {
int get(int i) const { return i; }
};
int main()
{
std::cout << forward_args(f, 2) << std::endl; //ok
A a;
//std::cout << forward_args(&A::get, a, 2) << std::endl; //ko
static auto wrong_wrapper = &A::get;
//std::cout << forward_args(wrong_wrapper, a, 2) << std::endl; //ko again
static std::function<int (const A&, int)> wrapper = &A::get;
std::cout << forward_args(wrapper, a, 2) << std::endl;
}
main函数中的注释行无法编译 (g++ 10.2.0 -- error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘f (...)’, e.g. ‘(... ->* f) (...)’)
我不太明白编译器想告诉我什么,考虑到最后一个带有std::function包装器的cll确实有效。而且,除了修复代码之外,我还想知道为什么它不起作用。
回答
通过指向成员的指针调用成员函数仍然需要this指针,就像通常的(直接)调用一样。简单地说,你可以A::get()像这样成功调用
static auto wrong_wrapper = &A::get;
(a.*wrong_wrapper)(2);
但是你在forward_args实例化后得到的是
A::get(a, 2);
这在本质上不是正确的语法。
解决方案
正如评论部分已经说过的那样,如果允许您使用 C++17,请使用std::invoke. 如果不是,您可以使用 来解决它std::reference_wrapper,它接受任何可调用类型。
template<class Function, class ... Args>
auto forward_args(Function f, Args&& ... args)
{
return std::ref(f)(std::forward<Args>(args)...);
}
我不在f这里转发,因为std::reference_wrapper要求传递的对象不是 rval。
更新:
forward_args如果您使用 C++11,请不要忘记指定尾随返回类型
template<class Function, class ... Args>
auto forward_args(Function f, Args&& ... args) -> decltype(std::ref(f)(std::forward<Args>(args)...))
{
return std::ref(f)(std::forward<Args>(args)...);
}