6

I'd like to use observer_ptr in my project, but the paper only defines the interface, not the complete implementation.

Is there an easy way to implement it myself?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
UniversE
  • 555
  • 2
  • 7
  • 25
  • From the abstract i don't see much of a difference to a `weak_ptr`. Edit: The paper does not even mention `weak_ptrs`... WTH?? – RedX Jun 11 '14 at 08:10
  • 5
    @RedX: weak_ptr needs an allocated shared state and won't be usable unless the object is owned by some shared_ptr. So, the semantics and usage seems quite different. – lisyarus Jun 11 '14 at 08:11
  • 1
    @RedX, `weak_ptr` can't be used on `unique_ptr`. – UniversE Jun 11 '14 at 08:14
  • @UniversE if you really need observer_ptr that much, it seems that it's implementation is more or less trivial, so you can just implement it yourself – lisyarus Jun 11 '14 at 08:21
  • @lisyarus, Yeah, I plan to do a simpler one if don't find it in a short time. – UniversE Jun 11 '14 at 08:30

1 Answers1

19

You can create the so called observer_ptr trivially by creating a unique_ptr with a NOP deleter.

template<typename T>
struct nop_deleter
{
  void operator()(T*) const {}
};

template<typename T>
using observer_ptr = unique_ptr<T, nop_deleter>;

This will still have unique_ptr's behavior, meaning it's move-only, while you'd want observer_ptr to be copyable. Which leads us to a simpler implementation:

template<typename T>
using observer_ptr = T*;

This does everything you want. You can call it observer_ptr<int> instead of int *, because the latter is, of course, evil. It's copyable, and does nothing upon destruction.


I'm being facetious in the answer above, but hopefully, it'll demonstrate that observer_ptr doesn't have much utility other than having a different name than a raw pointer type. There's nothing wrong in using a non-owning raw pointer.

You may argue that observer_ptr conveys intent, but that argument is only valid if your code base contains instances of raw pointers that manage resources. Eliminate those and then a raw pointer will automatically mean observer_ptr ... without the fancy name.


If you absolutely must have the fancy name, and/or a distinct type, implementing it yourself should be easy.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 4
    I suppose one of the required features of observer_ptr is its interface compatible with other standard smart pointers (having methods like reset, swap, get, probably release) – lisyarus Jun 11 '14 at 08:42
  • 1
    Thank you very much :) Your implementation is elegant and your train of thought is amazing! I don't think using raw poiners is evil. Avoid and only use them when have to is because that looks chaos when "unique_ptr xxx" and "xxx * xxx" mixed. In the other way, I'm forgetful and don't want to check every raw pointer whether it should be deleted/freed safely after a few months and then I shall nearly completely forget the code segements :D – UniversE Jun 11 '14 at 09:43
  • 2
    @lisyarus Yes, the interface is consistent with the other smart pointers, and maybe there are occasions when you need that. But I've not yet come across the need to generically operate on a smart pointer type without knowledge of the ownership semantics at play. But I'm sure a contrived example can be cooked up where this would be useful. Still, in reality, the utility would be rather limited. – Praetorian Jun 11 '14 at 13:34
  • 1
    @Praetorian: surely, use cases of such a requirenment are not widespread, otherwise it would already be present in c++11 / boost :) – lisyarus Jun 11 '14 at 15:42
  • Often, what you really want in this case are not raw pointers but references. – danijar Sep 19 '14 at 13:32
  • 2
    One downside of the `using` method compared to a smart pointer type is that this won't zero-initialise `observer_ptr` variables. It's still a nice technique though. – the_mandrill Feb 19 '15 at 10:15
  • 1
    I used to buy this argument (and it was widely circulated at some point), but no longer do. `observer_ptr` disables incrementing, comparison to 0, addition/subtraction, and the delete operator. This stuff may not be earth shattering, but it's absolutely free, and there's no downside. Plus you can debug check for NULL upon dereference, Plus, green field codebases are nice, but they are probably still the minority. If you work in a codebase that has owning raw pointers, this is a valuable tool in the conversion effort. – Nir Friedman May 04 '17 at 11:58
  • @NirFriedman At one time, my answer to the pointer math drawback would've been to use `boost::optional`. But I've changed my mind about this too, `observer_ptr` is nice, especially because of your last sentence. Every single sizeable codebase I've worked with already has owning raw pointers and it's just not feasible to rework everything. In those cases, `observer_ptr` conveys the necessary intent. – Praetorian May 04 '17 at 19:50
  • None of the two suggested quick-n-dirty implementations are good for practical use. But that's because the specification of `observer_ptr` is ungood. At the very least it should disallowed inavertent `delete` via the pointer. – Cheers and hth. - Alf Jun 17 '17 at 01:38