Wrapped lambda expressions - c++

Here's a lamba wrapper expression defined:
function <int(double)> f =
[](double x) -> int{ return static_cast <int> (x*x); };
It is used like this:
f(someintvalue);
What is the difference between normal functions and wrapped lambdas?

question is - what is the difference between normal function and wrapped lambda?
Normal function is a normal function and what you call "wrapped lambda" is actually a function object.
By the way, why use std::function? You could simply write this:
auto f = [](double x) { return static_cast <int> (x*x); };
//call
int result = f(100.0);
Also, I omitted the return type, as it is implicitly known to the compiler from the return expression. No need to write -> int in the lambda expression.

Lambdas can capture surrounding scope ([=] or [&]) resulting in anonymous structs that contain a member function.
Certain tasks, like accessing lambda (types) across Translation Units, or taking standard pointer-to-memberfunction addresses from lambdas may prove hard/useless because the actual type of the automatically generated 'anonymous' type cannot be known (and is in fact implementation defined).
std::function<> was designed to alleviate exactly that problem: being able to bind a function pointer (semantically) to a lambda (or indeed, whatever callable object)
1: in fact the type can have external linkage, but you cannot portably refer to that from another translation unit because the actual type is implementation defined (and need not even be expressible in C++ code; within the original TU you'd be able to use decltype to get the magic type. Thanks, Luc for the good precisions about this)

Related

Why cpp std::function can hold capture-lambda, while function pointer cannot?

I've got this code snippet:
int x = 3;
auto fauto = [=](){ cout<<'x'; };
function<void()> func{fauto};
func();
void (*rawPf)() = fauto; // fail to compile
rawPf();
I knew the syntax that only non-capture lambda can be assigned to function pointer. But:
(1) Why std::function can hold capture-lambda?
(2) as both std::function and function pointers are callable, what's the core difference that makes std::function able to hold capture-lambda, while function pointer cannot?
Any detailed explanation on language design for this?
Why can a function pointer not hold a lambda with a capture : because a Lambda is NOT a function ,it's an object!
Why can a lambda without a capture be converted to a function pointer ?
A Lambda is just an ordinairy object (a piece of data) of a compiler generated class (with a unique classname that only the compiler knows) with a function-operator member (i.e. auto operator() ( ??? )) that the compiler defines for you with the parameter definitions (if any) you provide. The data-members of a lambda-object are defined by the capture-list and/or usage of variables of its enclosing scope.
All non-static member functions when called on an object get a implicit hidden argument called this. This is also the case when you 'call' the lambda.
Now ,when you don't capture something ,the lambda has no data (empty class) and the compiler doesn't have to generate an implicit this pointer for the call ,which makes the function operator just like an ordinairy function and the compiler can convert it to function pointer.
So it not the lambda that is converted to a function-pointer ,it's the lambda's function-operator that is converted.
Why can std::function hold both : because it's a template and with templates and specializations you can do almost anything.
There's no reason not to implement it in std::function<>, so it's implemented.
The reason a function pointer cannot hold a capture lambda is that the latter has a this pointer and there's no place to store that in the function pointer (well, unless you compile new code or assign it from a pool). However, std::function<> can allocate arbitrary amount of space, amongst these, the this pointer.
You can understand this better if you try to implement a function returning function pointers for lambdas (which, when called, by specification should call the lambda).

Why can a C++ function type alias be used to pass a lambda to a function?

Have a look at the code example listed below, I tested it with Compiler explorer (using gcc and clang) and it works and prints out the (expected) output of 200.
What I am trying to figure out: why exactly is this valid C++. Or is it not?
Here, I'm using the using keyword to define an alias (instead of a typedef) for the function type ft, which describes functions that take an int as argument and return an int (ft is a function type, not a function pointer type!). The equivalent typedef syntax is typedef int ft(int);. Since the C++ standard says that for every typedef there is an equivalent form using the using syntax, it is clear that using ft = int(int) is a well-defined way to specify this function type.
Now comes the interesting part: I use the type ft to specify the argument type of another function (print_it), and then call it, passing a lambda function. My question is: where/how does the C++ standard say that this should actually work? I think it is a wonderfully simple way to pass lambdas around. That this works is not clear to me, as a lambda is really a functor, not a function in the strict sense. So I think it is not clear that this lambda matches the type ft and therefore can be passed to print_it (if ft was defined to be std::function<int(int)> it would be clear though).
The code example:
#include <iostream>
using ft = int(int);
void print_it (ft f, int a)
{
std::cout << f(a) << std::endl;
}
int main ()
{
auto my_lambda = [] (int a) -> int { return 2 * a; };
print_it (my_lambda, 100);
return (0);
}
My question is: where/how does the C++ standard say that this should actually work?
This is specified in [expr.prim.lambda.closure]/7, which specifies that a lambda's closure type has a conversion function to a function pointer type matching the lambda's parameter and return types if the lambda is non-generic and doesn't have any capture. Calling through this function pointer basically behaves as if the lambda body was just a normal function to which the pointer points, which is possible because there are no captures which could give the lambda a state that a normal function can't have.
This applies here and you are using the conversion operator to implicitly convert the lambda object to a function pointer when passing it to print_it. This works since the lambda's parameter and return type matches the ft type and a function type used as type of a function parameter is adjusted to a pointer-to-function type instead. (See [dcl.fct]/5 for the last part.)
For generic lambdas there is a conversion function template (see the following standard paragraph). For lambdas with a capture there is no such conversion function and therefore this wouldn't work for them.
This only works because your lambda does not capture. A capture-less lambda can be converted to a C-style function pointer but a captureing lambda cannot.

Function which converts from from a_func(A a_in) to b_func(B b_in) (c++)

I have a class of function (call it AFunc) which takes a parameter of type A, and a class of function (call it BFunc) which takes a parallel parameter of type B (i.e. there is a straightforward conversion from objects of type A to those of type B).
I need to write a function like the following:
using Afunc = AReturnType(*)(A);
using BFunc = BReturnType(*)(B);
BFunc convertFunction(AFunc a_func_in)
{
BReturnType(*b_func_out) =
[&](B b_in) {
A a_in = A(b_in);
AReturnType a_out = a_func_in(a_in);
return BReturnType(a_out);
};
return b_func_out;
}
That is, a function which takes a function compatible with A types and returns a function compatible with B types.
My first thought was to define a function within the conversion function, but I quickly discovered that local functions are not supported in c++. My next thought was to use a lambda expression as above, but I have since learned that lambda functions can only be decayed to function pointers if they don't capture any references, however in this case the lambda needs to be aware of the AFunc parameter provided to the wider conversion function.
This is where I've run out of ideas. Is there any other way of doing this?
The problem is that having a function pointer is stronger than simply having a callable object. The latter could be a function pointer, but it could also be a closure or a functor, both of which carry state. A function pointer is just that: a pointer to a function. No state, no special tricks. Just one chunk of code that can be executed on demand.
So, at least, there's no way to pass an AFunc at runtime and get a BFunc, the way you've defined everything, because that would involve generating new functions in the code itself at runtime, which C++ doesn't allow.
However, if you know the AFunc you want to apply this too at compile-time, we can use templates to get the same result. A template is evaluated at compile-time and actually generates code, so we can use it to come up with functions which have genuine function pointers. In fact, we're not even going to write a conversion function; we're just going to write our BFunc and then template parameterize it.
template <AFunc f>
BReturnType bFunc(B b) {
return f(b);
}
Assuming the appropriate conversions exist, you can write something like BFunc b = bFunc<sampleAFunc>; and the compiler will generate the appropriate function (and corresponding pointer) for you.

Capturing a lambda in another lambda can violate const qualifiers

Consider the following code:
int x = 3;
auto f1 = [x]() mutable
{
return x++;
};
auto f2 = [f1]()
{
return f1();
};
This will not compile, because f1() is not const, and f2 is not declared as mutable. Does this mean that if I have a library function that accepts an arbitrary function argument and captures it in a lambda, I always need to make that lambda mutable, because I don't know what users can pass in? Notably, wrapping f1 in std::function seems to resolve this problem (how?).
Does this mean that if I have a library function that accepts an arbitrary function argument and captures it in a lambda, I always need to make that lambda mutable, because I don't know what users can pass in?
That's a design decision for your library API. You can require client code to pass function objects with a const-qualified operator() (which is the case for non-mutable lambda expressions). If something different is passed, a compiler error is triggered. But if the context might require a function object argument that modifies its state, then yes, you have to make the internal lambda mutable.
An alternative would be to dispatch on the ability to invoke operator() on a const-qualified instance of the given function type. Something along those lines (note that this needs a fix for function objects with both const and non-const operator(), which results in an ambiguity):
template <class Fct>
auto wrap(Fct&& f) -> decltype(f(), void())
{
[fct = std::forward<Fct>(f)]() mutable { fct(); }();
}
template <class Fct>
auto wrap(Fct&& f) -> decltype(std::declval<const Fct&>()(), void())
{
[fct = std::forward<Fct>(f)]() { fct(); }();
}
Notably, wrapping f1 in std::function seems to resolve this problem (how?).
This is a bug in std::function due to its type-erasure and copy semantics. It allows non-const-qualified operator() to be invoked, which can be verified with such a snippet:
const std::function<void()> f = [i = 0]() mutable { ++i; };
f(); // Shouldn't be possible, but unfortunately, it is
This is a known issue, it's worth checking out Titus Winter's complaint on this.
I'll start by addressing your second question first. std::function type erases, and holds a copy of the functor it's initialized with. That means there's a layer of indirection between std::function::operator() and the actual functor's operator().
Envision if you will, holding something in your class by pointer. Then you may call a mutating operation on the pointee from a const member function of your class, because it doesn't affect (in a shallow view) the pointer that the class holds. This is a similar situation to what you observed.
As for your first question... "Always" is too strong a word. It depends on your goal.
If you want to support self mutating functors easily, then you should capture in a mutable lambda. But beware it may affect the library functions you may call now.
If you wish to favor non-mutating operations, then a non-mutable lambda. I say "favor" because as we observed, the type system can be "fooled" with an extra level of indirection. So the approach you prefer is only going to be easier to use, not impossible to go around. This is as the sage advice goes, make correct use of your API easy, and incorrect harder.

Why does boost::bind store arguments of the type passed in rather than of the type expected by the function?

I recently ran into a bug in my code when using boost::bind.
From the boost::bind docs:
The arguments that bind takes are copied and held internally by the returned function object.
I had assumed that the type of the copy that was being held was based on the signature of the function. However, it is actually based on the type of the value passed in.
In my case an implicit conversion was happening to convert the type used in the bind expression to the type received by the function. I was expecting this conversion to happen at the site of the bind, however it happens when the resulting function object is used.
In retrospect I should have been able to figure this out from the fact that using boost::bind gives errors when types are not compatible only at the call site, not the bind site.
My question is:
Why does boost::bind work this way?
It seems to give worse compiler error messages
It seems to be less efficient when implicit conversion happens and there are multiple calls to the functor
But given how well Boost is designed I'm guessing there is a reason. Was it behavior inherited from std::bind1st/bind2nd? Is there a subtle reason why this would be hard/impossible to implement? Something else entirely?
To test that second theory I wrote up a little code snippet that seems to work, but there may well be features of bind I haven't accounted for since it's just a fragment:
namespace b = boost;
template<class R, class B1, class A1>
b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
mybind(R (*f) (B1), A1 a1)
{
typedef R (*F) (B1);
typedef typename b::_bi::list_av_1<B1>::type list_type;
return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}
struct Convertible
{
Convertible(int a) : b(a) {}
int b;
};
int foo(Convertible bar)
{
return 2+bar.b;
}
void mainFunc()
{
int x = 3;
b::function<int()> funcObj = mybind(foo, x);
printf("val: %d\n", funcObj());
}
Because the functor may support multiple overloads, which may give different behaviours. Even if this signature could be resolved when you knew all the arguments (and I don't know if Standard C++ can guarantee this facility) bind does not know all the arguments, and therefore it definitely cannot be provided. Therefore, bind does not possess the necessary information.
Edit: Just to clarify, consider
struct x {
void operator()(int, std::vector<float>);
void operator()(float, std::string);
};
int main() {
auto b = std::bind(x(), 1); // convert or not?
}
Even if you were to reflect on the struct and gain the knowledge of it's overloads, it's still undecidable as to whether you need to convert the 1 to a float or not.
There are different cases where you need the arguments to be processed at the call site.
The first such example is calling a member function, where you can either have the member called on a copy of the object (boost::bind( &std::vector<int>::push_back, myvector)) which most probably you don't want, or else you need to pass a pointer and the binder will dereference the pointer as needed (boost::bind( &std::vector<int>::push_back, &myvector )) --Note both options can make sense in different programs
Another important use case is passing an argument by reference to a function. bind will copy performing the equivalent to a pass-by-value call. The library offers the option of wrapping arguments through the helper functions ref and cref, both of which store a pointer to the actual object to be passed, and at the place of call they dereference the pointer (through an implicit conversion). If the conversion to the target type was performed at bind time, then this would be impossible to implement.
I think this is due to the fact that bind has to work with any callable entity, be it a function pointer, std::function<>, or your own functor struct with operator(). This makes bind generic on any type that can be called using (). I.e. Bind's implicit requirement on your functor is just that it can be used with ()
If bind was to store the function argument types, it would have to somehow infer them for any callable entity passed in as a type parameter. This would obviously not be as generic, since deducing parameter types of an operator() of a passed-in struct type is impossible without relying on the user to specify some kind of typedef (as an example). As a result the requirement on the functor (or concept) is no longer concrete/simple.
I am not entirely sure this is the reason, but it's one of the things that would be a problem.
EDIT: Another point as DeadMG mentions in another answer, overloads would create ambiguities even for standard function pointers, since the compiler would not be able to resolve the functor type. By storing the types you provide to bind and using (), this problem is also avoided.
A good example would binding "std::future"s to some ordinary function taking ordinary types:
Say I want to use an ordinary f(x,y) function in an incredibly asynchronous way. Namely, I want to call it like "f(X.get(), Y.get())". There's a good reason for this- I can just call that line and f's logic will run as soon as both inputs are available (I don't need separate lines of code for the join). To do this I need the following:
1) I need to support implicit conversions "std::future<T> -> T". This means std::future or my custom equivalent needs a cast operator:
operator T() { return get(); }
2) Next, I need to bind my generic function to hide all its parameters
// Hide the parameters
template<typename OUTPUT, typename... INPUTS>
std::function<OUTPUT()> BindVariadic(std::function<OUTPUT(INPUTS...)> f,
INPUTS&&... in)
{
std::function<OUTPUT()> stub = std::bind( f, std::forward<INPUTS>(in)...);
return stub;
}
With a std::bind that does the "std::function<T> -> T" conversion at call time, I only wait for all the input parameters to become available when I ACTUALLY CALL "stub()". If it did the conversion via operator T() at the bind, the logic would silently force the wait when I actually constructed "stub" instead of when I use it. That might be fatal if "stub()" cannot always run safely in the same thread I built it.
There are other use cases that also forced that design choice. This elaborate one for async processing is simply the one I'm personally familiar with.