| Home | Libraries | People | FAQ | More

## Class template variant

boost::variant — Safe, generic, stack-based discriminated union container.

## Synopsis

    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;
    };

## Description

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:

- The bounded types of the `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`.
- All members of `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.
- Each type specified as a template argument to `variant` must meet the requirements of the BoundedType concept.
- Each type specified as a template argument to `variant` must be distinct after removal of qualifiers. Thus, for instance, both `variant<int, int>` and `variant<int, const int>` have undefined behavior.
- Conforming implementations of `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` construct/copy/destruct

1.     variant();

   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`.

2.     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.

3.     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.

4.     template<typename T> variant(const T & operand);

   Notes: Same semantics as previous constructor, but allows construction from temporaries.

5.     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.

6.     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.

7.     ~variant();

   Effects: Destroys the content of `*this`.
   Throws: Will not throw.

### `variant` modifiers

1.     void 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?).

2.     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?).

3.     template<typename T> variant & operator=(const T & rhs);

   Requires:

   - `T` must be unambiguously convertible to one of the bounded types (i.e., `T1`, `T2`, etc.).
   - Every bounded type must fulfill the requirements of the Assignable concept.
   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` queries

1.     int 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.

2.     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.

3.     const std::type_info & type() const;

   Returns: `typeid(x)`, where `x` is the the content of `*this`.
   Throws: Will not throw.

### `variant` relational

1.     bool operator==(const variant & rhs) const;
       template<typename U> void operator==(const U & ) const;

   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`.

2.     bool operator<(const variant & rhs) const;
       template<typename U> void operator<(const U & ) const;

   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`.

| Copyright © 2002, 2003 Eric Friedman, Itay Maman