📄 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 workarounds
public: // 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 ));
#endif
public: // 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 + -