Chapter 41. Boost.Variant

| Home | Libraries | People | FAQ | More

## Chapter 41. Boost.Variant

### Eric Friedman

### Itay Maman

Copyright © 2002, 2003 Eric Friedman, Itay Maman

Distributed under the Boost Software License, Version 1.0. (See accompanying file `LICENSE_1_0.txt` or copy at http://www.boost.org/LICENSE_1_0.txt)

## Introduction

### Abstract

The `variant` class template is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner. Whereas standard containers such as `std::vector` may be thought of as "multi-value, single type," `variant` is "multi-type, single value."

Notable features of `boost::variant` include:

- Full value semantics, including adherence to standard overload resolution rules for conversion operations.
- Compile-time type-safe value visitation via `boost::apply_visitor`.
- Run-time checked explicit value retrieval via `boost::get`.
- Support for recursive variant types via both `boost::make_recursive_variant` and `boost::recursive_wrapper`.
- Efficient implementation -- stack-based when possible (see the section called “"Never-Empty" Guarantee” for more details).

### Motivation

#### Problem

Many times, during the development of a C++ program, the programmer finds himself in need of manipulating several distinct types in a uniform manner. Indeed, C++ features direct language support for such types through its `union` keyword:

    union { int i; double d; } u;
    u.d = 3.14;
    u.i = 3; // overwrites u.d (OK: u.d is a POD type)

C++'s `union` construct, however, is nearly useless in an object-oriented environment. The construct entered the language primarily as a means for preserving compatibility with C, which supports only POD (Plain Old Data) types, and so does not accept types exhibiting non-trivial construction or destruction:

    union {
      int i;
      std::string s; // illegal: std::string is not a POD type!
    } u;

Clearly another approach is required. Typical solutions feature the dynamic-allocation of objects, which are subsequently manipulated through a common base type (often a virtual base class [Hen01] or, more dangerously, a `void*`). Objects of concrete type may be then retrieved by way of a polymorphic downcast construct (e.g., `dynamic_cast`, `boost::any_cast`, etc.).

However, solutions of this sort are highly error-prone, due to the following:

- Downcast errors cannot be detected at compile-time. Thus, incorrect usage of downcast constructs will lead to bugs detectable only at run-time.
- Addition of new concrete types may be ignored. If a new concrete type is added to the hierarchy, existing downcast code will continue to work as-is, wholly ignoring the new type. Consequently, the programmer must manually locate and modify code at numerous locations, which often results in run-time errors that are difficult to find.

Furthermore, even when properly implemented, these solutions tend to incur a relatively significant abstraction penalty due to the use of the heap, virtual function calls, and polymorphic downcasts.

#### Solution: A Motivating Example

The `boost::variant` class template addresses these issues in a safe, straightforward, and efficient manner. The following example demonstrates how the class can be used:

    #include "boost/variant.hpp"
    #include <iostream>

    class my_visitor : public boost::static_visitor<int>
    {
    public:
        int operator()(int i) const
        {
            return i;
        }

        int operator()(const std::string & str) const
        {
            return str.length();
        }
    };

    int main()
    {
        boost::variant< int, std::string > u("hello world");
        std::cout << u; // output: hello world

        int result = boost::apply_visitor( my_visitor(), u );
        std::cout << result; // output: 11 (i.e., length of "hello world")
    }