blob: af569ef6378544d4b04c07ad49c6b20c05e275c8 [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
Andrew Geissler072da3e2018-01-18 07:21:42 -080023template <typename T> class recursive_wrapper
Patrick Williamsceefb312016-09-11 21:12:42 -050024{
25
26 T* p_;
27
28 void assign(T const& rhs)
29 {
30 this->get() = rhs;
31 }
32
Andrew Geissler072da3e2018-01-18 07:21:42 -080033 public:
Patrick Williamsceefb312016-09-11 21:12:42 -050034 using type = T;
35
36 /**
37 * Default constructor default initializes the internally stored value.
38 * For POD types this means nothing is done and the storage is
39 * uninitialized.
40 *
41 * @throws std::bad_alloc if there is insufficient memory for an object
42 * of type T.
43 * @throws any exception thrown by the default constructur of T.
44 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080045 recursive_wrapper() : p_(new T)
46 {
47 }
Patrick Williamsceefb312016-09-11 21:12:42 -050048
Andrew Geissler072da3e2018-01-18 07:21:42 -080049 ~recursive_wrapper() noexcept
50 {
51 delete p_;
52 }
Patrick Williamsceefb312016-09-11 21:12:42 -050053
Andrew Geissler072da3e2018-01-18 07:21:42 -080054 recursive_wrapper(recursive_wrapper const& operand) :
55 p_(new T(operand.get()))
56 {
57 }
Patrick Williamsceefb312016-09-11 21:12:42 -050058
Andrew Geissler072da3e2018-01-18 07:21:42 -080059 recursive_wrapper(T const& operand) : p_(new T(operand))
60 {
61 }
Patrick Williamsceefb312016-09-11 21:12:42 -050062
Andrew Geissler072da3e2018-01-18 07:21:42 -080063 recursive_wrapper(recursive_wrapper&& operand) :
64 p_(new T(std::move(operand.get())))
65 {
66 }
Patrick Williamsceefb312016-09-11 21:12:42 -050067
Andrew Geissler072da3e2018-01-18 07:21:42 -080068 recursive_wrapper(T&& operand) : p_(new T(std::move(operand)))
69 {
70 }
Patrick Williamsceefb312016-09-11 21:12:42 -050071
72 inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
73 {
74 assign(rhs.get());
75 return *this;
76 }
77
78 inline recursive_wrapper& operator=(T const& rhs)
79 {
80 assign(rhs);
81 return *this;
82 }
83
84 inline void swap(recursive_wrapper& operand) noexcept
85 {
86 T* temp = operand.p_;
87 operand.p_ = p_;
88 p_ = temp;
89 }
90
91 recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
92 {
93 swap(rhs);
94 return *this;
95 }
96
97 recursive_wrapper& operator=(T&& rhs)
98 {
99 get() = std::move(rhs);
100 return *this;
101 }
102
103 T& get()
104 {
105 assert(p_);
106 return *get_pointer();
107 }
108
109 T const& get() const
110 {
111 assert(p_);
112 return *get_pointer();
113 }
114
Andrew Geissler072da3e2018-01-18 07:21:42 -0800115 T* get_pointer()
116 {
117 return p_;
118 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500119
Andrew Geissler072da3e2018-01-18 07:21:42 -0800120 const T* get_pointer() const
121 {
122 return p_;
123 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500124
Andrew Geissler072da3e2018-01-18 07:21:42 -0800125 operator T const&() const
126 {
127 return this->get();
128 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500129
Andrew Geissler072da3e2018-01-18 07:21:42 -0800130 operator T&()
131 {
132 return this->get();
133 }
Patrick Williamsceefb312016-09-11 21:12:42 -0500134
135}; // class recursive_wrapper
136
137template <typename T>
138inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
139{
140 lhs.swap(rhs);
141}
142} // namespace util
143} // namespace mapbox
144
145#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP