Why is the definition of an object using decltype (lamda) not allowed and how can I improve it?

I studied lambda expressions and came across this question:

 #include <iostream> using std::cout; int main() { auto lam = [](int a){ cout<<"a"; }; decltype(lam) bb; // oop! deleted default constructor! bb(1); } 

But the compiler complained, as mentioned above. As far as I know, lambda is an object of an unnamed class. Therefore, I believe that this fragment may work.

Where did I make mistakes and could I improve it? Which constructor has a lambda? Is there any default constructor that I can do as decltype(lambda) object(args...) ?

+5
source share
3 answers

The fact that lambda is implemented as a class is not really a programmer's problem. You do not need to know / care / think about it. By extension, whether it has a default constructor or why it does / does not, is not related to everyday life.

As it happens, it does not currently execute:

[C++14: expr.prim.lambda/20]: The closure type associated with the lambda expression has a remote (8.4.3) default constructor and a remote copy assignment statement. It has an implicitly declared copy constructor (12.8) and may have an implicitly declared move constructor (12.8). [..]

[C++17: expr.prim.lambda/11]: The closure type associated with the lambda expression does not have a default constructor and remote copy assignment operator. It has a default copy constructor and a default move constructor. [..]

But! This will be a change in C ++ 20 , as described in P0624r2 . As far as I can tell, your code will become valid in accordance with this standard ( until you add any bindings to it ).

But for now, if you want to store functions, use std::function :

 #include <iostream> #include <functional> int main() { std::function<void(int)> bb; bb = [](int a) { std::cout << a << '\n'; }; // (time passes) bb(1); } 

( live demo )

Disclaimer: This is a contrived example. In the above code you do not take the overhead std::function ; you would just do auto lam = ... , as in the source code, and that would be so. But the OP for some reason showed the need to copy it into a new, default built object. Here is what I show how to do it.

+7
source

It is specified in the current standard (N4659 [expr.prim.lambda] / 11):

The closure type associated with the lambda expression has no default constructor and remote copy assignment operator. It has a default copy constructor and a default move constructor.

So you cannot go decltype(lam) bb; . You must initialize it from another lambda, although there is no state in this particular state:

 auto bb = lam; 

As shown in P0624's suggestion , there is no real reason for this, except that no one thought that allowing builds without the default lambda binding, and this could very well become possible in C ++ 20.

+3
source
 decltype(lam) bb; 

You specified a bb variable of some type, but you did not initialize it. It can be an image as a function declaration without defining it. Try below to compile your code.

 decltype(lam) bb = lam; 

or

 decltype(lam) bb(lam); 

It is better to use auto instead of decltype() .

+2
source

Source: https://habr.com/ru/post/1275799/


All Articles