I am trying to write a c++ lambda function, and don't like having to use auto
as the type. Currently it looks like:
#include <iostream>
int main() {
// Sends the address of an integer to a function which prints out the contents;
auto print_int = [](int* a) {std::cout << *a << std::endl;};
int a;
a = 3;
print_int(&a);
return 0;
}
However, I would like to change the auto
to something like std::function<void(int)>
but am not sure how. The answers to
seems relevant, but I am not sure how to adapt it. Thanks.
Lambda expressions in C++14 are functions that can be treated as any other object, such as a class or struct. They can utilize variables defined in the same scope, 'capturing' them implicitly or explicitly by value or reference. A lambda object (also known as 'closure object') can be called like a normal function.
Types of Lambda Body In Java, the lambda body is of two types. () -> System. out. println("Lambdas are great");
The return type of a method in which lambda expression used in a return statement must be a functional interface.
Yes, any lambda expression is an object in Java. It is an instance of a functional interface. We have assigned a lambda expression to any variable and pass it like any other object.
Lambdas are meant to be used with either auto
or as template parameter. You never know the type of a lambda and you can't type it. Each lambda has it's own unique type. Even if you knew the name of the type, their type names usually contains character prohibited in type names.
Why does lambda have their own type? because in reality, the compiler create a class defined a bit like that:
struct /* unnamed */ {
// function body
auto operator()(int* a) const {
std::cout << *a << std::endl;
}
} print_int; // <- instance name
This code is very close to an equivalent (I omitted conversion operator). As you can see, you already use auto, because lambdas are deducing the return type.
Some will say to use std::function<void(int*)>
, but I disagree. std::function
is a polymorphic wrapper around anything callable. Since lambdas are callable types, they fit into it. I other words, it work much like std::any
but with a call operator. It will induce overhead in your application.
So what should you do?
use auto
! auto
isn't bad. In fact, it can even make your code faster and reduce unnecessary typing. If you feel uncomfortable with auto
, well you shouldn't! auto
is great, especially if you don't have the choice ;)
In fact, you could avoid using auto
by using a template parameter:
template<typename F, typename Arg>
void parametric_print(F function, Arg&& arg) {
function(std::forward<Arg>(arg));
}
Then use it like this:
int main() {
int a = 3;
parametric_print([](int* a) {std::cout << *a << std::endl;}, &a);
}
There you go, no auto
! However, a template parameter is deduced with the same rule as auto
. In fact, concept are accepted into the C++20 standard with terse function templates. You could write the same function template like this:
// C++20
void parametric_print(auto function, auto&& arg) {
function(std::forward<decltype(arg)>(arg));
}
As mentionned by Oktalist, if concepts are accepted into the standard, then you could replace auto
with Callable
:
Callable print_int = [](int* a) { std::cout << *a << std::endl; };
But it does not result in a different type, it just enforce some rules when deducing the type.
Here you go:
int a;
[](int* a) {std::cout << *a << std::endl;}(&a);
No auto
used.
However, I would like to change the auto to something like
std::function<void(int)>
but am not sure how.
That is certainly possible. std::functional
has a templated converting constructor. You simply pass the lambda to the constructor and that's all there is to it. Also, you'll need to fix the argument type since your lambda expects an int*
, not an int
(this is the kind of bug that auto
fixes automatically).
std::function<void(int*)> print_int = [](int* a) {std::cout << *a << std::endl;};
Note however that there are two drawbacks to this.
std::function
wrapper is an indirection layer that hides the actual type of the callable object. This wrapper layer adds runtime overhead and prevents some optimizations.The lambda has its own unnamed type.
Your may convert your lambda into std::function<void(int*)>
(or for captureless lambda to void (*)(int*)
).
You may create your functor explicitly so you give it a name, something like:
class Print_int
{
public:
void operator()(int* a) const {std::cout << *a << std::endl;}
};
and then
Print_int print_int;
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