2
0
mirror of https://github.com/boostorg/variant.git synced 2026-01-27 19:32:15 +00:00
Files
variant/doc/reference.html
Eric Friedman 4aaf6a2b43 Minor fixes and changes.
[SVN r19370]
2003-07-30 20:48:05 +00:00

521 lines
22 KiB
HTML
Raw Blame History

<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../../index.htm"> <img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a>
</h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">Reference</h2>
</td>
</tr>
</table>
<hr>
<p></p>
<ul>
<li><a href="#Synopsis">Synopsis</a></li>
<li><a href="#BoundedType">BoundedType Concept</a></li>
<li><a href="#Visitor">Visitor Concept</a></li>
<li><a HREF="#BoostVariantLimitTypes">BOOST_VARIANT_LIMIT_TYPES</a></li>
<li><a href="#variant"><code>boost::variant</code></li>
<li><a href="#Visitation"><code>boost::apply_visitor</code></a></li>
<li><a href="#StaticVisitor"><code>boost::static_visitor</code></a></li>
<li><a href="#ValueExtraction"><code>boost::get</code></a></li>
<li><a href="#incomplete"><code>boost::incomplete</code></a></li>
<li><a href="#empty"><code>boost::empty</code></a></li>
</ul>
<hr>
<h3><a name="Synopsis">Synopsis</a></h3>
<p>Dependencies and library features defined in <a href="../../../boost/variant.hpp">
&quot;<code>boost/variant.hpp</code>&quot;</a>:
</p>
<pre>
#define <a href="#BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a> <i>implementation-defined</i>
namespace boost
{
template
&lt;
typename T1 = boost::empty,
typename T2 = <em>implementation-defined</em>,
...
typename T<i>n</i> = <em>implementation-defined</em>
&gt;
class <a href="#variant">variant</a>;
template &lt;typename T1, typename T2, ... , typename T<i>n</i>&gt;
void swap(
variant&lt;T1,T2, ... ,T<i>n</i>&gt;&amp;,
variant&lt;T1,T2, ... ,T<i>n</i>&gt;&amp;);
template
&lt;
BOOST_TEMPLATED_STREAM_ARGS(E,T),
BOOST_TEMPLATED_STREAM_COMMA
typename U1, typename U2, ..., typename U<i>n</i>
&gt;
BOOST_TEMPLATED_STREAM(ostream, E, T)&
operator&lt;&lt;(BOOST_TEMPLATED_STREAM(ostream, E, T)& out,
const variant&lt;U1,U2, ..., U<i>n</i>&gt;&amp; v);
}
</pre>
<p>Test harnesses provided in <code>&quot;libs/variant/test&quot;</code> directory.</p>
<p></p>
<hr>
<h2><a name="BoundedType"><i>BoundedType</i>&nbsp;Concept</a></h2>
<p>Given <a href="#variant"><code>variant</code></a><code>&lt;T1,T2,...,T<i>n</i>&gt;</code>,
each type <code>T<i>i</i></code> is a <b>bounded type</b> of the <code>variant</code>.</p>
<p>The requirements on bounded types are as follows:</p>
<ul>
<li><em>CopyConstructible</em> [20.1.3].</li>
<LI><em><a href="../../utility/Assignable.html">Assignable</em></a>.</LI>
<li>Destructor upholds the no-throw exception-safety guarantee.</li>
<li>Not top-level <code>const</code>-qualified.</li>
<li>Not a reference type</li>
<li>Complete at the point of variant template instantiation.
(See <code><a href="#incomplete"> incomplete&lt;T&gt;</a></code>
wrapper for a solution to containing incomplete types.)</li>
</ul>
<p>Additional requirements on the first type T1:</p>
<ul>
<li>If <code>T1</code> is a
<a href="../../mpl/doc/ref/Sequences.html"><code>boost::mpl</code></a>
sequence,and no other types are specified (i.e: <i>n</i> = 1),
then the instantiated variant will use the types contained in
<code>T1</code> as its <em>Bounded Types</em>.
</li>
<li><code>T1</code> must be <em>DefaultConstructible</em> [20.1.4]
if the <code>variant</code> is expected to be default constructible.
</li>
</ul>
<hr>
<h2><a name="Visitor"><i>Visitor</i> Concept</a></h2>
<p>Given <a href="#variant"><code>variant</code></a><code>&lt;T1,T2,...,T<i>n</i>&gt;</code>,
a function object which unambiguously accepts any value of
each of the variant's <A HREF=#BoundedType">bounded types</A>, is a
<B>Visitor</B> of of the <CODE>variant</CODE>.
<p>Additional requirements on visitors are as follows:</p>
<ul>
<li>
Must expose inner type <code>result_type</code>,
or - alternatively - derive from
<a href="#StaticVisitor"><code>static_visitor</code></a>.
<!-- (See <code><a href="#visitor_ptr">visitor_ptr</a></code>
wrapper for a solution to functions as visitors.)--> </li>
<li>
Each overload of <code>operator()</code>must return a value
that is implicitly-convertible to <code>result_type</code>.</li>
</ul>
<h3><b>Examples:</b></h3>
<p>The following class is a visitor of a number of <code>variant</code> types
(e.g., explicitly: <code>variant&lt;int,std::string&gt;</code>, or implicitly: <code>
variant&lt;short,std::string&gt;</code>, etc.):</p>
<pre>class my_visitor
{
typedef int result_type;
int operator()(int i)
{
return i * 2;
}
int operator()(const std::string&amp; s)
{
return s.length();
}
};</pre>
<p>Another example is the following class, which exposes a templated
function call operator, allowing it to operate on values of many types.
Thus, the following class is a visitor of any <code>variant</code>
whose bounded types each support streaming output:</p>
<pre>class printer
{
typedef void result_type;
template &lt;typename T&gt;
void operator()(const T&amp; t)
{
std::cout &lt;&lt; t &lt;&lt; '\n';
}
};</pre>
<hr>
<h3><a name="BoostVariantLimitTypes">BOOST_VARIANT_LIMIT_TYPES</a></h3>
<pre>#define BOOST_VARIANT_LIMIT_TYPES <i>implementation-defined</i></pre>
<p><i>Implementation-defined</i>. Equal to the length of the template parameter
list for <code>variant</code>.</p>
<p><b>Note:</b> Conforming implementations of <code>variant</code> must allow at
least ten bounded types. That is, <code>BOOST_VARIANT_LIMIT_TYPES &gt;= 10</code>
must evaluate true.</p>
<hr>
<h2><a name="variant"><code>boost::variant</code></a></h2>
<pre>template
&lt;
typename T1 = boost::empty,
typename T2 = <em>implementation-defined</em>,
...
typename T<i>n</i> = <em>implementation-defined</em>
&gt;
class variant
{
public: // <i><a href="#variant-structors">structors</a></i>
<a href="#variant-default-ctor">variant</a>();
<a href="#variant-copy-ctor">variant</a>(const variant &amp;);
template &lt;typename OperandType&gt;
<a href="#variant-template-ctor">variant</a>(const OperandType &amp;);
<a href="#dtor">~variant</a>();
public: // <i><a href="#variant-modifiers">modifiers</a></i>
variant &amp; <a href="#variant-swap">swap</a>(variant &amp;);
variant &amp; <a href="#variant-copy-assign">operator=</a>(const variant &amp;);
template &lt;typename OperandType&gt;
variant &amp; <a href="#variant-template-assign">operator=</a>(const OperandType &amp;);
public: // <i><a href="#variant-queries">queries</a></i>
int <a href="#variant-which">which</a>() const;
const std::type_info &amp; <a href="#variant-type">type</a>() const;
bool <a href="#variant-empty">empty</a>() const;
private: // <i>representation</i>
...
};</pre>
<p>An instance of <code>variant</code> contains exactly one instance of one of its
bounded types, which are specified as arguments to <code>variant</code>'s
template parameter list. The length of <code>variant</code>'s template
parameter list is equal to the implementation defined value <a href="#BOOST_VARIANT_LIMIT_TYPES">
<code>BOOST_VARIANT_LIMIT_TYPES</code></a>.</p>
<p>Each type specified as a bounded type must satisfy the <a href="#BoundedType"><i>BoundedType</i></a>
requirements. Note that&nbsp; <code>variant</code> itself satisfies <a href="#BoundedType">
<i>BoundedType</i></a> requirements with default construction.
</p>
<p>All members of <code>variant</code> satisfy the strong guarantee of
exception-safety.</p>
<blockquote>
<hr>
<h3><a name="variant-structors">Structors</a></h3>
<pre><a name="variant-default-ctor">variant</a>();</pre>
<p>Default constructor. Initializes <code>*this</code> with the default value of
the first bounded type (i.e, <code>T1</code>). May fail with any exceptions
arising from the default constructor of <code>T1</code>.<br>
</p>
<pre><a name="variant-copy-ctor">variant</a>(const variant&amp; other);
</pre>
<p>Copy constructor. Copies the content of <code>other</code> into <code>*this</code>.
May fail with any exceptions arising from the copy constructor of <code>other</code>'s
contained type.<br>
</p>
<a name="variant-template-ctor"></a>
<pre>template &lt;typename OperandType&gt;
variant(const OperandType &amp; operand);
</pre>
<p>Templated constructor. Initializes <code>*this</code> according to the following
logic:</p>
<ol>
<li>
If <code>OperandType</code> is <b>not a <code>variant</code></b>:<ul>
<li>
If <code>OperandType</code> is one of the bounded types of the <code>variant</code>,
initialize <code>*this</code> with a copy of <code>operand</code>.</li>
<li>
Otherwise, use overload resolution rules to find the best conversion for <code>OperandType</code>,
and initialize <code>*this</code> with a copy of the converted <code>operand</code>.
(However, if the conversion is ambiguous, or if none exists, a compiler error
is generated.)</li>
</ul>
</li>
<li>
Otherwise (i.e: <code>OperandType</code> <b>is a <code>variant</code></b>):
<ul>
<li>
If <code>OperandType</code> does not appear on <code>*this</code>'s set of
types, then <code>*this</code> is initialized with <code>operand</code>'s held
value (as described in item 1, above).</li>
<li>
Otherwise, <code>operand</code> is assigned, as-is, into <code>*this</code>.
Hence, the held value of <code>*this</code> is, by itself, a variant.</li>
</ul>
</li>
</ol>
<p>May fail with any exceptions arising from the copy constructor of <code>OperandType</code>.<br>
</p>
<pre><a name="variant-dtor">~variant</a>();
</pre>
<p>Non-throwing destructor that releases all resources used in management of <code>*this</code>,
including the currently contained value.
</p>
<a name="variant-modifiers"><h3>Modifiers</h3></a>
<pre>void <a name="variant-swap">swap</a>(variant&amp; other);
</pre>
<p>Exchanges contents of <code>*this</code> and <code>other</code>. May fail with
any exceptions arising from the copy constructors of the contained types of <code>*this</code>
or <code>other</code>, or from the swap primitive of the held values, if <code>this-&gt;type()
== other.type()</code>.<br>
</p>
<pre>variant&amp; <a name="variant-copy-assign">operator=</a>(const variant&amp; rhs);
</pre>
<p>Copy assignment. Assigns <code>rhs</code>'s contained value into <code>*this</code>.
The old value contained by <code>*this</code> is properly destroyed.</p>
<p>Note: this operator follows the same logic as the <a href="#CopyConstructor">copy
constructor</a>.</p>
<a name="variant-template-assign"></a>
<pre>template&lt;class OperandType&gt;
variant&amp; operator=(const OperandType &amp;);
</pre>
<p>Templated assignment. Assigns <code>rhs</code> into <code>*this</code>. The old
value held by <code>*this</code> is properly destroyed.</p>
<p>Note: This operator follows the same logic as the <a href="#TemplatedConstructor">templated
constructor</a>.</p>
<a name="variant-queries"><h3>Queries</h3></a>
<a name="variant-type"></a>
<pre>const std::type_info &amp; type() const;</pre>
<p>Non-throwing query that returns the <code>typeid()</code> of the contained value</p>
<a name="variant-empty"></a>
<pre>bool empty() const;</pre>
<p>Non-throwing query that returns <code>true</code> if, and
only if, the held value is of type
<a href="#empty"><code>boost::empty</code></a>.<br>
Consequently, if <code>boost::empty</code> is not one of the
<a href="#BoundedType">BoundedTypes</a>, then
<code>empty()</code> will always yield <code>false</code>.</p>
<a name="variant-which"></a>
<pre>int which() const;</pre>
<p>Non-throwing query that returns the zero-based index of the bounded type of the
contained value.<br>
</p>
</blockquote>
<hr>
<h2><a name="Visitation">Visitation: <code>apply_visitor</code></a></h2>
<pre>// Binary form
template&lt;typename VisitorType, typename VariantType&gt;
typename VisitorType::result_type apply_visitor(VisitorType&amp; visitor,
VariantType&amp; var_inst);
// Unary form
template&lt;class VisitorType&gt;
boost::apply_visitor_t&lt;VisitorType&gt; apply_visitor(VisitorType&amp; visitor);
template &lt;typename VisitorType&gt;
class apply_visitor_t
{
public:
typedef typename VisitorType::result_type result_type;
template &lt;typename VariantType&gt;
result_type operator()(VariantType&amp; var_inst);
...
};
</pre>
<p><code>boost::apply_visitor(visitor, var_inst)</code> passes the variant object, <code>
var_inst</code>, to the given visitor (<code>visitor</code>). This is
equivalent to calling <code>visitor</code>'s function-call operator, with <code>var_inst</code>'s
currently held value.<br>
<code>VisitorType</code> must be a <a href="#Visitor">visitor of</a> <code>VariantType</code>.
See <a HREF="tutorial.html#FunctorBasedVisitation">Functor-based visitation</a>
for an in-depth description of visitors.<br>
<br>
The unary form of <code>apply_visitor()</code> tranforms the given visitor into
a unary function object which accepts a variant object, thus, the following two
lines are equivalent:<br>
</p>
<pre> boost::apply_visitor(visitor, var_inst); // Binary form
boost::apply_visitor(visitor)(var_inst); // Unary form
</pre>
<p>Consequently, the unary <code>apply_visitor()</code> function, is highly useful
when <code>std::for_each</code> (or a similar STL algorithm) needs to be
applied on a sequence of <code>variant</code> objects, as illustrated in the <a href="sample.html#poly">
Polymorphism: Inheritance Vs. Variants</a> sample.<br>
</p>
<hr>
<h2><a name="StaticVisitor">Visitation: <code>static_visitor</code></a></h2>
<pre>template&lt;typename R = void&gt;
struct static_visitor
{
typedef R result_type;
};
</pre>
<p><code>static_visitor</code> defines the nested type <code>result_type</code>,
which is required from each <a href="#Visitor">visitor</a> class.
<br>
</p>
<hr>
<h2><a name="ValueExtraction">Value Extraction: <code>get</code></a></h2>
<pre> class bad_get : public std::exception
{
public:
virtual const char* what() const throw();
};
template&lt;typename ToType,typename T1, typename T2, ...&gt;
ToType& get(boost::variant&lt;T1,T2,...&gt;&amp; v);
template&lt;typename ToType,typename T1, typename T2, ...&gt;
const ToType& get(const boost::variant&lt;T1,T2,...&gt;&amp; v);
template&lt;typename ToType,typename T1, typename T2, ...&gt;
ToType* get(boost::variant&lt;T1,T2,...&gt;* v);
template&lt;typename ToType,typename T1, typename T2, ...&gt;
const ToType* get(const boost::variant&lt;T1,T2,...&gt;* v);
</pre>
Returns a reference/pointer to a held value:<ul>
<li>If a pointer is passed: Returns a pointer to the held value if its type is
<code>ToType</code>. Otherwise, returns <code>NULL</code>.</li>
<li>If a value/reference is passed: Returns a reference to the held value if its type
is <code>ToType</code>. Otherwise, throws a <code>bad_get</code> exception.<br>
</li>
</ul>
<br><hr>
<h2><a name="incomplete"><code>incomplete</code></a></h2>
<p><code>incomplete&lt;T&gt;</code> is a class template, which allows a <code>variant</code>
type to be instantiated with incomplete types.<br>
By specifying <code>incomplete&lt;T&gt;</code> as one of the actual template
parameters, the instantiated variant will be able to handle values of type <code>T</code>,
although <code>T</code> is incomplete at the instantiation point.<br>
<code>incomplete&lt;&gt;</code> is typically used for solving circular
dependencies, but, more importantly, it also enables the creation of <b>recursive</b>,
variant-based, constructs.<br>
<br>
Note that using <code>incomplete&lt;T&gt;</code> instructs the concrete
<code>variant</code> type to employ heap allocation scheme
for storing values of type <code>T</code> ("Reference Semantics"). This
is opposite to the to the standard case, where values of complete types
are stored within the <code>variant</code> object itself ("Value
Semantics").<br>
<br>
The snip below demonstrates the usage of <code>incomplete&lt;&gt;</code>. A
complete sample program is available <a HREF="sample.html#tree">here</a>.
</p>
<pre> using boost::variant;
using boost::incomplete;
struct non_leaf_node; // Forward declaration
// Define a tree_node variant with these two types:
// (1) int, (2) non_leaf node
typedef variant
&lt;
int,
incomplete&lt;non_leaf_node&gt; // non_leaf_node is incomplete at
// this point so it must be wrapperd
// by incomplete&lt;&gt;
&gt; tree_node;
struct non_leaf_node
{
non_leaf_node(const non_leaf_node&amp; other)
: left_(other.left_), right_(other.right_), num_(other.num_)
{ }
int num_;
tree_node left_;
tree_node right_;
};
</pre>
<br><hr>
<h2><a name="empty"><code>empty</code></a></h2>
<pre>
struct empty { };
bool operator==(const empty&, const empty&); // Always true
bool operator&lt;(const empty&, const empty&); // Always false
BOOST_TEMPLATED_STREAM_TEMPLATE(E,T)
BOOST_TEMPLATED_STREAM(ostream, E,T)&
operator&lt;&lt;(BOOST_TEMPLATED_STREAM(ostream, E,T)&, const empty& ); // NOP
</pre>
<p>
A <code>variant</code> object holding a value of
type <code>boost::empty</code> is considered to be empty.<br>
This convention is acknowledged by <code>varinat::empty()</code>: Its
return value is <code>true</code>, if and only if the held value is of type
<code>boost::empty</code>.<br>
<br>
Public interface
<ul>
<li>Comparisons:<code>operator==(const empty&, const empty&)</code>
always returns <code>true</code>, while
<code>operator&lt;(const empty&, const empty&)</code> always returns
<code>false</code>.</li>
<li>Output: <code>operator&lt;&lt;</code> has a "Do-nothing" behavior when
invoked with a <code>boost::empty</code> value.
</li>
</ul>
<br>
Comments
<ul>
<li>A <code>variant</code> object that does not have <code>boost::empty</code>
as one of its <a href="#BoundedType">BoundedTypes</a>, can never be in an empty
state. At any given point it holds a valid value.
</li>
<li>Empty variants are visitable. Consequently, every visitor of a possibly
empty variant, must accept a <code>boost::empty</code> value.
</li>
<li><code>boost::empty</code> has no state. Thus, when two instances of
<code>boost::empty</code> are tested for equality, the result is always
<code>true</code>.</li>
</ul>
<h3><b>Example:</b></h3>
<p>The following snip demonstrates an optional string value, using a variant
whose bounded types are <code>boost::empty</code> and
<code>std::string</code>:
<pre>typedef boost::variant&lt;boost::empty,std::string&gt; string_or_nothing;
void print(const string_or_nothing& a)
{
if(a.empty())
cout << "No string is specified" << endl;
else
cout << boost::get&lt;const std::string&gt;(a) << endl;
}
int main()
{
string_or_nothing s;
print(s); // Output: "No string is specified"
s = "Ford Prefect";
print(s); // Output: "Ford Prefect"
return 0;
}
</pre>
<hr>
<p>Revised 28 July 2003</p>
<p><i><EFBFBD> Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied
warranty.</p>
</body>
</html>