1 // 2 // Copyright (c) MapBox All rights reserved. 3 // SPDX-License-Identifier: BSD-3-Clause 4 // 5 6 #ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP 7 #define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP 8 9 // Based on variant/recursive_wrapper.hpp from boost. 10 // 11 // Original license: 12 // 13 // Copyright (c) 2002-2003 14 // Eric Friedman, Itay Maman 15 // 16 // Distributed under the Boost Software License, Version 1.0. (See 17 // accompanying file LICENSE_1_0.txt or copy at 18 // http://www.boost.org/LICENSE_1_0.txt) 19 20 #include <cassert> 21 #include <utility> 22 23 namespace mapbox { 24 namespace util { 25 26 template <typename T> 27 class recursive_wrapper 28 { 29 30 T* p_; 31 assign(T const & rhs)32 void assign(T const& rhs) 33 { 34 this->get() = rhs; 35 } 36 37 public: 38 using type = T; 39 40 /** 41 * Default constructor default initializes the internally stored value. 42 * For POD types this means nothing is done and the storage is 43 * uninitialized. 44 * 45 * @throws std::bad_alloc if there is insufficient memory for an object 46 * of type T. 47 * @throws any exception thrown by the default constructur of T. 48 */ recursive_wrapper()49 recursive_wrapper() 50 : p_(new T){} 51 ~recursive_wrapper()52 ~recursive_wrapper() noexcept { delete p_; } 53 recursive_wrapper(recursive_wrapper const & operand)54 recursive_wrapper(recursive_wrapper const& operand) 55 : p_(new T(operand.get())) {} 56 recursive_wrapper(T const & operand)57 recursive_wrapper(T const& operand) 58 : p_(new T(operand)) {} 59 recursive_wrapper(recursive_wrapper && operand)60 recursive_wrapper(recursive_wrapper&& operand) 61 : p_(new T(std::move(operand.get()))) {} 62 recursive_wrapper(T && operand)63 recursive_wrapper(T&& operand) 64 : p_(new T(std::move(operand))) {} 65 operator =(recursive_wrapper const & rhs)66 inline recursive_wrapper& operator=(recursive_wrapper const& rhs) 67 { 68 assign(rhs.get()); 69 return *this; 70 } 71 operator =(T const & rhs)72 inline recursive_wrapper& operator=(T const& rhs) 73 { 74 assign(rhs); 75 return *this; 76 } 77 swap(recursive_wrapper & operand)78 inline void swap(recursive_wrapper& operand) noexcept 79 { 80 T* temp = operand.p_; 81 operand.p_ = p_; 82 p_ = temp; 83 } 84 operator =(recursive_wrapper && rhs)85 recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept 86 { 87 swap(rhs); 88 return *this; 89 } 90 operator =(T && rhs)91 recursive_wrapper& operator=(T&& rhs) 92 { 93 get() = std::move(rhs); 94 return *this; 95 } 96 get()97 T& get() 98 { 99 assert(p_); 100 return *get_pointer(); 101 } 102 get() const103 T const& get() const 104 { 105 assert(p_); 106 return *get_pointer(); 107 } 108 get_pointer()109 T* get_pointer() { return p_; } 110 get_pointer() const111 const T* get_pointer() const { return p_; } 112 operator T const&() const113 operator T const&() const { return this->get(); } 114 operator T&()115 operator T&() { return this->get(); } 116 117 }; // class recursive_wrapper 118 119 template <typename T> swap(recursive_wrapper<T> & lhs,recursive_wrapper<T> & rhs)120inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept 121 { 122 lhs.swap(rhs); 123 } 124 } // namespace util 125 } // namespace mapbox 126 127 #endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP 128