blob: c90a88cefe481c60e408011d71ece74033a24792 [file] [log] [blame]
Patrick Williamsceefb312016-09-11 21:12:42 -05001#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
2#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP
3
4// Based on variant/recursive_wrapper.hpp from boost.
5//
6// Original license:
7//
8// Copyright (c) 2002-2003
9// Eric Friedman, Itay Maman
10//
11// Distributed under the Boost Software License, Version 1.0. (See
12// accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#include <cassert>
16#include <utility>
17
Andrew Geissler072da3e2018-01-18 07:21:42 -080018namespace mapbox
19{
20namespace util
21{
Patrick Williamsceefb312016-09-11 21:12:42 -050022
Patrick Venture2b238af2018-08-31 12:45:01 -070023template <typename T>
24class recursive_wrapper
Patrick Williamsceefb312016-09-11 21:12:42 -050025{
26
27 T* p_;
28
29 void assign(T const& rhs)
30 {
31 this->get() = rhs;
32 }
33
Andrew Geissler072da3e2018-01-18 07:21:42 -080034 public:
Patrick Williamsceefb312016-09-11 21:12:42 -050035 using type = T;
36
37 /**
38 * Default constructor default initializes the internally stored value.
39 * For POD types this means nothing is done and the storage is
40 * uninitialized.
41 *
42 * @throws std::bad_alloc if there is insufficient memory for an object
43 * of type T.
44 * @throws any exception thrown by the default constructur of T.
45 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080046 recursive_wrapper() : p_(new T)
47 {
48 }
Patrick Williamsceefb312016-09-11 21:12:42 -050049
Andrew Geissler072da3e2018-01-18 07:21:42 -080050 ~recursive_wrapper() noexcept
51 {
52 delete p_;
53 }
Patrick Williamsceefb312016-09-11 21:12:42 -050054
Andrew Geissler072da3e2018-01-18 07:21:42 -080055 recursive_wrapper(recursive_wrapper const& operand) :
56 p_(new T(operand.get()))
57 {
58 }
Patrick Williamsceefb312016-09-11 21:12:42 -050059
Andrew Geissler072da3e2018-01-18 07:21:42 -080060 recursive_wrapper(T const& operand) : p_(new T(operand))
61 {
62 }
Patrick Williamsceefb312016-09-11 21:12:42 -050063
Andrew Geissler072da3e2018-01-18 07:21:42 -080064 recursive_wrapper(recursive_wrapper&& operand) :
65 p_(new T(std::move(operand.get())))
66 {
67 }
Patrick Williamsceefb312016-09-11 21:12:42 -050068
Andrew Geissler072da3e2018-01-18 07:21:42 -080069 recursive_wrapper(T&& operand) : p_(new T(std::move(operand)))
70 {
71 }
Patrick Williamsceefb312016-09-11 21:12:42 -050072
73 inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
74 {
75 assign(rhs.get());
76 return *this;
77 }
78
79 inline recursive_wrapper& operator=(T const& rhs)
80 {
81 assign(rhs);
82 return *this;
83 }
84
85 inline void swap(recursive_wrapper& operand) noexcept
86 {
87 T* temp = operand.p_;
88 operand.p_ = p_;
89 p_ = temp;
90 }
91
92 recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
93 {
94 swap(rhs);
95 return *this;
96 }
97
98 recursive_wrapper& operator=(T&& rhs)
99 {
100 get() = std::move(rhs);
101 return *this;
102 }
103
104 T& get()
105 {
106 assert(p_);
107 return *get_pointer();
108 }
109
110 T const& get() const
111 {
112 assert(p_);
113 return *get_pointer();
114 }
115
Andrew Geissler072da3e2018-01-18 07:21:42 -0800116 T* get_pointer()
117 {
118 return p_;
119 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500120
Andrew Geissler072da3e2018-01-18 07:21:42 -0800121 const T* get_pointer() const
122 {
123 return p_;
124 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500125
Andrew Geissler072da3e2018-01-18 07:21:42 -0800126 operator T const&() const
127 {
128 return this->get();
129 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500130
Andrew Geissler072da3e2018-01-18 07:21:42 -0800131 operator T&()
132 {
133 return this->get();
134 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500135
136}; // class recursive_wrapper
137
138template <typename T>
139inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
140{
141 lhs.swap(rhs);
142}
143} // namespace util
144} // namespace mapbox
145
146#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP