...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 &); template<typename T> variant(T &); template<typename T> variant(const 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> &); ~variant(); // modifiers void swap(variant &); variant & operator=(const variant &); template<typename T> variant & operator=(const 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; };
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<int, int>
and
variant<int, const int>
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. |
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 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<U1, U2, ..., UN> 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<U1, U2, ..., UN> is itself
one of the bounded types, then may fail with any exceptions arising
from the copy constructor of
variant<U1, U2, ..., UN> . 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. |
~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 Assignable 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 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?). |
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?). |
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<int, std::string> 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;
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 iff 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;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 . |