// // maybe_null.hpp // pointer // // Created by Sam Jaffe on 9/24/15. // // #pragma once #include #include #include "pointer_fwd.hpp" #include "not_null.hpp" class unchecked_pointer_exception : public std::logic_error { using std::logic_error::logic_error; }; template class maybe_null>; // not permitted template class maybe_null { public: using element_type = typename std::pointer_traits::element_type; using pointer = element_type *; using reference = element_type &; maybe_null() : _ptr(nullptr) {} template maybe_null(Args && ...args) : _ptr(std::forward(args)...) { } maybe_null(maybe_null const&) = default; template maybe_null(maybe_null const& other) : _ptr(other.ptr_) { } template maybe_null(not_null const& other) : _ptr(other.get()) { } maybe_null& operator=(T ptr) { return operator=(maybe_null(ptr)); } maybe_null& operator=(maybe_null const&) = default; template maybe_null& operator=(maybe_null const&other) { if (_ptr != other.get()) { _ptr = other.get(); #if defined( DEBUG ) tested_ = other.tested_; #endif } return *this; } template maybe_null& operator=(not_null const&other) { _ptr = other.get(); #if defined( DEBUG ) tested_ = true; #endif return *this; } operator bool() const { #if defined( DEBUG ) tested_ = true; #endif return bool(_ptr); } pointer get() const { #if defined( DEBUG ) if ( !tested_ ) { throw unchecked_pointer_exception{"did not verify that pointer was non-null"}; } #endif return std::addressof(operator*()); } // operator T() const { return get(); } pointer operator->() const { return get(); } reference operator*() const { return *_ptr; } bool operator==(maybe_null const&rhs) const { return _ptr == rhs._ptr; } bool operator!=(maybe_null const&rhs) const { return _ptr != rhs._ptr; } bool operator<=(maybe_null const&rhs) const { return _ptr <= rhs._ptr; } bool operator>=(maybe_null const&rhs) const { return _ptr >= rhs._ptr; } bool operator< (maybe_null const&rhs) const { return _ptr < rhs._ptr; } bool operator> (maybe_null const&rhs) const { return _ptr > rhs._ptr; } private: T _ptr; #if defined( DEBUG ) mutable bool tested_ = false; #endif };