根据我之前的问题Variadic template, function as argument
我最终得到了一个简单的类,但是如何使用std :: invoke或其他方法调用Tester :: test作为参数? http://en.cppreference.com/w/cpp/utility/functional/invoke#Example提供的示例对我没有多大帮助,我尝试了很多不同的方法来使用std :: invoke。
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test(t.simple, 3); // how do you modify this line such that the code compiles?
}
谢谢!
答案 0 :(得分:5)
一种方法是修改class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
成员函数的定义,如下所示:
test()
然后我们可以将一个成员函数指针传递给int main()
{
Tester t;
std::cout << t.test(&Tester::simple, t, 3);
}
,其中应该调用该方法的实例作为第二个参数,然后是函数参数本身:
std::invoke
这可行的原因是因为std::invoke(ptr-to-member, instance, args...);
有一个special overload for pointers-to-members,所以
(instance.*ptr-to-member)(args...);
被称为
s3
这正是我们在这种情况下想要的。
答案 1 :(得分:3)
注意,std::invoke
是 C ++ 17 的一部分。如果它不可用,可以实现test
函数,以便它接受指向成员函数的指针和类的实例:
template<typename F, typename T, typename... Args>
decltype(auto) test(F f, T&& t, Args&&... args) {
return (std::forward<T>(t).*f)(std::forward<Args>(args)...);
}
现在test
接受一个指向成员函数的指针作为第一个参数,一个类的实例作为第二个参数和任意数量的附加参数。
然后test
可能被称为:
Tester t;
std::cout << t.test(&Tester::simple, t, 42);
答案 2 :(得分:1)
再提一个可能性,你可以将成员函数调用包装在lambda中并捕获实例t
。在C ++ 14中,我们可以使用通用lambda,因此我们不必明确指定参数。
#include <iostream>
#include <utility>
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test([&t] (auto&&... args) { return t.simple(std::forward<decltype(args)>(args)...); }, 3);
}