定义可以执行对象方法和独立函数的函数时出现问题

Problem with defining a function which can execute object's methods and standalone functions

本文关键字:函数 问题 独立 执行 对象 方法 定义      更新时间:2023-10-16

我坚持定义一个函数,该函数可以使用模板执行独立的函数和对象方法。

template <typename Func, typename ...Args>
void execute(Func&& f, Args&&... args)
{
cout << "execute1" << endl;
std::forward<decltype(f)>(f)(std::forward<Args>(args)...);
}
template <typename Func, typename Obj, typename ...Args>
void execute(Func&& fun, Obj&& obj, Args&&... args)
{
cout << "execute2" << endl;
std::forward<decltype(obj)>(obj).fun(args...);
}
void fun()
{
cout << "in fun()" << endl;
}
class A
{
public:
void method()
{
cout << "in method()" << endl;
}
};
int main()
{
A a;
execute(fun);
execute(&A::method, std::move(a));
return 0;
}

现在,如果我传递 fun() 函数作为参数,它会通过第一次重载正确执行。

当我传递对象的方法和应该调用此方法的对象时,出现以下错误:

main.cpp: In instantiation of ‘void execute(Func&&, Obj&&, Args&& ...) [with Func = void (A::*)(); Obj = A; Args = {}]’:
main.cpp:20:38: error: ‘class A’ has no member named ‘fun’
std::forward<decltype(obj)>(obj).fun(args...);

我是模板新手,所以请原谅:)

几个问题:

两个重载对于execute(&A::method, std::move(a));都是可行的,第一个是更好的匹配。所以你的错误。

您可以使用 SFINAE 丢弃无效重载:

template <typename Func, typename ...Args>
auto execute(Func&& f, Args&&... args)
-> decltype(std::forward<Func>(f)(std::forward<Args>(args)...))
{
cout << "execute1" << endl;
std::forward<Func>(f)(std::forward<Args>(args)...);
}
template <typename Func, typename Obj, typename ...Args>
auto execute(Func&& fun, Obj&& obj, Args&&... args)
-> decltype((std::forward<Obj>(obj).*fun)(std::forward<Args>(args)...);)
{
cout << "execute2" << endl;
(std::forward<Obj>(obj).*fun)(std::forward<Args>(args)...);
}

您可能会注意到,我还修复了使用方法指针(.*->*)进行方法调用的语法。 第二个重载仅处理引用对象,而不处理(智能)指针。将添加其他重载来处理这个问题。

在 std 中,我们有std::invoke(C++17) 这样做,甚至更多。