1 /*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
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
10 #include <boost/variant.hpp>
11 #include <boost/mpl/list.hpp>
12 #include <boost/type_traits/is_base_of.hpp>
13 #include <type_traits>
15 ///////////////////////////////////////////////////////////////////////////////
16 namespace boost { namespace spirit { namespace x3
27 forward_ast() : p_(new T) {}
29 forward_ast(forward_ast const& operand)
30 : p_(new T(operand.get())) {}
32 forward_ast(forward_ast&& operand)
38 forward_ast(T const& operand)
39 : p_(new T(operand)) {}
41 forward_ast(T&& operand)
42 : p_(new T(std::move(operand))) {}
46 boost::checked_delete(p_);
49 forward_ast& operator=(forward_ast const& rhs)
55 void swap(forward_ast& operand) BOOST_NOEXCEPT
62 forward_ast& operator=(T const& rhs)
68 forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT
74 forward_ast& operator=(T&& rhs)
76 get() = std::move(rhs);
80 T& get() { return *get_pointer(); }
81 const T& get() const { return *get_pointer(); }
83 T* get_pointer() { return p_; }
84 const T* get_pointer() const { return p_; }
86 operator T const&() const { return this->get(); }
87 operator T&() { return this->get(); }
91 void assign(const T& rhs)
99 // function template swap
101 // Swaps two forward_ast<T> objects of the same type T.
103 template <typename T>
104 inline void swap(forward_ast<T>& lhs, forward_ast<T>& rhs) BOOST_NOEXCEPT
111 template <typename T>
112 struct remove_forward : mpl::identity<T>
115 template <typename T>
116 struct remove_forward<forward_ast<T>> : mpl::identity<T>
120 template <typename ...Types>
123 // tell spirit that this is an adapted variant
124 struct adapted_variant_tag;
126 using variant_type = boost::variant<Types...>;
127 using types = mpl::list<typename detail::remove_forward<Types>::type...>;
128 using base_type = variant; // The current instantiation
131 using non_self_t // used only for SFINAE checks below
132 = std::enable_if_t<!(std::is_base_of<base_type
133 ,std::remove_reference_t<T>
140 template <typename T, class = non_self_t<T>>
141 explicit variant(T const& rhs)
144 template <typename T, class = non_self_t<T>>
145 explicit variant(T&& rhs)
146 : var(std::forward<T>(rhs)) {}
148 variant(variant const& rhs)
151 variant(variant& rhs)
154 variant(variant&& rhs)
155 : var(std::forward<variant_type>(rhs.var)) {}
157 variant& operator=(variant const& rhs)
163 variant& operator=(variant&& rhs)
165 var = std::forward<variant_type>(rhs.get());
169 template <typename T, class = non_self_t<T>>
170 variant& operator=(T const& rhs)
176 template <typename T, class = non_self_t<T>>
177 variant& operator=(T&& rhs)
179 var = std::forward<T>(rhs);
183 template <typename F>
184 typename F::result_type apply_visitor(F const& v)
186 return var.apply_visitor(v);
189 template <typename F>
190 typename F::result_type apply_visitor(F const& v) const
192 return var.apply_visitor(v);
195 template <typename F>
196 typename F::result_type apply_visitor(F& v)
198 return var.apply_visitor(v);
201 template <typename F>
202 typename F::result_type apply_visitor(F& v) const
204 return var.apply_visitor(v);
207 variant_type const& get() const
217 void swap(variant& rhs) BOOST_NOEXCEPT
228 template <typename T, typename ...Types>
230 get(boost::spirit::x3::variant<Types...> const& x)
232 return boost::get<T>(x.get());
235 template <typename T, typename ...Types>
237 get(boost::spirit::x3::variant<Types...>& x)
239 return boost::get<T>(x.get());
242 template <typename T, typename ...Types>
244 get(boost::spirit::x3::variant<Types...> const* x)
246 return boost::get<T>(&x->get());
249 template <typename T, typename ...Types>
251 get(boost::spirit::x3::variant<Types...>* x)
253 return boost::get<T>(&x->get());