【问题标题】:Overload resolution with parameter pack带参数包的过载解决方案
【发布时间】: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&lt;void(MyClass&amp;)&gt; 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


【解决方案1】:

lambda 不是std::function,所以第一次重载是更好的匹配。

我能做些什么来保留 lambda?

使用常规模板参数而不是std::function

template <typename T, typename F, typename... Args>
requires (std::invocable<F, T&>)
void Foo(F&& func, Args&&... args)
{
    // ...
}

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2011-02-26
    相关资源
    最近更新 更多