• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
assign(T const & rhs)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      */
recursive_wrapper()44     recursive_wrapper()
45         : p_(new T){}
46 
~recursive_wrapper()47     ~recursive_wrapper() noexcept { delete p_; }
48 
recursive_wrapper(recursive_wrapper const & operand)49     recursive_wrapper(recursive_wrapper const& operand)
50         : p_(new T(operand.get())) {}
51 
recursive_wrapper(T const & operand)52     recursive_wrapper(T const& operand)
53         : p_(new T(operand)) {}
54 
recursive_wrapper(recursive_wrapper && operand)55     recursive_wrapper(recursive_wrapper&& operand)
56         : p_(new T(std::move(operand.get()))) {}
57 
recursive_wrapper(T && operand)58     recursive_wrapper(T&& operand)
59         : p_(new T(std::move(operand))) {}
60 
operator =(recursive_wrapper const & rhs)61     inline recursive_wrapper& operator=(recursive_wrapper const& rhs)
62     {
63         assign(rhs.get());
64         return *this;
65     }
66 
operator =(T const & rhs)67     inline recursive_wrapper& operator=(T const& rhs)
68     {
69         assign(rhs);
70         return *this;
71     }
72 
swap(recursive_wrapper & operand)73     inline void swap(recursive_wrapper& operand) noexcept
74     {
75         T* temp = operand.p_;
76         operand.p_ = p_;
77         p_ = temp;
78     }
79 
operator =(recursive_wrapper && rhs)80     recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept
81     {
82         swap(rhs);
83         return *this;
84     }
85 
operator =(T && rhs)86     recursive_wrapper& operator=(T&& rhs)
87     {
88         get() = std::move(rhs);
89         return *this;
90     }
91 
get()92     T& get()
93     {
94         assert(p_);
95         return *get_pointer();
96     }
97 
get() const98     T const& get() const
99     {
100         assert(p_);
101         return *get_pointer();
102     }
103 
get_pointer()104     T* get_pointer() { return p_; }
105 
get_pointer() const106     const T* get_pointer() const { return p_; }
107 
operator T const&() const108     operator T const&() const { return this->get(); }
109 
operator T&()110     operator T&() { return this->get(); }
111 
112 }; // class recursive_wrapper
113 
114 template <typename T>
swap(recursive_wrapper<T> & lhs,recursive_wrapper<T> & rhs)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