Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

c++ - Lambda closure type constructors

The cppreference shows that there are different rules for lambda closure type constructors.

Default Construction - Until C++14

ClosureType() = delete; (until C++14)

Closure types are not Default Constructible. Closure types have a deleted (until C++14)no (since C++14) default constructor.

Default Construction - Since C++14

Closure types have no (since C++14) default constructor.

Default Construction - Since C++20

If no captures are specified, the closure type has a defaulted default constructor. Otherwise, it has no default constructor (this includes the case when there is a capture-default, even if it does not actually capture anything).

Copy Assignment Operator - Until C++20

The copy assignment operator is defined as deleted (and the move assignment operator is not declared). Closure types are not CopyAssignable.

Copy Assignment Operator - Since C++20

If no captures are specified, the closure type has a defaulted copy assignment operator and a defaulted move assignment operator. Otherwise, it has a deleted copy assignment operator (this includes the case when there is a capture-default, even if it does not actually capture anything).

What is the reason behind this change in the rules? Did standard committee identified some short comings in the standard for lambda closure type construction? If so, what are those short comings?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There was a shortcoming. We couldn't use lambdas quite as "on the fly" as one might have wanted. C++20 (with the addition of allowing lambdas in unevaluated contexts) makes this code valid:

struct foo {
    int x, y;
};

std::map<foo, decltype([](foo const& a, foo const& b) { return a.x < a.y; })> m;

Note how we defined the compare function inline? No need to create a named functor (could be a good idea otherwise, but we aren't forced too). And there's no need to break the declaration in two:

// C++17
auto cmp = [](foo const& a, foo const& b) { return a.x < a.y; };
std::map<foo, decltype(cmp)> m(cmp); // And also need to pass and hold it!

Usages like this (and many more) were the motivating factor in making this change. In the example above, the anonymous functors type will bring all the benefits a named functor type can bring. Default initialization and EBO among them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...