// // maybe_null.hpp // pointer // // Created by Sam Jaffe on 9/24/15. // // #pragma once #include #include #include "pointer_fwd.hpp" #include "ptr_compare.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() noexcept : _ptr(nullptr) {} maybe_null(T const & p) noexcept(std::is_nothrow_copy_constructible::value) : _ptr(p) { } maybe_null(T && p) noexcept(std::is_nothrow_move_constructible::value) : _ptr(std::move(p)) { } maybe_null(maybe_null const&) noexcept(std::is_nothrow_copy_constructible::value) = default; template explicit operator maybe_null() const noexcept(std::is_nothrow_copy_constructible::value) { return _ptr; } maybe_null& operator=(maybe_null const&) noexcept = default; template maybe_null& operator=(maybe_null const&other) noexcept { if (_ptr != other._ptr) { _ptr = other._ptr; #if defined( DEBUG ) tested_ = other.tested_; #endif } return *this; } operator bool() const noexcept { #if defined( DEBUG ) tested_ = true; #endif return static_cast(_ptr); } pointer get() const noexcept { return std::addressof(*_ptr); } pointer operator->() const /*throw(unchecked_pointer_exception)*/ { return std::addressof(operator*()); } #if defined( DEBUG ) reference operator*() const /*throw(unchecked_pointer_exception)*/ { if ( !tested_ ) { throw unchecked_pointer_exception{"did not verify that pointer was non-null"}; } return *_ptr; } #else reference operator*() const noexcept { return *_ptr; } #endif private: T _ptr; #if defined( DEBUG ) mutable bool tested_ = false; #endif }; POINTER_TEMPLATE_COMPARE( maybe_null )