1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 #if !defined(BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM) 8 #define BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM 9 10 #include <boost/config.hpp> 11 #include <boost/variant.hpp> 12 #include <boost/mpl/list.hpp> 13 #include <utility> 14 #include <type_traits> 15 16 /////////////////////////////////////////////////////////////////////////////// 17 namespace boost { namespace spirit { namespace x3 18 { 19 template <typename T> 20 class forward_ast 21 { 22 public: 23 24 typedef T type; 25 26 public: 27 28 forward_ast() : p_(new T) {} 29 30 forward_ast(forward_ast const& operand) 31 : p_(new T(operand.get())) {} position_cache(iterator_type first,iterator_type last)32 33 forward_ast(forward_ast&& operand) BOOST_NOEXCEPT 34 : p_(operand.p_) 35 { 36 operand.p_ = 0; 37 } 38 position_of(position_tagged const & ast) const39 forward_ast(T const& operand) 40 : p_(new T(operand)) {} 41 42 forward_ast(T&& operand) 43 : p_(new T(std::move(operand))) {} 44 45 ~forward_ast() 46 { 47 boost::checked_delete(p_); 48 } 49 50 forward_ast& operator=(forward_ast const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value) 51 { 52 assign(rhs.get()); 53 return *this; position_of(AST const &) const54 } 55 56 void swap(forward_ast& operand) BOOST_NOEXCEPT 57 { 58 T* temp = operand.p_; 59 operand.p_ = p_; 60 p_ = temp; 61 } annotate(AST &,iterator_type,iterator_type,mpl::false_)62 63 forward_ast& operator=(T const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value) 64 { 65 assign(rhs); 66 return *this; 67 } annotate(position_tagged & ast,iterator_type first,iterator_type last,mpl::true_)68 69 forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT 70 { 71 swap(rhs); 72 return *this; 73 } 74 75 forward_ast& operator=(T&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<T>::value) 76 { annotate(AST & ast,iterator_type first,iterator_type last)77 get() = std::move(rhs); 78 return *this; 79 } 80 81 T& get() BOOST_NOEXCEPT { return *get_pointer(); } 82 const T& get() const BOOST_NOEXCEPT { return *get_pointer(); } get_positions() const83 84 T* get_pointer() BOOST_NOEXCEPT { return p_; } 85 const T* get_pointer() const BOOST_NOEXCEPT { return p_; } 86 87 operator T const&() const BOOST_NOEXCEPT { return this->get(); } first() const88 operator T&() BOOST_NOEXCEPT { return this->get(); } last() const89 90 private: 91 92 void assign(const T& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<T>::value) 93 { 94 this->get() = rhs; 95 } 96 97 T* p_; 98 }; 99 100 // function template swap 101 // 102 // Swaps two forward_ast<T> objects of the same type T. 103 // 104 template <typename T> 105 inline void swap(forward_ast<T>& lhs, forward_ast<T>& rhs) BOOST_NOEXCEPT 106 { 107 lhs.swap(rhs); 108 } 109 110 namespace detail 111 { 112 template <typename T> 113 struct remove_forward : mpl::identity<T> 114 {}; 115 116 template <typename T> 117 struct remove_forward<forward_ast<T>> : mpl::identity<T> 118 {}; 119 } 120 121 #if defined(BOOST_MSVC) 122 # pragma warning(push) 123 # pragma warning(disable: 4521) // multiple copy constructors specified 124 #endif 125 template <typename ...Types> 126 struct variant 127 { 128 // tell spirit that this is an adapted variant 129 struct adapted_variant_tag; 130 131 using variant_type = boost::variant<Types...>; 132 using types = mpl::list<typename detail::remove_forward<Types>::type...>; 133 using base_type = variant; // The current instantiation 134 135 template<typename T> 136 using non_self_t // used only for SFINAE checks below 137 = std::enable_if_t<!(std::is_base_of<base_type 138 ,std::remove_reference_t<T> 139 > 140 ::value) 141 >; 142 143 variant() BOOST_NOEXCEPT_IF(std::is_nothrow_default_constructible<variant_type>::value) : var() {} 144 145 template <typename T, class = non_self_t<T>> 146 explicit variant(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T const&>::value)) 147 : var(rhs) {} 148 149 template <typename T, class = non_self_t<T>> 150 explicit variant(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, T&&>::value)) 151 : var(std::forward<T>(rhs)) {} 152 153 variant(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_constructible<variant_type>::value) 154 : var(rhs.var) {} 155 156 variant(variant& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible<variant_type, variant_type&>::value)) 157 : var(rhs.var) {} 158 159 variant(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_constructible<variant_type>::value) 160 : var(std::move(rhs.var)) {} 161 162 variant& operator=(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable<variant_type>::value) 163 { 164 var = rhs.get(); 165 return *this; 166 } 167 168 variant& operator=(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable<variant_type>::value) 169 { 170 var = std::move(rhs.get()); 171 return *this; 172 } 173 174 template <typename T, class = non_self_t<T>> 175 variant& operator=(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T const&>::value)) 176 { 177 var = rhs; 178 return *this; 179 } 180 181 template <typename T, class = non_self_t<T>> 182 variant& operator=(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable<variant_type, T&&>::value)) 183 { 184 var = std::forward<T>(rhs); 185 return *this; 186 } 187 188 template <typename F> 189 typename F::result_type apply_visitor(F const& v) 190 { 191 return var.apply_visitor(v); 192 } 193 194 template <typename F> 195 typename F::result_type apply_visitor(F const& v) const 196 { 197 return var.apply_visitor(v); 198 } 199 200 template <typename F> 201 typename F::result_type apply_visitor(F& v) 202 { 203 return var.apply_visitor(v); 204 } 205 206 template <typename F> 207 typename F::result_type apply_visitor(F& v) const 208 { 209 return var.apply_visitor(v); 210 } 211 212 variant_type const& get() const BOOST_NOEXCEPT 213 { 214 return var; 215 } 216 217 variant_type& get() BOOST_NOEXCEPT 218 { 219 return var; 220 } 221 222 void swap(variant& rhs) BOOST_NOEXCEPT 223 { 224 var.swap(rhs.var); 225 } 226 227 variant_type var; 228 }; 229 #if defined(BOOST_MSVC) 230 # pragma warning(pop) 231 #endif 232 }}} 233 234 namespace boost 235 { 236 template <typename T, typename ...Types> 237 inline T const& 238 get(boost::spirit::x3::variant<Types...> const& x) BOOST_NOEXCEPT 239 { 240 return boost::get<T>(x.get()); 241 } 242 243 template <typename T, typename ...Types> 244 inline T& 245 get(boost::spirit::x3::variant<Types...>& x) BOOST_NOEXCEPT 246 { 247 return boost::get<T>(x.get()); 248 } 249 250 template <typename T, typename ...Types> 251 inline T const* 252 get(boost::spirit::x3::variant<Types...> const* x) BOOST_NOEXCEPT 253 { 254 return boost::get<T>(&x->get()); 255 } 256 257 template <typename T, typename ...Types> 258 inline T* 259 get(boost::spirit::x3::variant<Types...>* x) BOOST_NOEXCEPT 260 { 261 return boost::get<T>(&x->get()); 262 } 263 } 264 265 #endif 266