Boost logo

Boost :

Subject: Re: [boost] Is there any interest in non-owning pointer-like types?
From: Joseph Thomson (joseph.thomson_at_[hidden])
Date: 2017-02-03 05:46:33


On Fri, Feb 3, 2017 at 1:17 PM, David Stone <david_at_[hidden]> wrote:

> There is only one proper way to represent the concept of a T that might not
> be a T: optional<T>, so I think you are defining your objects backward. The
> "top level" type should be observer<T>, and if you want to support the
> concept of nullness, use optional<observer<T>>. This is a much more
> consistent way to treat nullness throughout the language, rather than
> special-casing it for every type.
>

I actually agree with you from an ideological perspective, but practical
implications drove me to my current design.

My original goal was to create a better interface for `not_null<T*>`, where
the "not null" precondition was enforced at compile-time. I came up with
`observer<T>` and deligated `optional<observer<T>>` as the optional
counterpart. However, I realised that `optional<observer<T>>` is not a
zero-overhead abstraction: it is twice the size of `T*` and many of its
operations do more than just reading and writing a pointer. I worried that
this would hurt adoption, so I created a zero-overhead replacement called
`optional_observer<T>`.

Originally, I was using `nullopt` to make `optional_observer<T>` look like
`optional<T>`, but soon realised that it was impossible to get both
zero-overhead comparison operations *and* have behavour consistent with
`optional<T>` (essentially, `nullopt` compares lower than any `T`, but the
ordering of `nullptr_t` is implementation-specified). Thus, I replaced it
with my own `nullobs` constant before realising it was just duplicating the
function of `nullptr` (`optional_observer<T>` was constructible from `T*`
and `nullptr_t` for performance and convenience reasons), so I removed
`nullobs` and ended up with something that looked very much like
`observer_ptr<T>`, so I renamed it and here we are today.

And `observer<T>` is still the "top level" type in a sense. `make_observer`
returns an `observer<T>`, and `observer_ptr<T>` is implicitly convertible
from `observer<T>`. This is another thing that is wrong with
`not_null<T*>`: it gets things backwards by putting the nullable type
(`T*`) on top and trying to suppress that nullability with a wrapper. This
is why it ends enforcing the "not null" precondition at run-time instead of
compile-time, because `not_null<T>` has to be constructed from `T`, a
nullable type.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk