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 03:14:33


We need a proposal to change experimental::observer_ptr :)
>

That was my intention before I was informed by the proposal author that the
proposal was a dead-end. I am not sure whether it would or would not be
worth pursuing now.

I agree we need this vocabulary type. GSL guidelines are for code that will
be written from scratch with C++14/C++17.
The reality is that we have tons of C++98 code. Pretending that T* is a not
owning pointer because we have gsl::owner is not useful in a legacy code
project. I'm not saying that gsl::owner is not useful.

Totally agree. In addition, there is still more than one use for `T*` in
the Core Guidelines (observer and "optional reference" parameter). I would
rather look at some unfamiliar code and see `observer_ptr<T>` than see `T*`
and have to consider whether or not the code is adhering to the guidelines.
The guidelines also assume that all people follow the guidelines perfectly,
and that the static analysis can catch all the "incorrect" uses of `T*`,
and that all code has been upgraded. In my opinion, `observer` and
`observer_ptr` embody the guidelines' own rules to "be type-safe" and
"express intent".

Whether to allow implicit/explicit conversion from `T&` is a design detail.
> The benefits are there regardless.
>
Yes, I believe the implicit conversion could be questionable.

Yes. I am increasingly feeling this way.

`observer<T>` is similar to `not_null<T>`, in that it enforces a "not null"
> precondition, except `observer<T>` does a much better job because it
> enforces the precondition at compile-time.
>
> auto o = make_observer(null_ptr); // compile error: expects `T&`
> auto n = not_null<T*>(null_ptr); // compiles fine; run-time error
>
I prefer also a not null smart pointer that takes this as a precondition.
Requiring the class to check the parameter is not nullptr (as gsl::not_null
does) is more than what I need.

Disagree. As I said, better to enforce at compile-time using the type
system.

`observer` forces the user to dereference their pointer, which should be
> flagged as unsafe by the static analyser if they don't check for null.
> `not_null` waits until compile-time to report the error, and makes it
> harder for a static analyser to catch the potential null pointer bug.
>
> I have had a few discussions with Neil over at the GSL GitHub page about
> the purpose of `not_null`. Honestly, the design goals of `not_null<T>` seem
> unclear to me; it seems to be trying to do too many things at once,
> simultaneously trying to be a drop-in replacement for `T*` that enforces a
> "not null" precondition at run-time (it's meant to be able to hold any kind
> of pointer or pointer-like object), but also trying to be this high-level
> modern type that has compile-time type safety (it deletes various pointer
> arithmetic operations, and it has been seriously suggested that conversion
> from `T` should be explicit). It was initially meant to be compatible with
> smart pointers like `unique_ptr`, but this goal seems to have been all but
> abandoned after it was realised that this won't really work. It's also
> meant to be used in conjunction with strings, despite the fact that
> `string_view` is a much better alternative, and with the `owner`
> annotation, despite the fact that this will probably have the same
> conceptual problems as `unique_ptr`. If my ramblings sound confused, it's
> because I am confused, because `not_null` is confused.
>
Maybe we could have not_null<Ptr> that works for any pointer-like type, but
what I need today is not_null_ptr<T>.
Maybe it is worth providing a single not_null<T*> instantiation.

I believe that `not_null` could be useful as a transparent pointer type
that can be used to enforce the "not null" precondition at compile-time
where you have a legacy interface that you do not want to break by updating
your interface to use some other kind of modern type (e.g. `observer` or
`vector` or whatever). I believe it should do nothing other than prevent
the pointer from becoming null (e.g. it should support pointer arithmetic).

In other words, `not_null` should be a crutch for legacy code that cannot
be updated to use modern C++ facilities because it would break client code.
Other, modern, type-safe facilities should be recommended for new C++ code.

`observer` and `observer_ptr` are essentially `maybe_null` and
> `not_null` with clearer design goals and a fixed interface.
>
> In reverse order ;-)

Yeah, I noticed that after I pressed send :)


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