sergey
sergey

Reputation: 43

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

Upvotes: 4

Views: 114

Answers (1)

HolyBlackCat
HolyBlackCat

Reputation: 96719

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)

Upvotes: 8

Related Questions