diff options
Diffstat (limited to 'boost/spirit/home/x3/support/ast/variant.hpp')
-rw-r--r-- | boost/spirit/home/x3/support/ast/variant.hpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/boost/spirit/home/x3/support/ast/variant.hpp b/boost/spirit/home/x3/support/ast/variant.hpp new file mode 100644 index 0000000000..cf626e88be --- /dev/null +++ b/boost/spirit/home/x3/support/ast/variant.hpp @@ -0,0 +1,249 @@ +/*============================================================================= + Copyright (c) 2001-2014 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM) +#define BOOST_SPIRIT_X3_VARIANT_AUGUST_6_2011_0859AM + +#if defined(_MSC_VER) +#pragma once +#endif + +#include <boost/variant.hpp> +#include <boost/mpl/list.hpp> +#include <boost/type_traits/is_base_of.hpp> + +/////////////////////////////////////////////////////////////////////////////// +namespace boost { namespace spirit { namespace x3 +{ + template <typename T> + class forward_ast + { + public: + + typedef T type; + + public: + + forward_ast() : p_(new T) {} + + forward_ast(forward_ast const& operand) + : p_(new T(operand.get())) {} + + forward_ast(forward_ast&& operand) + : p_(operand.p_) + { + operand.p_ = 0; + } + + forward_ast(T const& operand) + : p_(new T(operand)) {} + + forward_ast(T&& operand) + : p_(new T(std::move(operand))) {} + + ~forward_ast() + { + boost::checked_delete(p_); + } + + forward_ast& operator=(forward_ast const& rhs) + { + assign(rhs.get()); + return *this; + } + + void swap(forward_ast& operand) BOOST_NOEXCEPT + { + T* temp = operand.p_; + operand.p_ = p_; + p_ = temp; + } + + forward_ast& operator=(T const& rhs) + { + assign(rhs); + return *this; + } + + forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT + { + swap(rhs); + return *this; + } + + forward_ast& operator=(T&& rhs) + { + get() = std::move(rhs); + return *this; + } + + T& get() { return *get_pointer(); } + const T& get() const { return *get_pointer(); } + + T* get_pointer() { return p_; } + const T* get_pointer() const { return p_; } + + operator T const&() const { return this->get(); } + operator T&() { return this->get(); } + + private: + + void assign(const T& rhs) + { + this->get() = rhs; + } + + T* p_; + }; + + // function template swap + // + // Swaps two forward_ast<T> objects of the same type T. + // + template <typename T> + inline void swap(forward_ast<T>& lhs, forward_ast<T>& rhs) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + namespace detail + { + template <typename T> + struct remove_forward : mpl::identity<T> + {}; + + template <typename T> + struct remove_forward<forward_ast<T>> : mpl::identity<T> + {}; + } + + template <typename ...Types> + struct variant + { + // tell spirit that this is an adapted variant + struct adapted_variant_tag; + + typedef boost::variant<Types...> variant_type; + typedef mpl::list<typename detail::remove_forward<Types>::type...> types; + typedef variant<Types...> base_type; + + variant() : var() {} + + template <typename T, typename disable_if<is_base_of<base_type, T>>::type> + explicit variant(T const& rhs) + : var(rhs) {} + + template <typename T, typename disable_if<is_base_of<base_type, T>>::type> + explicit variant(T&& rhs) + : var(std::forward<T>(rhs)) {} + + variant(variant const& rhs) + : var(rhs.var) {} + + variant(variant& rhs) + : var(rhs.var) {} + + variant(variant&& rhs) + : var(std::forward<variant_type>(rhs.var)) {} + + variant& operator=(variant const& rhs) + { + var = rhs.get(); + return *this; + } + + variant& operator=(variant&& rhs) + { + var = std::forward<variant_type>(rhs.get()); + return *this; + } + + template <typename T> + //typename disable_if<is_base_of<base_type, T>, variant&>::type + variant& operator=(T const& rhs) + { + var = rhs; + return *this; + } + + template <typename T> + //typename disable_if<is_base_of<base_type, T>, variant&>::type + variant& operator=(T&& rhs) + { + var = std::forward<T>(rhs); + return *this; + } + + template <typename F> + typename F::result_type apply_visitor(F const& v) + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F const& v) const + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F& v) + { + return var.apply_visitor(v); + } + + template <typename F> + typename F::result_type apply_visitor(F& v) const + { + return var.apply_visitor(v); + } + + variant_type const& get() const + { + return var; + } + + variant_type& get() + { + return var; + } + + variant_type var; + }; +}}} + +namespace boost +{ + template <typename T, typename ...Types> + inline T const& + get(boost::spirit::x3::variant<Types...> const& x) + { + return boost::get<T>(x.get()); + } + + template <typename T, typename ...Types> + inline T& + get(boost::spirit::x3::variant<Types...>& x) + { + return boost::get<T>(x.get()); + } + + template <typename T, typename ...Types> + inline T const* + get(boost::spirit::x3::variant<Types...> const* x) + { + return boost::get<T>(&x->get()); + } + + template <typename T, typename ...Types> + inline T* + get(boost::spirit::x3::variant<Types...>* x) + { + return boost::get<T>(&x->get()); + } +} + +#endif |