📄 variant.hpp
字号:
// For compilers that cannot distinguish between T& and const T& in // template constructors, and do NOT support SFINAE, we can't workaround: template <typename T> variant(const T& operand) { convert_construct(operand, 1L); }#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workaroundspublic: // structors, cont. // [MSVC6 requires copy constructor appear after template constructors] variant(const variant& operand) { // Copy the value of operand into *this... detail::variant::copy_into visitor( storage_.address() ); operand.internal_apply_visitor(visitor); // ...and activate the *this's primary storage on success: indicate_which(operand.which()); }private: // helpers, for modifiers (below)# if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template <typename Variant, typename RhsT> friend class detail::variant::backup_assigner;# endif // class assigner // // Internal visitor that "assigns" the visited value to the given variant // by appropriate destruction and copy-construction. // class assigner : public static_visitor<> { private: // representation variant& lhs_; int rhs_which_; public: // structors assigner(variant& lhs, int rhs_which) : lhs_(lhs) , rhs_which_(rhs_which) { } private: // helpers, for internal visitor interface (below) template <typename RhsT, typename B1, typename B2> void assign_impl( const RhsT& rhs_content , mpl::true_// has_nothrow_copy , B1// has_nothrow_move_constructor , B2// has_fallback_type ) { // Destroy lhs's content... lhs_.destroy_content(); // nothrow // ...copy rhs content into lhs's storage... new(lhs_.storage_.address()) RhsT( rhs_content ); // nothrow // ...and indicate new content type: lhs_.indicate_which(rhs_which_); // nothrow } template <typename RhsT, typename B> void assign_impl( const RhsT& rhs_content , mpl::false_// has_nothrow_copy , mpl::true_// has_nothrow_move_constructor , B// has_fallback_type ) { // Attempt to make a temporary copy (so as to move it below)... RhsT temp(rhs_content); // ...and upon success destroy lhs's content... lhs_.destroy_content(); // nothrow // ...move the temporary copy into lhs's storage... new(lhs_.storage_.address()) RhsT( detail::variant::move(temp) ); // nothrow // ...and indicate new content type: lhs_.indicate_which(rhs_which_); // nothrow } template <typename RhsT> void assign_impl( const RhsT& rhs_content , mpl::false_// has_nothrow_copy , mpl::false_// has_nothrow_move_constructor , mpl::true_// has_fallback_type ) { // Destroy lhs's content... lhs_.destroy_content(); // nothrow try { // ...and attempt to copy rhs's content into lhs's storage: new(lhs_.storage_.address()) RhsT( rhs_content ); } catch (...) { // In case of failure, default-construct fallback type in lhs's storage... new (lhs_.storage_.address()) fallback_type_; // nothrow // ...indicate construction of fallback type... lhs_.indicate_which( BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value ); // nothrow // ...and rethrow: throw; } // In the event of success, indicate new content type: lhs_.indicate_which(rhs_which_); // nothrow } template <typename RhsT> void assign_impl( const RhsT& rhs_content , mpl::false_// has_nothrow_copy , mpl::false_// has_nothrow_move_constructor , mpl::false_// has_fallback_type ) { detail::variant::backup_assigner<wknd_self_t, RhsT> visitor(lhs_, rhs_which_, rhs_content); lhs_.internal_apply_visitor(visitor); } public: // internal visitor interfaces template <typename RhsT> BOOST_VARIANT_AUX_RETURN_VOID_TYPE internal_visit(const RhsT& rhs_content, int) { typedef typename has_nothrow_copy<RhsT>::type nothrow_copy; typedef typename mpl::or_< // reduces compile-time nothrow_copy , detail::variant::has_nothrow_move_constructor<RhsT> >::type nothrow_move_constructor; assign_impl( rhs_content , nothrow_copy() , nothrow_move_constructor() , has_fallback_type_() ); BOOST_VARIANT_AUX_RETURN_VOID; } }; friend class assigner; void variant_assign(const variant& rhs) { // If the contained types are EXACTLY the same... if (which_ == rhs.which_) { // ...then assign rhs's storage to lhs's content: detail::variant::assign_storage visitor(rhs.storage_.address()); this->internal_apply_visitor(visitor); } else { // Otherwise, perform general (copy-based) variant assignment: assigner visitor(*this, rhs.which()); rhs.internal_apply_visitor(visitor); } }private: // helpers, for modifiers (below) template <typename T> void assign(const T& rhs) { // If direct T-to-T assignment is not possible... detail::variant::direct_assigner<const T> direct_assign(rhs); if (this->apply_visitor(direct_assign) == false) { // ...then convert rhs to variant and assign: // // While potentially inefficient, the following construction of a // variant allows T as any type convertible to one of the bounded // types without excessive code redundancy. // variant temp(rhs); variant_assign( detail::variant::move(temp) ); } }public: // modifiers template <typename T> variant& operator=(const T& rhs) { assign(rhs); return *this; } // [MSVC6 requires copy assign appear after templated operator=] variant& operator=(const variant& rhs) { variant_assign(rhs); return *this; } void swap(variant& rhs) { // If the contained types are the same... if (which() == rhs.which()) { // ...then swap the values directly: detail::variant::swap_with<variant> visitor(rhs); this->apply_visitor(visitor); } else { // ...otherwise, perform general variant swap: variant tmp( detail::variant::move(rhs) ); rhs = detail::variant::move(*this); *this = detail::variant::move(tmp); } }public: // queries // // NOTE: member which() defined above. // bool empty() const { return false; } const std::type_info& type() const { detail::variant::reflect visitor; return this->apply_visitor(visitor); }public: // prevent comparison with foreign types#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \ void#else // MSVC7 // // MSVC7 gives error about return types for above being different than // the true comparison operator overloads: //# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \ bool#endif // MSVC7 workaround template <typename U> BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE operator==(const U&) const { BOOST_STATIC_ASSERT( false && sizeof(U) ); } template <typename U> BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE operator<(const U&) const { BOOST_STATIC_ASSERT( false && sizeof(U) ); }public: // comparison operators // [MSVC6 requires these operators appear after template operators] bool operator==(const variant& rhs) const { if (this->which() != rhs.which()) return false; detail::variant::comparer< variant, detail::variant::equal_comp > visitor(*this); return rhs.apply_visitor(visitor); } bool operator<(const variant& rhs) const { // // Dirk Schreib suggested this collating order. // if (this->which() != rhs.which()) return this->which() < rhs.which(); detail::variant::comparer< variant, detail::variant::less_comp > visitor(*this); return rhs.apply_visitor(visitor); }// helpers, for visitation support (below) -- private when possible#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template < BOOST_VARIANT_ENUM_PARAMS(typename U) > friend class variant;private:#else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)public:#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template <typename Visitor, typename VoidPtrCV> static BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( typename Visitor::result_type ) internal_apply_visitor_impl( int internal_which , int logical_which , Visitor& visitor , VoidPtrCV storage ) { typedef mpl::int_<0> first_which; typedef typename mpl::begin<internal_types>::type first_it; typedef typename mpl::end<internal_types>::type last_it; typedef detail::variant::visitation_impl_step< first_it, last_it > first_step; return detail::variant::visitation_impl( internal_which, logical_which , visitor, storage, mpl::false_() , never_uses_backup_flag() , static_cast<first_which*>(0), static_cast<first_step*>(0) ); } template <typename Visitor> BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( typename Visitor::result_type ) internal_apply_visitor(Visitor& visitor) { return internal_apply_visitor_impl( which_, which(), visitor, storage_.address() ); } template <typename Visitor> BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( typename Visitor::result_type ) internal_apply_visitor(Visitor& visitor) const { return internal_apply_visitor_impl( which_, which(), visitor, storage_.address() ); }public: // visitation support template <typename Visitor> BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( typename Visitor::result_type ) apply_visitor(Visitor& visitor) { detail::variant::invoke_visitor<Visitor> invoker(visitor); return this->internal_apply_visitor(invoker); } template <typename Visitor> BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE( typename Visitor::result_type ) apply_visitor(Visitor& visitor) const { detail::variant::invoke_visitor<Visitor> invoker(visitor); return this->internal_apply_visitor(invoker); }}; // class variant///////////////////////////////////////////////////////////////////////////////// metafunction make_variant_over//// See docs and boost/variant/variant_fwd.hpp for more information.//template <typename Types>struct make_variant_over{private: // precondition assertions#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));#endifpublic: // metafunction result typedef variant< detail::variant::over_sequence< Types > > type;};///////////////////////////////////////////////////////////////////////////////// function template swap//// Swaps two variants of the same type (i.e., identical specification).//template < BOOST_VARIANT_ENUM_PARAMS(typename T) >inline void swap( variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs ){ lhs.swap(rhs);}} // namespace boost// implementation additions#include "boost/variant/detail/variant_io.hpp"#endif // BOOST_VARIANT_VARIANT_HPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -