C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Make closure type structural

From: Zhihao Yuan <zy_at_[hidden]>
Date: Sun, 19 Nov 2023 07:27:19 +0000
Paper is definitely welcome.

With regarding to technical details, I was told
that by value captures have no issue to implement.
There are two more corner cases to consider:


1. By-reference captures. Are they actually
    useful? You can't reference a local variable
    (yet, not until P2686), and you don't have to
    reference a global variable.
    

2. A by-value capture of an array type can be
    be allowed, but array is not a structural type.
    This is a special case (a structural type can
    contain array member.)


As always, more motivation is needed for allowing
your second proposal.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
_______________________________________________
On Saturday, November 18th, 2023 at 10:17 PM, Chromo Runge via Std-Proposals <std-proposals_at_[hidden]> wrote:
> 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 07:27:37