Consider this simple example code:
#include <functional>
#include <iostream>
void f(bool _switch) {
std::cout << "Nothing really" << std::endl;
}
void f(std::function<double (int)> _f) {
std::cout << "Nothing really, too" << std::endl;
}
int main ( int argc, char* argv[] ) {
f([](int _idx){ return 7.9;});
return 0;
}
It fails to compile:
$ g++ --std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:15:33: error: call of overloaded ‘f(main(int, char**)::<lambda(int)>)’ is ambiguous
main.cpp:15:33: note: candidates are:
main.cpp:6:6: note: void f(bool)
main.cpp:10:6: note: void f(std::function<double(int)>)
However if I replace the second function with a reference argument it compiles fine. And again if it is replaced by a const reference it fails.
So I have some questions concerning this example:
bool
in the first place?Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.
Lambdas are an inplace way to create function objects. Function objects are usually used in places were in C one employs function pointers as callbacks.
In C++, lambda expression constructs a closure, an unnamed function object capable of capturing variables in scope. It still sounds ambiguous, at least to me. Closure is a general concept in programming that originated from functional programming.
An implicit conversion sequence is the sequence of conversions required to convert an argument in a function call to the type of the corresponding parameter in a function declaration. The compiler tries to determine an implicit conversion sequence for each argument.
A lambda function with no capture can be converted to a regular function pointer, which then has a standard conversion to a bool.
If you take the std::function
by non-const reference, then that eliminates it as a candidate, since converting the lambda to a std::function
requires a temporary, and a temporary cannot bind to a non-const reference. That just leaves f(bool)
as a candidate, so there is no ambiguity.
There are many ways you could avoid the ambiguity. For example, you could create a std::function
variable first:
std::function<double(int)> g = [](int _idx){ return 7.9;};
f(g);
or you could cast the lambda:
f(std::function<double(int)>([](int _idx){return 7.9;}));
You could have a helper function:
template<typename T>
std::function<T> make_function(T *f) { return {f}; }
int main ( int argc, char* argv[] ) {
f(make_function([](int _idx){ return 7.9;}));
return 0;
}
or you could grab the particular function you are interested in:
int main ( int argc, char* argv[] ) {
void (*f_func)(std::function<double(int)>) = f;
f_func([](int _idx){ return 7.9;});
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With