From 0b383b72841e4af2890d082e4caed3119484fe95 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Feb 2017 08:08:43 +0200 Subject: Add const_ptr, const-propagating smart pointer --- butl/buildfile | 1 + butl/const-ptr | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 butl/const-ptr 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 // 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 left; + // const_ptr 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 (x.left). + // + template + 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 explicit const_ptr (T1* p): p_ (p) {} + template const_ptr (const_ptr& p): p_ (p.p_) {} + + template const_ptr& operator= (T1* p) {p_ = p; return *this;} + template const_ptr& operator= (const_ptr& 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 -- cgit v1.1