
Value_ptr – The Missing C++ Smart-pointer - etrevino
https://hackernoon.com/value-ptr-the-missing-c-smart-pointer-1f515664153e
======
SeanCline
The idea of a value_ptr is something that's been around in C++ for quite some
time, now. It usually goes by the name clone_ptr or copy_ptr. (Googling for
either will yield several implementations.)

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...](https://gist.github.com/SeanCline/c81218e4c0208ccb871268aecd7d4eff)

~~~
cjhanks
For similar reasons it seems inappropriate for PIMPL. The template indirectly
calls `sizeof(...)` on the template type. When that type is not concrete
(which is likely the case with PIMPL) the code will not compile. The
`value_ptr_example_pimpl.hpp` example doesn't compile for me using GCC 5.4.

~~~
SeanCline
Well, that isn't a flaw in the implementation of value_ptr. The example, as
provided, won't compile because the the copy constructor, assignment operator,
and destructor are declared `= default` in the header. This causes any
translation units that include value_ptr_example_pimpl.hpp to attempt to stamp
out the default implementation, which does require knowing
`sizeof(Foo::Pimpl)`.

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...](https://gist.github.com/SeanCline/55d700d4fbf8cc1bdaeb44b547ee200c)

------
petters
Not sure I like this pointer. Copying a pointer should not be a heavyweight
operation. That is pretty well established.

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.

~~~
entelechy
If you don't copy the resource then you are sharing it. This means you'll have
reference semantics and every instance operates on the same resource.
Value_ptr implements value semantics and so it behaves like primitives.

~~~
masklinn
> If you don't copy the resource then you are sharing it.

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.

------
arximboldi
Shameless plug, but that is very similar to the _immer::box_ type in this
library of immutable data-structures:
[https://sinusoid.es/immer/containers.html#box](https://sinusoid.es/immer/containers.html#box)

------
humanrebar
You still need to dereference the `value_ptr` a lot, right? Otherwise argument
dependent lookup won't work for the wrapped value type.

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.

------
adgasf
The comparison chart is nice
[https://gist.github.com/njlr/b03f212a3b56a22a54db536f536434f...](https://gist.github.com/njlr/b03f212a3b56a22a54db536f536434ff#file-
smartpointers-md)

~~~
wuch
Semantics would be more accurately described as optional-value (instead of
value).

------
ericfrederich
I highly recommend watching this presentation:
[https://www.youtube.com/watch?v=JfmTagWcqoE](https://www.youtube.com/watch?v=JfmTagWcqoE)

Herb Sutter: Leak-Freedom in C++ by default

------
matzf
That's just a confusing name for boost::optional, right?

~~~
wuch
Not exactly as boost::optional would have infinite size for recursive types.
You would need to combine it together with recursive_wrapper.

------
radarsat1
Since memory is copied, it's really not clear to me what the advantage is of
using value_ptr over just using values.

Is it just about heap vs. stack?

~~~
Eyas
I think its about recursive types/members, e.g.

    
    
        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`.

~~~
waqf
I think you have to say something about the copy semantics too, because if you
ignore those, value_ptr would be synonymous with unique_ptr.

    
    
       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.

------
faragon
C++ "smart pointers" share with threads a common risk: most people using them
should avoid using them.

~~~
TillE
"Most people" using new/delete with raw pointers = memory leaks and crashes,
guaranteed.

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.

~~~
faragon
Well, I'm using C++ since 1993, so go figure.

