diff options
-rw-r--r-- | butl/buildfile | 1 | ||||
-rw-r--r-- | butl/const-ptr | 77 |
2 files changed, 78 insertions, 0 deletions
diff --git a/butl/buildfile b/butl/buildfile index 734195e..090f9ed 100644 --- a/butl/buildfile +++ b/butl/buildfile @@ -5,6 +5,7 @@ lib{butl}: \ {hxx cxx}{ base64 } \ {hxx cxx}{ char-scanner } \ + {hxx }{ const-ptr } \ {hxx cxx}{ diagnostics } \ {hxx }{ export } \ {hxx ixx cxx}{ fdstream } \ diff --git a/butl/const-ptr b/butl/const-ptr new file mode 100644 index 0000000..23686bc --- /dev/null +++ b/butl/const-ptr @@ -0,0 +1,77 @@ +// file : butl/const-ptr -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUTL_CONST_PTR +#define BUTL_CONST_PTR + +#include <cstddef> // nullptr_t + +namespace butl +{ + // Const-propagating pointer. + // + // It has the semantics of a raw pointer except that it passes on its own + // const-ness to the pointed-to object. In other words, if you have a const + // instance of this pointer, then you can only obtain a const raw pointer to + // the underlying object. It is normally used as a data member, for example: + // + // struct tree + // { + // const_ptr<tree> left; + // const_ptr<tree> right; + // + // void modify (); + // }; + // + // tree* x = ...; + // const tree* y = ...; + // + // x.left->modify (); // Ok. + // y.left->modify (); // Error. + // + // Note that due to this semantics, copy construction/assignment requires + // a non-const instance of const_ptr. + // + // Known drawbacks/issues: + // + // 1. Cannot do static_cast<mytree*> (x.left). + // + template <typename T> + class const_ptr + { + public: + const_ptr () = default; + explicit const_ptr (T* p): p_ (p) {} + const_ptr (std::nullptr_t): p_ (nullptr) {} + + const_ptr& operator= (T* p) {p_ = p; return *this;} + const_ptr& operator= (std::nullptr_t) {p_ = nullptr; return *this;} + + template <class T1> explicit const_ptr (T1* p): p_ (p) {} + template <class T1> const_ptr (const_ptr<T1>& p): p_ (p.p_) {} + + template <class T1> const_ptr& operator= (T1* p) {p_ = p; return *this;} + template <class T1> const_ptr& operator= (const_ptr<T1>& p) { + p_ = p.p_; return *this;} + + T* operator-> () {return p_;} + const T* operator-> () const {return p_;} + + T& operator* () {return *p_;} + const T& operator* () const {return *p_;} + + operator T* () {return p_;} + operator const T* () const {return p_;} + + explicit operator bool () const {return p_ != nullptr;} + + T* get () {return p_;} + const T* get () const {return p_;} + + private: + T* p_; + }; +}; + +#endif // BUTL_CONST_PTR |