/*============================================================================= 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 #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace x3 { template 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) BOOST_NOEXCEPT : 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) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable::value) { 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) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable::value) { assign(rhs); return *this; } forward_ast& operator=(forward_ast&& rhs) BOOST_NOEXCEPT { swap(rhs); return *this; } forward_ast& operator=(T&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) { get() = std::move(rhs); return *this; } T& get() BOOST_NOEXCEPT { return *get_pointer(); } const T& get() const BOOST_NOEXCEPT { return *get_pointer(); } T* get_pointer() BOOST_NOEXCEPT { return p_; } const T* get_pointer() const BOOST_NOEXCEPT { return p_; } operator T const&() const BOOST_NOEXCEPT { return this->get(); } operator T&() BOOST_NOEXCEPT { return this->get(); } private: void assign(const T& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable::value) { this->get() = rhs; } T* p_; }; // function template swap // // Swaps two forward_ast objects of the same type T. // template inline void swap(forward_ast& lhs, forward_ast& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } namespace detail { template struct remove_forward : mpl::identity {}; template struct remove_forward> : mpl::identity {}; } #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable: 4521) // multiple copy constructors specified #endif template struct variant { // tell spirit that this is an adapted variant struct adapted_variant_tag; using variant_type = boost::variant; using types = mpl::list::type...>; using base_type = variant; // The current instantiation template using non_self_t // used only for SFINAE checks below = std::enable_if_t > ::value) >; variant() BOOST_NOEXCEPT_IF(std::is_nothrow_default_constructible::value) : var() {} template > explicit variant(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible::value)) : var(rhs) {} template > explicit variant(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible::value)) : var(std::forward(rhs)) {} variant(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_constructible::value) : var(rhs.var) {} variant(variant& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_constructible::value)) : var(rhs.var) {} variant(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_constructible::value) : var(std::move(rhs.var)) {} variant& operator=(variant const& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_copy_assignable::value) { var = rhs.get(); return *this; } variant& operator=(variant&& rhs) BOOST_NOEXCEPT_IF(std::is_nothrow_move_assignable::value) { var = std::move(rhs.get()); return *this; } template > variant& operator=(T const& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable::value)) { var = rhs; return *this; } template > variant& operator=(T&& rhs) BOOST_NOEXCEPT_IF((std::is_nothrow_assignable::value)) { var = std::forward(rhs); return *this; } template typename F::result_type apply_visitor(F const& v) { return var.apply_visitor(v); } template typename F::result_type apply_visitor(F const& v) const { return var.apply_visitor(v); } template typename F::result_type apply_visitor(F& v) { return var.apply_visitor(v); } template typename F::result_type apply_visitor(F& v) const { return var.apply_visitor(v); } variant_type const& get() const BOOST_NOEXCEPT { return var; } variant_type& get() BOOST_NOEXCEPT { return var; } void swap(variant& rhs) BOOST_NOEXCEPT { var.swap(rhs.var); } variant_type var; }; #if defined(BOOST_MSVC) # pragma warning(pop) #endif }}} namespace boost { template inline T const& get(boost::spirit::x3::variant const& x) BOOST_NOEXCEPT { return boost::get(x.get()); } template inline T& get(boost::spirit::x3::variant& x) BOOST_NOEXCEPT { return boost::get(x.get()); } template inline T const* get(boost::spirit::x3::variant const* x) BOOST_NOEXCEPT { return boost::get(&x->get()); } template inline T* get(boost::spirit::x3::variant* x) BOOST_NOEXCEPT { return boost::get(&x->get()); } } #endif