可变泛型 lambda 和函数重载

ser*_*gey 4 c++ c++14

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

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; }
Run Code Online (Sandbox Code Playgroud)

以下 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; } )
    // );
}
Run Code Online (Sandbox Code Playgroud)

你能帮我理解为什么它成功编译语句 1-3 但编译语句 4 失败吗?

海湾合作委员会 7.5.0

Hol*_*Cat 8

std::function<void()>可以存储具有任何返回类型(void或不具有)的函数,其返回值将被丢弃。

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

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


可能的解决方案是:

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

  • 为 编写自定义包装器/替换std::function,为构造函数使用不同的 SFINAE。(需要努力)

  • 制作foo模板(使用模板参数作为回调的类型)。然后使用decltype来确定返回类型,并相应地进行操作。(这就是我会做的)