Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Lambda functions implicit conversion to bool vs. std::function

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:

  • Why is a lambda function implicitly convertible to bool in the first place?
  • Why does taking a std::function reference solve the ambiguity?
  • And most important to me, how can I avoid this problem? I need the second function to take either a (copy of a) std::function or a const reference to it.
like image 620
Haatschii Avatar asked Apr 18 '14 21:04

Haatschii


People also ask

What is the correct syntax for Lambda Expression in C++11?

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.

What is the difference between lambda and function in C++?

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.

Are C++ lambdas closures?

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.

How do you define implicit conversion in C++?

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.


1 Answers

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;
}
like image 167
Vaughn Cato Avatar answered Oct 20 '22 01:10

Vaughn Cato