blob: 8a85d3035cfcba94178343551ca3e37b7e78399f [file] [log] [blame]
Jim Flynn6217c3d2022-06-14 10:58:23 +01001//
2// Copyright (c) MapBox All rights reserved.
3// SPDX-License-Identifier: BSD-3-Clause
4//
5
James Ward22a4e152020-09-25 11:43:21 +01006#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
23namespace mapbox {
24namespace util {
25
26template <typename T>
27class recursive_wrapper
28{
29
30 T* p_;
31
32 void assign(T const& rhs)
33 {
34 this->get() = rhs;
35 }
36
37public:
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 */
49 recursive_wrapper()
50 : p_(new T){}
51
52 ~recursive_wrapper() noexcept { delete p_; }
53
54 recursive_wrapper(recursive_wrapper const& operand)
55 : p_(new T(operand.get())) {}
56
57 recursive_wrapper(T const& operand)
58 : p_(new T(operand)) {}
59
60 recursive_wrapper(recursive_wrapper&& operand)
61 : p_(new T(std::move(operand.get()))) {}
62
63 recursive_wrapper(T&& operand)
64 : p_(new T(std::move(operand))) {}
65
66 inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
67 {
68 assign(rhs.get());
69 return *this;
70 }
71
72 inline recursive_wrapper& operator=(T const& rhs)
73 {
74 assign(rhs);
75 return *this;
76 }
77
78 inline void swap(recursive_wrapper& operand) noexcept
79 {
80 T* temp = operand.p_;
81 operand.p_ = p_;
82 p_ = temp;
83 }
84
85 recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
86 {
87 swap(rhs);
88 return *this;
89 }
90
91 recursive_wrapper& operator=(T&& rhs)
92 {
93 get() = std::move(rhs);
94 return *this;
95 }
96
97 T& get()
98 {
99 assert(p_);
100 return *get_pointer();
101 }
102
103 T const& get() const
104 {
105 assert(p_);
106 return *get_pointer();
107 }
108
109 T* get_pointer() { return p_; }
110
111 const T* get_pointer() const { return p_; }
112
113 operator T const&() const { return this->get(); }
114
115 operator T&() { return this->get(); }
116
117}; // class recursive_wrapper
118
119template <typename T>
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