Boost logo

Boost :

From: Glen Fernandes (glen.fernandes_at_[hidden])
Date: 2020-01-29 14:18:21

Gavin, in case my explanation in that earlier reply wasn't clear:

Given std::unique_ptr<Foo, D> p;

1. Users know that *p and p->x do the right thing by Foo.
2. p.get() will get them a D::pointer.

This D::pointer might be Foo*, or it might be offset_ptr<Foo> or it
might be alloc_ptr<offset_ptr<Foo>> or any other pointer-like type.

To get a Foo* out of p.get() regardless of which of the above three it
returns, you can call:

    Foo* q = std::to_address(p.get()); // C++20 in std, C++03 in boost

Or, if you know that p is not a null pointer, you can also use:

    if (p) {
        Foo* q = std::addressof(*p); // C++11 in std, C++03 in boost

std::unique_ptr<T, D> was always designed for this (since C++11).

Because not all pointers we use are raw pointers. An
Allocator::pointer might not be X*, it might be offset_ptr<X>, or it
might be aligned_ptr<offset_ptr<X>>.

This property of unique_ptr is also unrelated to allocate_unique
(which just leverages this with a fancy-pointer around the
Allocator::pointer which in turn might be a fancy-pointer).

But even today, users are using unique_ptr with non-raw pointers (like
Allocators where Allocator::pointer is offset_ptr<X> instead of X*).
They don't assume that p.get() returns a raw X* pointer.

This might be a lesser known property of unique_ptr to some
(especially those that do not work much with custom allocators), but
this is the way it has always been and intentionally so.


Boost list run by bdawes at, gregod at, cpdaniel at, john at