blob: 4ffcbd7c9366b00951cd2902ecc0e211f7c0ffd9 [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
18namespace mapbox {
19namespace util {
20
21template <typename T>
22class recursive_wrapper
23{
24
25 T* p_;
26
27 void assign(T const& rhs)
28 {
29 this->get() = rhs;
30 }
31
32public:
33 using type = T;
34
35 /**
36 * Default constructor default initializes the internally stored value.
37 * For POD types this means nothing is done and the storage is
38 * uninitialized.
39 *
40 * @throws std::bad_alloc if there is insufficient memory for an object
41 * of type T.
42 * @throws any exception thrown by the default constructur of T.
43 */
44 recursive_wrapper()
45 : p_(new T){}
46
47 ~recursive_wrapper() noexcept { delete p_; }
48
49 recursive_wrapper(recursive_wrapper const& operand)
50 : p_(new T(operand.get())) {}
51
52 recursive_wrapper(T const& operand)
53 : p_(new T(operand)) {}
54
55 recursive_wrapper(recursive_wrapper&& operand)
56 : p_(new T(std::move(operand.get()))) {}
57
58 recursive_wrapper(T&& operand)
59 : p_(new T(std::move(operand))) {}
60
61 inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
62 {
63 assign(rhs.get());
64 return *this;
65 }
66
67 inline recursive_wrapper& operator=(T const& rhs)
68 {
69 assign(rhs);
70 return *this;
71 }
72
73 inline void swap(recursive_wrapper& operand) noexcept
74 {
75 T* temp = operand.p_;
76 operand.p_ = p_;
77 p_ = temp;
78 }
79
80 recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
81 {
82 swap(rhs);
83 return *this;
84 }
85
86 recursive_wrapper& operator=(T&& rhs)
87 {
88 get() = std::move(rhs);
89 return *this;
90 }
91
92 T& get()
93 {
94 assert(p_);
95 return *get_pointer();
96 }
97
98 T const& get() const
99 {
100 assert(p_);
101 return *get_pointer();
102 }
103
104 T* get_pointer() { return p_; }
105
106 const T* get_pointer() const { return p_; }
107
108 operator T const&() const { return this->get(); }
109
110 operator T&() { return this->get(); }
111
112}; // class recursive_wrapper
113
114template <typename T>
115inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) noexcept
116{
117 lhs.swap(rhs);
118}
119} // namespace util
120} // namespace mapbox
121
122#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP