C++ Logo

std-proposals

Advanced search

[std-proposals] Make closure type structural

From: Chromo Runge <rungecc_at_[hidden]>
Date: Sun, 19 Nov 2023 14:17:54 +0800
Currently, after CWG2452(https://cplusplus.github.io/CWG/issues/2542.html)
was solved by simply making all closure types non-structural, the below
example (from cppref) becomes ill-formed:

```c++

auto plus = [](int a, int b) { return a + b; }; auto forty_plus_cpp26
= std::bind_front<plus>(40);

```

The workaround is changing the template parameter `plus` to `+plus`, which
implicitly converts the closure type to a function pointer. But this only
works with capture-less non-generic lambda.

This is pretty astonishing since a lambda with no capture *has already met
the original requirements for a structural class type*: [temp.parm]/7:

> a literal class type with the following properties:
> - all base classes and non-static data members are public and non-mutable
and
> - the types of all bases classes and non-static data members are
structural types or (possibly multidimensional) array thereof.

Since closure type with no capture has no non-static data member (and no
base class, obviously), then the non-static members of it surely are all
public, non-mutable and structural by vacouse truth principle.

*So the first thing I would propose here is to make a closure type with no
capture structural. *This would make the above example valid (as before
the solution to CWG2452 was adopted). There's no difficulty in the
implementation, today, msvc, gcc and clang all accept this (
https://godbolt.org/z/K6TvYfhYr).

*The second proposal is more subtle, we want to make the captured closure
type also (possibly, if the captures are all structural) structural*. It is
actually possible, since though we alter the definition of the structural
class type in the future to allow class like `string_view` to be structural
(one possible way is allowing user defining a `structural equal to
operator` which converts a non-structural type into a structural type),
those changes shall not bother the structurality of closure type itself,
since user could not provide any member functions (other than
`operator()`), friend functions for a closure type. Thus, we could actually
treat all captured members public and non mutable (the mutable specifier in
the lambda declaration belongs to lambda's operator()). (Currently, only
gcc allows this: https://godbolt.org/z/KT3aerWjd)

It would be nice to just accept Proposal 1, since in most cases a
constexpr-usable capture need not to be captured.

Received on 2023-11-19 06:18:08