Value_ptr – The Missing C++ Smart-pointer
hackernoon.com
hackernoon.com
Looking at the author's code on GitHub, this implementation seems decent.
One thing to note about this implementation is that it doesn't address the other big reason for doing dynamic allocations: polymorphic types. Value semantics are preserved so faithfully that objects are sliced just as they would be if they weren't dynamically allocated.
Consider this example: https://gist.github.com/SeanCline/c81218e4c0208ccb871268aecd...
Moving those methods to value_ptr_example_pimpl.cpp, just as you'd normally do for PIMPL makes the compiler happy.
This works for me in VS2017 but should work on any C++11 compliant compiler: https://gist.github.com/SeanCline/55d700d4fbf8cc1bdaeb44b547...
I wish C++ had a unique_ptr without the ability to be null. But that does not seem possible given that moving from a pointer must give a valid object.
I think their point is more that the copy has an arbitrary complexity, so while you think you're copying a smart pointer you're triggering a possibly huge cascade behind the scenes.
> This means you'll have reference semantics and every instance operates on the same resource
You could have an explicit copy operation on an otherwise move-semantic smart pointer. No sharing, and while you get the ability to copy stuff if necessary it's not potentially hidden behind every argument passing or assignation, it becomes a very deliberate operation.
moving from a pointer must give a valid object
Yes (well, actually it's state is 'valid but unspecified') but afaik performing any operations having preconditions on moved-from objects is undefined behaviour anyway so you shouldn't even be doing that. And when using not_null that would again result in an exception.
An alternative option would be a unique_ptr subtype (or extension) which allows cloning if the wrapped type is clonable, something similar to rust's
impl<T> Clone for Box<T> where T: Clone
Can that be expressed without concepts?Separate implementation, but not separate interface? The Rust bit means Box is "transparently" clonable, meaning it only implements the clone trait(/interface) if the value it wraps also does, trying to clone a Box<T> where T can not be cloned would be a compile-time error.
I guess you could provide specializations for all the common candidates (begin, end, swap, size, empty, data, and whatever gets added in the future) in the "valuable" namespace, but you'll need to be pretty aggressive with adding new specializations as people find ones they need.
Also, it might be a good idea to support a Deleter template parameter and propagate it to the underlying `unique_ptr`. Some projects use that customization point for various purposes, like instrumentation of (de)allocation or grabbing certain kinds of objects from memory pools.
Herb Sutter: Leak-Freedom in C++ by default
Is it just about heap vs. stack?
class Tree { Tree _left, _right; };
Won't compile because it has an infinite size. However class Tree { Tree *_left, *_right; };
Compiles, but the author contends that a more explicit description of the ownership semantics is better: class Tree { value_ptr<Tree> _left, _right; }
This is also why `value_ptr` is different than `optional`. class Tree { Tree *_left, *_right; };
Tree y = x;
makes a shallow copy. class Tree { unique_ptr<Tree> _left, _right; };
Tree y = x;
doesn't compile, but class Tree { value_ptr<Tree> _left, _right; };
Tree y = x;
makes a deep copy.unique_ptr and shared_ptr are really simple and incredibly useful. If you're too scared to use them, you should not be using C++ at all.