...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::variant — Safe, generic, stack-based discriminated union container.
// In header: <boost/variant/variant.hpp> template<typename T1, typename T2 = unspecified, ..., typename TN = unspecified> class variant { public: // types typedef unspecified types; // construct/copy/destruct variant(); variant(const variant &); variant(variant &&); template<typename T> variant(T &); template<typename T> variant(const T &); template<typename T> variant(T &&); template<typename U1, typename U2, ..., typename UN> variant(variant<U1, U2, ..., UN> &); template<typename U1, typename U2, ..., typename UN> variant(const variant<U1, U2, ..., UN> &); template<typename U1, typename U2, ..., typename UN> variant(variant<U1, U2, ..., UN> &&); ~variant(); // modifiers void swap(variant &); variant & operator=(const variant &); variant & operator=(variant &&); template<typename T> variant & operator=(const T &); template<typename T> variant & operator=(T &&); // queries int which() const; bool empty() const; const std::type_info & type() const; // relational bool operator==(const variant &) const; template<typename U> void operator==(const U &) const; bool operator!=(const variant &) const; template<typename U> void operator!=(const U &) const; bool operator<(const variant &) const; template<typename U> void operator<(const U &) const; bool operator>(const variant &) const; template<typename U> void operator>(const U &) const; bool operator<=(const variant &) const; template<typename U> void operator<=(const U &) const; bool operator>=(const variant &) const; template<typename U> void operator>=(const U &) const; };
The variant
class template (inspired by Andrei
Alexandrescu's class of the same name
[Ale01A]) is an efficient,
recursive-capable,
bounded discriminated union value type capable of containing any value
type (either POD or non-POD). It supports construction from any type
convertible to one of its bounded types or from a source
variant
whose bounded types are each convertible to one
of the destination variant
's bounded types. As well,
through apply_visitor
,
variant
supports compile-time checked, type-safe
visitation; and through get
,
variant
supports run-time checked, type-safe value
retrieval.
Notes:
variant
are exposed
via the nested typedef types
, which is an
MPL-compatible Sequence containing the
set of types that must be handled by any
visitor to
the variant
.variant
satisfy at least the
basic guarantee of exception-safety. That is, all operations on
a variant
remain defined even after previous
operations have failed.variant
must meet the requirements of the
BoundedType
concept.variant
must be distinct after removal of qualifiers.
Thus, for instance, both variant
and
variant
have undefined
behavior.variant
must
allow at least ten types as template arguments. The exact number
of allowed arguments is exposed by the preprocessor macro
BOOST_VARIANT_LIMIT_TYPES
.
(See make_variant_over
for a
means to specify the bounded types of a variant
by
the elements of an MPL or compatible
Sequence, thus overcoming this limitation.)variant
public
construct/copy/destructvariant();
Requires: |
The first bounded type of the variant (i.e.,
T1 ) must fulfill the requirements of the
DefaultConstructible [20.1.4]
concept. |
Postconditions: |
Content of *this is the default value of the
first bounded type (i.e, T1 ). |
Throws: |
May fail with any exceptions arising from the default
constructor of T1 . |
variant(const variant & other);
Postconditions: |
Content of *this is a copy of the content of
other . |
Throws: |
May fail with any exceptions arising from the
copy constructor of other 's contained type. |
variant(variant && other);
Requires: |
C++11 compatible compiler. |
Postconditions: |
Content of *this is move constructed from the content of
other . |
Throws: |
May fail with any exceptions arising from the
move constructor of other 's contained type. |
template<typename T> variant(T & operand);
Requires: |
T must be unambiguously convertible to one of
the bounded types (i.e., T1 , T2 ,
etc.). |
Postconditions: |
Content of *this is the best conversion of
operand to one of the bounded types, as determined
by standard overload resolution rules. |
Throws: |
May fail with any exceptions arising from the conversion of
operand to one of the bounded types. |
template<typename T> variant(const T & operand);
Notes: |
Same semantics as previous constructor, but allows construction from temporaries. |
template<typename T> variant(T && operand);
Requires: |
C++11 compatible compiler. |
Notes: |
Same semantics as previous constructor, but allows
move construction if operand is an rvalue. |
template<typename U1, typename U2, ..., typename UN> variant(variant<U1, U2, ..., UN> & operand);
Requires: |
Every one of U1 ,
U2 , ..., UN must have an unambiguous
conversion to one of the bounded types (i.e., T1 ,
T2 , ..., TN ). |
Postconditions: |
If variant is itself
one of the bounded types, then content of *this is a
copy of operand . Otherwise, content of
*this is the best conversion of the content of
operand to one of the bounded types, as determined
by standard overload resolution rules. |
Throws: |
If variant is itself
one of the bounded types, then may fail with any exceptions arising
from the copy constructor of
variant . Otherwise, may fail
with any exceptions arising from the conversion of the content of
operand to one of the bounded types. |
template<typename U1, typename U2, ..., typename UN> variant(const variant<U1, U2, ..., UN> & operand);
Notes: |
Same semantics as previous constructor, but allows construction from temporaries. |
template<typename U1, typename U2, ..., typename UN> variant(variant<U1, U2, ..., UN> && operand);
Requires: |
C++11 compatible compiler. |
Notes: |
Same semantics as previous constructor, but allows move construction. |
~variant();
Effects: |
Destroys the content of *this . |
Throws: |
Will not throw. |
variant
modifiersvoid swap(variant & other);
Requires: |
Every bounded type must fulfill the requirements of the MoveAssignable concept. |
Effects: |
Interchanges the content of *this and
other . |
Throws: |
If the contained type of other is the same as
the contained type of *this , then may fail with any
exceptions arising from the swap of the contents of
*this and other . Otherwise, may fail
with any exceptions arising from either of the move or copy constructors
of the contained types. Also, in the event of insufficient
memory, may fail with std::bad_alloc
(why?). |
variant & operator=(const variant & rhs);
Requires: |
Every bounded type must fulfill the requirements of the Assignable concept. |
Effects: |
If the contained type of rhs is the same as
the contained type of *this , then assigns the
content of rhs into the content of
*this . Otherwise, makes the content of
*this a copy of the content of rhs ,
destroying the previous content of *this . |
Throws: |
If the contained type of rhs is the same as
the contained type of *this , then may fail with any
exceptions arising from the assignment of the content of
rhs into the content *this . Otherwise,
may fail with any exceptions arising from the copy constructor
of the contained type of rhs . Also, in the event of
insufficient memory, may fail with std::bad_alloc
(why?). |
variant & operator=(variant && rhs);
Requires: |
|
Effects: |
If the contained type of rhs is the same as
the contained type of *this , then move assigns the
content of rhs into the content of
*this . Otherwise, move constructs
*this using the content of rhs ,
destroying the previous content of *this . |
Throws: |
If the contained type of rhs is the same as
the contained type of *this , then may fail with any
exceptions arising from the move assignment of the content of
rhs into the content *this . Otherwise,
may fail with any exceptions arising from the move constructor
of the contained type of rhs . Also, in the event of
insufficient memory, may fail with std::bad_alloc
(why?). |
template<typename T> variant & operator=(const T & rhs);
Requires: |
|
Effects: |
If the contained type of *this is
T , then assigns rhs into the content
of *this . Otherwise, makes the content of
*this the best conversion of rhs to
one of the bounded types, as determined by standard overload
resolution rules, destroying the previous content of
*this . |
Throws: |
If the contained type of *this is
T , then may fail with any exceptions arising from
the assignment of rhs into the content
*this . Otherwise, may fail with any exceptions
arising from the conversion of rhs to one of the
bounded types. Also, in the event of insufficient memory, may
fail with std::bad_alloc
(why?). |
template<typename T> variant & operator=(T && rhs);
Requires: |
|
Effects: |
If the contained type of *this is
T , then move assigns rhs into the content
of *this . Otherwise, makes the content of
*this the best conversion of rhs to
one of the bounded types, as determined by standard overload
resolution rules, destroying the previous content of
*this (conversion is usually done via move construction). |
Throws: |
If the contained type of *this is
T , then may fail with any exceptions arising from
the move assignment of rhs into the content
*this . Otherwise, may fail with any exceptions
arising from the conversion of rhs to one of the
bounded types. Also, in the event of insufficient memory, may
fail with std::bad_alloc
(why?). |
variant
queriesint which() const;
Returns: |
The zero-based index into the set of bounded types
of the contained type of *this . (For instance, if
called on a variant object
containing a std::string , which()
would return 1 .) |
Throws: |
Will not throw. |
bool empty() const;
Returns: |
false : variant always contains
exactly one of its bounded types. (See
the section called “"Never-Empty" Guarantee”
for more information.) |
Rationale: |
Facilitates generic compatibility with boost::any. |
Throws: |
Will not throw. |
const std::type_info & type() const;
Notes: |
boost::variant usues Boost.TypeIndex library so actually
const boost::typeindex::type_info & is returned.
This method is available even if RTTI is off. |
Returns: |
typeid(x) , where x is the the
content of *this . |
Throws: |
Will not throw. |
variant
relationalbool operator==(const variant & rhs) const; template<typename U> void operator==(const U &) const;Equality comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
EqualityComparable
concept. |
Returns: |
true if which() == rhs.which()
and
content_this == content_rhs , where
content_this is the content of *this
and content_rhs is the content of
rhs . |
Throws: |
If which() == rhs.which() then may fail with
any exceptions arising from operator==(T,T) , where
T is the contained type of
*this . |
bool operator!=(const variant & rhs) const; template<typename U> void operator!=(const U &) const;InEquality comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
EqualityComparable
concept. |
Returns: |
true if !(*this == rhs) . |
Throws: |
If which() == rhs.which() then may fail with
any exceptions arising from operator==(T,T) , where
T is the contained type of
*this . |
bool operator<(const variant & rhs) const; template<typename U> void operator<(const U &) const;LessThan comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
LessThanComparable
concept. |
Returns: |
If which() == rhs.which() then:
content_this < content_rhs , where
content_this is the content of *this
and content_rhs is the content of rhs .
Otherwise: which() < rhs.which() . |
Throws: |
If which() == rhs.which() then may fail with
any exceptions arising from operator<(T,T) ,
where T is the contained type of
*this . |
bool operator>(const variant & rhs) const; template<typename U> void operator>(const U &) const;GreaterThan comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
LessThanComparable
concept. |
Returns: |
true if rhs < *this . |
Throws: |
May fail with
any exceptions arising from operator<(T,T) ,
where T is the contained type of
*this . |
bool operator<=(const variant & rhs) const; template<typename U> void operator<=(const U &) const;LessThan or Equal comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
LessThanComparable
concept. |
Returns: |
true if !(*this > rhs) . |
Throws: |
May fail with
any exceptions arising from operator<(T,T) ,
where T is the contained type of
*this . |
bool operator>=(const variant & rhs) const; template<typename U> void operator>=(const U &) const;GreaterThan or Equal comparison.
Notes: |
The overload returning void exists only to
prohibit implicit conversion of the operator's right-hand side
to variant ; thus, its use will (purposefully)
result in a compile-time error. |
Requires: |
Every bounded type of the variant must
fulfill the requirements of the
LessThanComparable
concept. |
Returns: |
true if !(*this < lhs) . |
Throws: |
May fail with
any exceptions arising from operator<(T,T) ,
where T is the contained type of
*this . |