1 | #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 | |
18 | namespace mapbox { |
19 | namespace util { |
20 | |
21 | template <typename T> |
22 | class recursive_wrapper |
23 | { |
24 | |
25 | T* p_; |
26 | |
27 | void assign(T const& rhs) |
28 | { |
29 | this->get() = rhs; |
30 | } |
31 | |
32 | public: |
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: 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(operand&: 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 | |
114 | template <typename T> |
115 | inline 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 |
123 | |