> Container in C++  usually means something differently than what you use it here

I agree, that's my mistake. I did not mean it as a container in the classical sense. It's really a kind of smart pointer. I'm going to refer to it as such from now on.

> You can have that type today with wrapping unique_ptr and removing some methods, like release.

Of course. However if you have to both add and remove functionality, those are grounds to make it a separate object.
As this is an even more strict unique_ptr, I would like to see it implemented in the standard.
I believe more frequent usage of this could lead to safer code.

> How exactly this would not lead to an invalid state of box?
That is a fair point and something i had overlooked. This may have to be changed to something similar to emplace, where a value is placed
in instead or this is available only on default-constructible items, so a default value is placed inside.

> Swap is not semantics of any move constructor in standard library.
This does seem unconventional, yes, however, it does not seem to break the standard as "Unless otherwise specified, all standard library objects that have been moved from are placed in a "valid but unspecified state", meaning the object's class invariants hold (so functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from)" (taken from cppreference.com)

This just looks like bad design.
I agree, this isn't the cleanest thing. But for the purposes for this proposal, I mentioned this to increase cohesion with the rest of the standard library. You probably wouldn't use the box in cases where the C function has a chance to leave the pointer empty. This case does seem a bit niche, I can believe that.

sestd., 2024. g. 14. dec., plkst. 23:04 — lietotājs Ivan Matek (<libbooze@gmail.com>) rakstīja:
Not a C++ standards person, so dont take anything I say as likely to be correct,  but here is my feedback:

On Sat, Dec 14, 2024 at 9:31 PM Oskars Putans via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
This is my first time posting here, so I appreciate any guidance on the style of my post.

C++ has been progressively incorporating ideas from Rust to improve memory safety. Easy examples are std::expected which parallel Rust's Result, std::optional which parallels Rust's Option.

I propose an adaptation of Rust's Box type: a pointer to a heap object that always contains a valid value and allows the templated object to be an incomplete type.



Container in C++  usually means something differently than what you use it here:
https://en.cppreference.com/w/cpp/container

First of all, I have to acknowledge that this type will most definitely be a lot more restrictive than a std::unique_ptr. 

This container enforces two key invariants: (1) the internal pointer is never nullptr and always points to an initialized value, and (2) the contained value is immovable.
To upkeep the invariant that the contained heap value is valid, if there is ever an invalid state,
an exception would be thrown immediately. 

You can have that type today with wrapping unique_ptr and removing some methods, like release.
 

Here's some of box's properties I've figured out so far (T being the template type):

- As a more constrained unique_ptr, it would be implicitly movable to a unique_ptr.

How exactly this would not lead to an invalid state of box?
 



- Move constructor swaps the internal pointers to not have to perform any extra initializations. Although this could be omitted from the standard and let implementations decide how to perform the move while keeping or discarding the invariant of the moved object. Either way should work well enough. I haven't yet thought about how up-casting and down-casting would function, but it shouldn't be too far from the way unique_ptr does that.

Swap is not semantics of any move constructor in standard library.

- To facilitate interoperation with C libraries, support for std::inout_ptr can be provided. std::inout_ptr would delete the object and set the pointer to nullptr in case 
This does risk breaking an invariant, but it would throw soon enough, and anyone who uses this would immediately assume this is the place where an invalid state is raised.

This just looks like bad design.