【发布时间】:2023-02-21 00:38:48
【问题描述】:
说我有这两种方法:
// Overload 1
template <typename T, typename... Args>
void Foo(Args&&... args)
{
// do things with T, args...
}
// Overload 2
template <typename T, typename... Args>
void Foo(std::function<void(T&)> && func, Args&&... args)
{
// do things with func, T, args...
}
我试图这样称呼它:
Foo<MyClass>([](auto& my_class){
// do things with my_class
});
我打算调用 Overload 2。问题是它实际上解决了 Overload 1。我可以通过显式 std::function<void(MyClass&)> func 变量并在删除 std::function 上的 r 值后传递它来使其工作,但我'我想尝试让它与 lambda 一起工作。如果我提供另一个参数,它也可以与 lambda 一起使用,但我不会有另一个参数给它。
带有 std::function 参数的方法不应该更专业吗?为什么选择错误的重载?我已阅读 overload resolution 规则,但没有看到/理解该行为的原因。
鉴于它使用显式参数,我假设它与从 lambda 到 std::function 的隐式转换有关,该转换的排名低于仅使用 Args,即使它更专业.我能做些什么来保留 lambda?
【问题讨论】:
-
您的问题是 lambda 表达式不会导致
std::funtion。它会导致具有重载的operator ()的未命名类类型。 -
(1) 是更接近的匹配,因为它不需要将 lambda 转换为
std::function。 -
与往常一样,问题在于采用
std::function参数。永远不要那样做。只需将可调用对象视为其类型即可。 -
我添加了一个新的模板参数
typename Func并将std::function替换为Func。但是,现在我无法将enum之类的东西传递给Foo以解决超载 1。
标签: c++ variadic-functions overload-resolution