简体   繁体   中英

Variadic generic lambda and function overload

I have the following variadic generic lambda and overloaded foo() function defined.

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; }

The following 3 foo() calls 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; } )
    // );
}

Could you please help me to understand why it successfully compiles statements 1-3 but fails to compile statement 4?

gcc 7.5.0

std::function<void()> can store a function with any return type ( void or not), its return value is discarded.

Because of that, in (4) both overloads are applicable, and the compiler can't decide which one to use.

In (1), (2), and (3) on the other hand, at least one of the two lambdas returns void , so the bool overload of foo is not applicable.


Possible solutions are:

  • When passing a functor into foo , cast it to a proper specialization of std::function first. (doesn't look too good)

  • Write a custom wrapper/replacement for std::function , with a different SFINAE for the constructor. (takes effort)

  • Make foo a template (use template parameters as types for the callbacks). Then use decltype to determine the return type, and act accordingly. (this is what I would do)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM