Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading std::function argument to match lambda [duplicate]

Possible Duplicate:
Disambiguating calls to functions taking std::functions
Isn't the template argument (the signature) of std::function part of its type?

I want to overload a function so that it can be called with a variety of different lambdas (generally with more or fewer arguments) naturally. The obvious thing I tried was:

#include <functional>
#include <iostream>

extern void fn(std::function<void(int)>);
extern void fn(std::function<void(int, int)>);

void test()
{
    fn([](int a) { std::cout << "lambda with 1 arg " << a << std::endl; });
}

However, this fails with g++ (tried v4.6.2 and v4.7.1) with the error:

test.cc: In function ‘void test()’:
test.cc:9:74: error: call of overloaded ‘fn(test()::<lambda(int)>)’ is ambiguous
test.cc:9:74: note: candidates are:
test.cc:4:13: note: void fn(std::function<void(int)>)
test.cc:5:13: note: void fn(std::function<void(int, int)>)

Now I found an alternate (and much more complex) approaches here and here, but my question is, why does the above code fail? Is there something in the standard that says it can't work, or is this merely a bug/limitation of g++?

like image 773
Chris Dodd Avatar asked Aug 18 '12 18:08

Chris Dodd


1 Answers

Every Lambda [](int a) { std::cout << "lambda with 1 arg " << a << std::endl; } has unique type even another lambda same as above will result in different lambda type with member operator()(int a)

Your implementation of std::function has a templated conversion that can be used by both std::function<void(int)> and std::function<void(int, int)>. While only one of them compiles when instantiated, they're both considered for overload resolution, and that's what creates the ambiguity. To get the desired result the library needs to employ SFINAE to exclude the erroneous one from the overload candidate set (recent versions of libc++ do that).

like image 65
Mr.Anubis Avatar answered Oct 08 '22 17:10

Mr.Anubis