【问题标题】:Variadic generic lambda and function overload可变泛型 lambda 和函数重载
【发布时间】:2020-06-05 21:51:39
【问题描述】:

我定义了以下可变参数泛型 lambda 和重载的 foo() 函数。

template <typename Lambda>
auto bar(Lambda&& lambda) {
    return [lambda = std::forward<Lambda>(lambda)](auto&& ...args) {
        return lambda(std::forward<decltype(args)>(args)...);
    };
}

void foo(std::function<void()>&& cmd, std::function<void()>&& callback) { std::cout << "void" << std::endl; }
void foo(std::function<bool()>&& cmd, std::function<bool()>&& callback) { std::cout << "bool" << std::endl; }

以下 3 个foo() 调用 print "void"。

int main()
{
    // 1
    foo(
        bar( []() {} ),
        bar( []() {} )
    );
    // 2
    foo(
        bar( []() { return true; } ),
        bar( []() {} )
    );
    // 3
    foo(
        bar( []() {} ),
        bar( []() { return true;} )
    );
    // 4) compiler error: foo is ambiguous
    // foo(
    //     bar( []() { return false; } ),
    //     bar( []() { return true; } )
    // );
}

能否请您帮我理解为什么它成功编译语句 1-3 但无法编译语句 4?

gcc 7.5.0

【问题讨论】:

  • 我很好奇bar 是否有任何目的。这个例子似乎没有任何区别。我想这会迫使任何函子有一个占位符返回类型,但我想不出这可能会有所不同。
  • 对,但是当我问这个问题时我并不清楚。

标签: c++ c++14


【解决方案1】:

std::function&lt;void()&gt; 可以存储任何返回类型(void 与否)的函数,其返回值被丢弃。

因此,在 (4) 中,两个重载都适用,编译器无法决定使用哪一个。

另一方面,在 (1)、(2) 和 (3) 中,两个 lambda 表达式中至少有一个返回 void,因此 foobool 重载不适用。


可能的解决方案是:

  • 将函子传递给foo 时,首先将其转换为std::function 的适当特化。 (看起来不太好)

  • std::function 编写一个自定义包装器/替换器,并为构造函数使用不同的 SFINAE。 (费劲)

  • foo 设为模板(使用模板参数作为回调类型)。然后使用decltype 确定返回类型,并采取相应措施。 (这就是我会做的)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2016-05-28
    相关资源
    最近更新 更多