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 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") }