C++ 变量泛型lambda与函数重载

C++ 变量泛型lambda与函数重载,c++,c++14,C++,C++14,我定义了以下可变通用lambda和重载的foo()函数 template <typename Lambda> auto bar(Lambda&& lambda) { return [lambda = std::forward<Lambda>(lambda)](auto&& ...args) { return lambda(std::forward<decltype(args)>(args)...);

我定义了以下可变通用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; }
你能帮助我理解为什么它成功地编译了语句1-3,但未能编译语句4吗

gcc 7.5.0

std::function
可以存储任何返回类型的函数(
void
),其返回值被丢弃

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

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


可能的解决办法是:

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

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

  • 使
    foo
    成为模板(使用模板参数作为回调的类型)。然后使用
    decltype
    确定返回类型,并相应地采取行动。(这就是我要做的)


我很好奇
bar
是否有任何用途。对于这个例子来说似乎没有任何区别。我想这会迫使任何函子有一个占位符返回类型,但我想不出这会有什么不同。对,但当我被问到这个问题时,我并不清楚。
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; } )
    // );
}