early-access version 3088

This commit is contained in:
pineappleEA
2022-11-05 15:35:56 +01:00
parent 4e4fc25ce3
commit b601909c6d
35519 changed files with 5996896 additions and 860 deletions

View File

@@ -0,0 +1,29 @@
# Boost.Variant Library doc Jamfile
#
# Copyright (C) 2003, Eric Friedman, Itay Maman.
#
# Use, modification and distribution is subject to 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)
#
project variant/doc ;
import boostbook : boostbook ;
boostbook variant-doc
:
variant.xml
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
###############################################################################
alias boostdoc
: variant.xml
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.refs">
<title>References</title>
<para id="variant.refs.abr00">
<ulink url="http://boost.org/more/generic_exception_safety.html">[Abr00]</ulink>
David Abrahams.
&quot;Exception-Safety in Generic Components.&quot;
M. Jazayeri, R. Loos, D. Musser (eds.):
Generic Programming '98, Proc. of a Dagstuhl Seminar, Lecture Notes on Computer Science, Vol. 1766, pp. 69-79.
Springer-Verlag Berlin Heidelberg.
2000.
</para>
<para id="variant.refs.abr01">
<ulink url="http://boost.org/more/error_handling.html">[Abr01]</ulink>
David Abrahams.
&quot;Error and Exception Handling.&quot;
Boost technical article.
2001-2003.
</para>
<para id="variant.refs.ale01a">
<ulink url="http://www.oonumerics.org/tmpw01/alexandrescu.pdf">[Ale01a]</ulink>
Andrei Alexandrescu.
&quot;An Implementation of Discriminated Unions in C++.&quot;
<emphasis>OOPSLA 2001</emphasis>, Second Workshop on C++ Template Programming.
Tampa Bay, 14 October 2001.
</para>
<para id="variant.refs.ale01b">
<ulink url="http://www.moderncppdesign.com/book/main.html">[Ale01b]</ulink>
Andrei Alexandrescu.
<emphasis>Modern C++ Design</emphasis>.
Addison-Wesley, C++ In-Depth series.
2001.
</para>
<para id="variant.refs.ale02">
<ulink url="http://cuj.com/experts/2008/alexandr.htm">[Ale02]</ulink>
Andrei Alexandrescu.
&quot;Generic&lt;Programming&gt;: Discriminated Unions&quot; series:
<ulink url="http://cuj.com/experts/2004/alexandr.htm">Part 1</ulink>,
<ulink url="http://cuj.com/experts/2006/alexandr.htm">Part 2</ulink>,
<ulink url="http://cuj.com/experts/2008/alexandr.htm">Part 3</ulink>.
<emphasis>C/C++ Users Journal</emphasis>.
2002.
</para>
<para id="variant.refs.boo02">
<ulink url="http://lists.boost.org/MailArchives/boost/msg30415.php">[Boo02]</ulink>
Various Boost members.
&quot;Proposal --- A type-safe union.&quot;
Boost public discussion.
2002.
</para>
<para id="variant.refs.c++98">
[C++98]
<emphasis>International Standard, Programming Languages C++</emphasis>.
ISO/IEC:14882.
1998.
</para>
<para id="variant.refs.gof95">
[GoF95]
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.
<emphasis>Design Patterns: Elements of Reusable Object-Oriented Software</emphasis>.
Addison-Wesley.
1995.
</para>
<para id="variant.refs.gre02">
<ulink url="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?variant">[Gre02]</ulink>
Douglas Gregor.
&quot;BOOST_USER: variant.&quot;
Boost Wiki paper.
2002.
</para>
<para id="variant.refs.gur02">
<libraryname alt="MPL">[Gur02]</libraryname>
Aleksey Gurtovoy.
<emphasis>Boost Metaprogramming Library.</emphasis>
2002.
</para>
<para id="variant.refs.hen01">
<libraryname alt="Any">[Hen01]</libraryname>
Kevlin Henney.
<emphasis>Boost Any Library.</emphasis>
2001.
</para>
<para id="variant.refs.mk02">
<libraryname alt="Preprocessor">[MK02]</libraryname>
Paul Mensonides and Vesa Karvonen.
<emphasis>Boost Preprocessor Library.</emphasis>
2002.
</para>
<para id="variant.refs.mcd+01">
<libraryname alt="Type Traits">[MCD+01]</libraryname>
Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat Marcus, John Maddock, Jeremy Siek.
<emphasis>Boost Type Traits Library</emphasis>.
2001.
</para>
<para id="variant.refs.sut00">
<ulink url="http://www.gotw.ca/publications/xc++.htm">[Sut00]</ulink>
Herb Sutter.
<emphasis>Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions</emphasis>.
Addison-Wesley, C++ In-Depth series.
2000.
</para>
<para id="variant.refs.wil02">
<ulink url="http://aspn.activestate.com/ASPN/Mail/Message/boost/1314807">[Wil02]</ulink>
Anthony Williams.
Double-Storage Proposal.
2002.
</para>
</section>

View File

@@ -0,0 +1,310 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.design">
<title>Design Overview</title>
<using-namespace name="boost"/>
<section id="variant.design.never-empty">
<title>&quot;Never-Empty&quot; Guarantee</title>
<section id="variant.design.never-empty.guarantee">
<title>The Guarantee</title>
<para>All instances <code>v</code> of type
<code><classname>variant</classname>&lt;T1,T2,...,TN&gt;</code>
guarantee that <code>v</code> has constructed content of one of the
types <code>T<emphasis>i</emphasis></code>, even if an operation on
<code>v</code> has previously failed.</para>
<para>This implies that <code>variant</code> may be viewed precisely as
a union of <emphasis>exactly</emphasis> its bounded types. This
&quot;never-empty&quot; property insulates the user from the
possibility of undefined <code>variant</code> content and the
significant additional complexity-of-use attendant with such a
possibility.</para>
</section>
<section id="variant.design.never-empty.problem">
<title>The Implementation Problem</title>
<para>While the
<link linkend="variant.design.never-empty.guarantee">never-empty guarantee</link>
might at first seem &quot;obvious,&quot; it is in fact not even
straightforward how to implement it in general (i.e., without
unreasonably restrictive additional requirements on
<link linkend="variant.concepts.bounded-type">bounded types</link>).</para>
<para>The central difficulty emerges in the details of
<code>variant</code> assignment. Given two instances <code>v1</code>
and <code>v2</code> of some concrete <code>variant</code> type, there
are two distinct, fundamental cases we must consider for the assignment
<code>v1 = v2</code>.</para>
<para>First consider the case that <code>v1</code> and <code>v2</code>
each contains a value of the same type. Call this type <code>T</code>.
In this situation, assignment is perfectly straightforward: use
<code>T::operator=</code>.</para>
<para>However, we must also consider the case that <code>v1</code> and
<code>v2</code> contain values <emphasis>of distinct types</emphasis>.
Call these types <code>T</code> and <code>U</code>. At this point,
since <code>variant</code> manages its content on the stack, the
left-hand side of the assignment (i.e., <code>v1</code>) must destroy
its content so as to permit in-place copy-construction of the content
of the right-hand side (i.e., <code>v2</code>). In the end, whereas
<code>v1</code> began with content of type <code>T</code>, it ends
with content of type <code>U</code>, namely a copy of the content of
<code>v2</code>.</para>
<para>The crux of the problem, then, is this: in the event that
copy-construction of the content of <code>v2</code> fails, how can
<code>v1</code> maintain its &quot;never-empty&quot; guarantee?
By the time copy-construction from <code>v2</code> is attempted,
<code>v1</code> has already destroyed its content!</para>
</section>
<section id="variant.design.never-empty.memcpy-solution">
<title>The &quot;Ideal&quot; Solution: False Hopes</title>
<para>Upon learning of this dilemma, clever individuals may propose the
following scheme hoping to solve the problem:
<orderedlist>
<listitem>Provide some &quot;backup&quot; storage, appropriately
aligned, capable of holding values of the contained type of the
left-hand side.</listitem>
<listitem>Copy the memory (e.g., using <code>memcpy</code>) of the
storage of the left-hand side to the backup storage.</listitem>
<listitem>Attempt a copy of the right-hand side content to the
(now-replicated) left-hand side storage.</listitem>
<listitem>In the event of an exception from the copy, restore the
backup (i.e., copy the memory from the backup storage back into
the left-hand side storage).</listitem>
<listitem>Otherwise, in the event of success, now copy the memory
of the left-hand side storage to another &quot;temporary&quot;
aligned storage.</listitem>
<listitem>Now restore the backup (i.e., again copying the memory)
to the left-hand side storage; with the &quot;old&quot; content
now restored, invoke the destructor of the contained type on the
storage of the left-hand side.</listitem>
<listitem>Finally, copy the memory of the temporary storage to the
(now-empty) storage of the left-hand side.</listitem>
</orderedlist>
</para>
<para>While complicated, it appears such a scheme could provide the
desired safety in a relatively efficient manner. In fact, several
early iterations of the library implemented this very approach.</para>
<para>Unfortunately, as Dave Abraham's first noted, the scheme results
in undefined behavior:
<blockquote>
<para>&quot;That's a lot of code to read through, but if it's
doing what I think it's doing, it's undefined behavior.</para>
<para>&quot;Is the trick to move the bits for an existing object
into a buffer so we can tentatively construct a new object in
that memory, and later move the old bits back temporarily to
destroy the old object?</para>
<para>&quot;The standard does not give license to do that: only one
object may have a given address at a time. See 3.8, and
particularly paragraph 4.&quot;</para>
</blockquote>
</para>
<para>Additionally, as close examination quickly reveals, the scheme has
the potential to create irreconcilable race-conditions in concurrent
environments.</para>
<para>Ultimately, even if the above scheme could be made to work on
certain platforms with particular compilers, it is still necessary to
find a portable solution.</para>
</section>
<section id="variant.design.never-empty.double-storage-solution">
<title>An Initial Solution: Double Storage</title>
<para>Upon learning of the infeasibility of the above scheme, Anthony
Williams proposed in
<link linkend="variant.refs.wil02">[Wil02]</link> a scheme that served
as the basis for a portable solution in some pre-release
implementations of <code>variant</code>.</para>
<para>The essential idea to this scheme, which shall be referred to as
the &quot;double storage&quot; scheme, is to provide enough space
within a <code>variant</code> to hold two separate values of any of
the bounded types.</para>
<para>With the secondary storage, a copy the right-hand side can be
attempted without first destroying the content of the left-hand side;
accordingly, the content of the left-hand side remains available in
the event of an exception.</para>
<para>Thus, with this scheme, the <code>variant</code> implementation
needs only to keep track of which storage contains the content -- and
dispatch any visitation requests, queries, etc. accordingly.</para>
<para>The most obvious flaw to this approach is the space overhead
incurred. Though some optimizations could be applied in special cases
to eliminate the need for double storage -- for certain bounded types
or in some cases entirely (see
<xref linkend="variant.design.never-empty.optimizations"/> for more
details) -- many users on the Boost mailing list strongly objected to
the use of double storage. In particular, it was noted that the
overhead of double storage would be at play at all times -- even if
assignment to <code>variant</code> never occurred. For this reason
and others, a new approach was developed.</para>
</section>
<section id="variant.design.never-empty.heap-backup-solution">
<title>Current Approach: Temporary Heap Backup</title>
<para>Despite the many objections to the double storage solution, it was
realized that no replacement would be without drawbacks. Thus, a
compromise was desired.</para>
<para>To this end, Dave Abrahams suggested to include the following in
the behavior specification for <code>variant</code> assignment:
&quot;<code>variant</code> assignment from one type to another may
incur dynamic allocation." That is, while <code>variant</code> would
continue to store its content <emphasis>in situ</emphasis> after
construction and after assignment involving identical contained types,
<code>variant</code> would store its content on the heap after
assignment involving distinct contained types.</para>
<para>The algorithm for assignment would proceed as follows:
<orderedlist>
<listitem>Copy-construct the content of the right-hand side to the
heap; call the pointer to this data <code>p</code>.</listitem>
<listitem>Destroy the content of the left-hand side.</listitem>
<listitem>Copy <code>p</code> to the left-hand side
storage.</listitem>
</orderedlist>
Since all operations on pointers are nothrow, this scheme would allow
<code>variant</code> to meet its never-empty guarantee.
</para>
<para>The most obvious concern with this approach is that while it
certainly eliminates the space overhead of double storage, it
introduces the overhead of dynamic-allocation to <code>variant</code>
assignment -- not just in terms of the initial allocation but also
as a result of the continued storage of the content on the heap. While
the former problem is unavoidable, the latter problem may be avoided
with the following &quot;temporary heap backup&quot; technique:
<orderedlist>
<listitem>Copy-construct the content of the
<emphasis>left</emphasis>-hand side to the heap; call the pointer to
this data <code>backup</code>.</listitem>
<listitem>Destroy the content of the left-hand side.</listitem>
<listitem>Copy-construct the content of the right-hand side in the
(now-empty) storage of the left-hand side.</listitem>
<listitem>In the event of failure, copy <code>backup</code> to the
left-hand side storage.</listitem>
<listitem>In the event of success, deallocate the data pointed to
by <code>backup</code>.</listitem>
</orderedlist>
</para>
<para>With this technique: 1) only a single storage is used;
2) allocation is on the heap in the long-term only if the assignment
fails; and 3) after any <emphasis>successful</emphasis> assignment,
storage within the <code>variant</code> is guaranteed. For the
purposes of the initial release of the library, these characteristics
were deemed a satisfactory compromise solution.</para>
<para>There remain notable shortcomings, however. In particular, there
may be some users for which heap allocation must be avoided at all
costs; for other users, any allocation may need to occur via a
user-supplied allocator. These issues will be addressed in the future
(see <xref linkend="variant.design.never-empty.roadmap"/>). For now,
though, the library treats storage of its content as an implementation
detail. Nonetheless, as described in the next section, there
<emphasis>are</emphasis> certain things the user can do to ensure the
greatest efficiency for <code>variant</code> instances (see
<xref linkend="variant.design.never-empty.optimizations"/> for
details).</para>
</section>
<section id="variant.design.never-empty.optimizations">
<title>Enabling Optimizations</title>
<para>As described in
<xref linkend="variant.design.never-empty.problem"/>, the central
difficulty in implementing the never-empty guarantee is the
possibility of failed copy-construction during <code>variant</code>
assignment. Yet types with nothrow copy constructors clearly never
face this possibility. Similarly, if one of the bounded types of the
<code>variant</code> is nothrow default-constructible, then such a
type could be used as a safe &quot;fallback&quot; type in the event of
failed copy construction.</para>
<para>Accordingly, <code>variant</code> is designed to enable the
following optimizations once the following criteria on its bounded
types are met:
<itemizedlist>
<listitem>For each bounded type <code>T</code> that is nothrow
copy-constructible (as indicated by
<code><classname>boost::has_nothrow_copy</classname></code>), the
library guarantees <code>variant</code> will use only single
storage and in-place construction for <code>T</code>.</listitem>
<listitem>If <emphasis>any</emphasis> bounded type is nothrow
default-constructible (as indicated by
<code><classname>boost::has_nothrow_constructor</classname></code>),
the library guarantees <code>variant</code> will use only single
storage and in-place construction for <emphasis>every</emphasis>
bounded type in the <code>variant</code>. Note, however, that in
the event of assignment failure, an unspecified nothrow
default-constructible bounded type will be default-constructed in
the left-hand side operand so as to preserve the never-empty
guarantee.</listitem>
</itemizedlist>
</para>
<para><emphasis role="bold">Implementation Note</emphasis>: So as to make
the behavior of <code>variant</code> more predictable in the aftermath
of an exception, the current implementation prefers to default-construct
<code><classname>boost::blank</classname></code> if specified as a
bounded type instead of other nothrow default-constructible bounded
types. (If this is deemed to be a useful feature, it will become part
of the specification for <code>variant</code>; otherwise, it may be
obsoleted. Please provide feedback to the Boost mailing list.)</para>
</section>
<section id="variant.design.never-empty.roadmap">
<title>Future Direction: Policy-based Implementation</title>
<para>As the previous sections have demonstrated, much effort has been
expended in an attempt to provide a balance between performance, data
size, and heap usage. Further, significant optimizations may be
enabled in <code>variant</code> on the basis of certain traits of its
bounded types.</para>
<para>However, there will be some users for whom the chosen compromise
is unsatisfactory (e.g.: heap allocation must be avoided at all costs;
if heap allocation is used, custom allocators must be used; etc.). For
this reason, a future version of the library will support a
policy-based implementation of <code>variant</code>. While this will
not eliminate the problems described in the previous sections, it will
allow the decisions regarding tradeoffs to be decided by the user
rather than the library designers.</para>
</section>
</section>
</section>

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.intro">
<title>Introduction</title>
<using-namespace name="boost"/>
<section id="variant.abstract">
<title>Abstract</title>
<para>The <code>variant</code> 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 <code>std::vector</code> may be thought of as
"<emphasis role="bold">multi-value, single type</emphasis>,"
<code>variant</code> is "<emphasis role="bold">multi-type,
single value</emphasis>."</para>
<para>Notable features of <code><classname>boost::variant</classname></code>
include:</para>
<itemizedlist>
<listitem>Full value semantics, including adherence to standard
overload resolution rules for conversion operations.</listitem>
<listitem>Compile-time type-safe value visitation via
<code><functionname>boost::apply_visitor</functionname></code>.</listitem>
<listitem>Run-time checked explicit value retrieval via
<code><functionname>boost::get</functionname></code>.</listitem>
<listitem>Support for recursive variant types via both
<code><classname>boost::make_recursive_variant</classname></code> and
<code><classname>boost::recursive_wrapper</classname></code>.</listitem>
<listitem>Efficient implementation -- stack-based when possible (see
<xref linkend="variant.design.never-empty"/> for more details).</listitem>
</itemizedlist>
</section>
<section id="variant.motivation">
<title>Motivation</title>
<section id="variant.motivation.problem">
<title>Problem</title>
<para>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 <code>union</code>
keyword:</para>
<programlisting>union { int i; double d; } u;
u.d = 3.14;
u.i = 3; // overwrites u.d (OK: u.d is a POD type)</programlisting>
<para>C++'s <code>union</code> 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:</para>
<programlisting>union {
int i;
std::string s; // illegal: std::string is not a POD type!
} u;</programlisting>
<para>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
[<link linkend="variant.refs.hen01">Hen01</link>]
or, more dangerously, a <code>void*</code>). Objects of
concrete type may be then retrieved by way of a polymorphic downcast
construct (e.g., <code>dynamic_cast</code>,
<code><functionname>boost::any_cast</functionname></code>, etc.).</para>
<para>However, solutions of this sort are highly error-prone, due
to the following:</para>
<itemizedlist>
<listitem><emphasis>Downcast errors cannot be detected at
compile-time.</emphasis> Thus, incorrect usage of downcast
constructs will lead to bugs detectable only at run-time.</listitem>
<listitem><emphasis>Addition of new concrete types may be
ignored.</emphasis> 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.</listitem>
</itemizedlist>
<para>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.</para>
</section>
<section id="variant.motivation.solution">
<title>Solution: A Motivating Example</title>
<para>The <code><classname>boost::variant</classname></code> class template
addresses these issues in a safe, straightforward, and efficient manner. The
following example demonstrates how the class can be used:</para>
<programlisting>#include "boost/variant.hpp"
#include &lt;iostream&gt;
class my_visitor : public <classname>boost::static_visitor</classname>&lt;int&gt;
{
public:
int operator()(int i) const
{
return i;
}
int operator()(const <classname>std::string</classname> &amp; str) const
{
return str.length();
}
};
int main()
{
<classname>boost::variant</classname>&lt; int, std::string &gt; u("hello world");
std::cout &lt;&lt; u; // output: hello world
int result = <functionname>boost::apply_visitor</functionname>( my_visitor(), u );
std::cout &lt;&lt; result; // output: 11 (i.e., length of "hello world")
}
</programlisting>
</section>
</section>
</section>

View File

@@ -0,0 +1,241 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.misc">
<title>Miscellaneous Notes</title>
<using-namespace name="boost"/>
<section id="variant.versus-any">
<title>Boost.Variant vs. Boost.Any</title>
<para>As a discriminated union container, the Variant library shares many
of the same features of the <libraryname>Any</libraryname> library.
However, since neither library wholly encapsulates the features of the
other, one library cannot be generally recommended for use over the
other.</para>
<para>That said, Boost.Variant has several advantages over Boost.Any,
such as:
<itemizedlist>
<listitem>Boost.Variant guarantees the type of its content is one of a
finite, user-specified set of types.</listitem>
<listitem>Boost.Variant provides <emphasis>compile-time</emphasis>
checked visitation of its content. (By contrast, the current version
of Boost.Any provides no visitation mechanism at all; but even if it
did, it would need to be checked at run-time.)</listitem>
<listitem>Boost.Variant enables generic visitation of its content.
(Even if Boost.Any did provide a visitation mechanism, it would enable
visitation only of explicitly-specified types.)</listitem>
<listitem>Boost.Variant offers an efficient, stack-based storage scheme
(avoiding the overhead of dynamic allocation).</listitem>
</itemizedlist>
</para>
<para>Of course, Boost.Any has several advantages over Boost.Variant,
such as:
<itemizedlist>
<listitem>Boost.Any, as its name implies, allows virtually any type for
its content, providing great flexibility.</listitem>
<listitem>Boost.Any provides the no-throw guarantee of exception safety
for its swap operation.</listitem>
<listitem>Boost.Any makes little use of template metaprogramming
techniques (avoiding potentially hard-to-read error messages and
significant compile-time processor and memory demands).</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Portability</title>
<para>The library aims for 100% ANSI/ISO C++ conformance. However, this is
strictly impossible due to the inherently non-portable nature of the
<libraryname>Type Traits</libraryname> library's
<code><classname>type_with_alignment</classname></code> facility. In
practice though, no compilers or platforms have been discovered where this
reliance on undefined behavior has been an issue.</para>
<para>Additionally, significant effort has been expended to ensure proper
functioning despite various compiler bugs and other conformance problems.
To date the library testsuite has
been compiled and tested successfully on at least the following compilers
for basic and advanced functionality:
<informaltable>
<tgroup cols="5">
<thead>
<row>
<entry></entry>
<entry>Basic</entry>
<entry>
<code>variant&lt;T&amp;&gt;</code>
</entry>
<entry>
<link linkend="variant.tutorial.over-sequence">
<code>make_variant_over</code>
</link>
</entry>
<entry>
<link linkend="variant.tutorial.recursive.recursive-variant">
<code>make_recursive_variant</code>
</link>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>Borland C++ 5.5.1 and 5.6.4</entry>
<entry>X</entry>
<entry>X</entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry>Comeau C++ 4.3.0</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
</row>
<row>
<entry>GNU GCC 3.3.1</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
</row>
<row>
<entry>GNU GCC 2.95.3</entry>
<entry>X</entry>
<entry>X</entry>
<entry></entry>
<entry>X</entry>
</row>
<row>
<entry>Intel C++ 7.0</entry>
<entry>X</entry>
<entry></entry>
<entry>X</entry>
<entry>X</entry>
</row>
<row>
<entry>Metrowerks CodeWarrior 8.3</entry>
<entry>X</entry>
<entry></entry>
<entry>X</entry>
<entry>X</entry>
</row>
<row>
<entry>Microsoft Visual C++ 7.1</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
</row>
<row>
<entry>Microsoft Visual C++ 6 SP5 and 7</entry>
<entry>X</entry>
<entry></entry>
<entry></entry>
<entry></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>Finally, the current state of the testsuite in CVS may be found on the
<ulink url="http://boost.sourceforge.net/regression-logs">Test Summary</ulink>
page. Please note, however, that this page reports on day-to-day changes
to inter-release code found in the Boost CVS and thus likely does not
match the state of code found in Boost releases.</para>
</section>
<section id="variant.troubleshooting">
<title>Troubleshooting</title>
<para>Due to the heavy use of templates in the implementation of
<code>variant</code>, it is not uncommon when compiling to encounter
problems related to template instantiaton depth, compiler memory, etc. This
section attempts to provide advice to common problems experienced on several
popular compilers.</para>
<para>(This section is still in progress, with additional advice/feedback
welcome. Please post to the Boost-Users list with any useful experiences you
may have.)</para>
<section id="variant.troubleshooting.template-depth">
<title>&quot;Template instantiation depth exceeds maximum&quot;</title>
<section id="variant.troubleshooting.template-depth.gcc">
<title>GNU GCC</title>
<para>The compiler option
<code>-ftemplate-depth-<emphasis>NN</emphasis></code> can increase the
maximum allowed instantiation depth. (Try
<code>-ftemplate-depth-50</code>.)</para>
</section>
</section>
<section id="variant.troubleshooting.compiler-memory">
<title>&quot;Internal heap limit reached&quot;</title>
<section id="variant.troubleshooting.compiler-memory.msvc">
<title>Microsoft Visual C++</title>
<para>The compiler option <code>/Zm<emphasis>NNN</emphasis></code> can
increase the memory allocation limit. The <code>NNN</code> is a
scaling percentage (i.e., <code>100</code> denotes the default limit).
(Try <code>/Zm200</code>.)</para>
</section>
</section>
</section>
<section id="variant.ack">
<title>Acknowledgments</title>
<para>Eric Friedman and Itay Maman designed the initial submission; Eric was
the primary implementer.</para>
<para>Eric is also the library maintainer and has expanded upon the initial
submission -- adding
<code><classname>make_recursive_variant</classname></code>,
<code><classname>make_variant_over</classname></code>, support for
reference content, etc.</para>
<para>Andrei Alexandrescu's work in
[<link linkend="variant.refs.ale01a">Ale01a</link>]
and
[<link linkend="variant.refs.ale02">Ale02</link>]
inspired the library's design.</para>
<para>Jeff Garland was the formal review manager.</para>
<para>Douglas Gregor,
Dave Abrahams,
Anthony Williams,
Fernando Cacciola,
Joel de Guzman,
Dirk Schreib,
Brad King,
Giovanni Bajo,
Eugene Gladyshev,
and others provided helpful feedback and suggestions to refine the semantics,
interface, and implementation of the library.</para>
</section>
</section>

View File

@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Copyright 2013-2022 Antony Polukhin.
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)
-->
<header name="boost/variant/apply_visitor.hpp">
<namespace name="boost">
<class name="apply_visitor_delayed_t">
<purpose>Adapts a visitor for use as a function object.</purpose>
<description>
<simpara>Adapts the function given at construction for use as a
function object. This is useful, for example, when one needs to
operate on each element of a sequence of variant objects using a
standard library algorithm such as
<code>std::for_each</code>.</simpara>
<simpara>See the &quot;visitor-only&quot; form of
<code><functionname>apply_visitor</functionname></code> for a simple
way to create <code>apply_visitor_delayed_t</code> objects.</simpara>
<simpara>See <code><classname>apply_visitor_delayed_cpp14_t</classname></code>
which is used on C++14 compatible compilers when <code>Visitor</code> has no
<code>result_type</code> typedef.</simpara>
</description>
<template>
<template-type-parameter name="Visitor"/>
</template>
<typedef name="result_type">
<type>typename Visitor::result_type</type>
</typedef>
<constructor specifiers="explicit">
<parameter name="visitor">
<paramtype>Visitor &amp;</paramtype>
</parameter>
<effects>
<simpara>Constructs the function object with the given
visitor.</simpara>
</effects>
</constructor>
<method-group name="function object interface">
<overloaded-method name="operator()">
<signature>
<template>
<template-type-parameter name="... Variant"/>
</template>
<type>result_type</type>
<parameter name="operand">
<paramtype>Variant&amp;...</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Variant"/>
</template>
<type>result_type</type>
<parameter name="operand">
<paramtype>Variant &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
</template>
<type>result_type</type>
<parameter name="operand1">
<paramtype>Variant1 &amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2 &amp;</paramtype>
</parameter>
</signature>
<purpose>Function call operator.</purpose>
<description>
<simpara>Invokes
<code><functionname>apply_visitor</functionname></code> on the
stored visitor using the given operands.</simpara>
</description>
<notes>Version with variadic templates is used by default if
<macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname> is not defined.</notes>
</overloaded-method>
</method-group>
</class>
<class name="apply_visitor_delayed_cpp14_t">
<purpose>Adapts a visitor for use as a function object.</purpose>
<description>
<simpara>Adapts the function given at construction for use as a
function object. This is useful, for example, when one needs to
operate on each element of a sequence of variant objects using a
standard library algorithm such as
<code>std::for_each</code>.</simpara>
<simpara>See the &quot;visitor-only&quot; form of
<code><functionname>apply_visitor</functionname></code> for a simple
way to create <code>apply_visitor_delayed_t</code> objects.</simpara>
<simpara>See <code><classname>apply_visitor_delayed_t</classname></code>
which is used when <code>Visitor</code> has <code>result_type</code>
typedef.</simpara>
<simpara>Available only if macro
<macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname> is not defined and
compiler supports <code>decltype(auto)</code> and <code>decltype(some-expression)</code>.</simpara>
</description>
<template>
<template-type-parameter name="Visitor"/>
</template>
<constructor specifiers="explicit">
<parameter name="visitor">
<paramtype>Visitor &amp;</paramtype>
</parameter>
<effects>
<simpara>Constructs the function object with the given
visitor.</simpara>
</effects>
</constructor>
<method-group name="function object interface">
<overloaded-method name="operator()">
<signature>
<template>
<template-type-parameter name="... Variant"/>
</template>
<type>decltype(auto)</type>
<parameter name="operand">
<paramtype>Variant&amp;...</paramtype>
</parameter>
</signature>
<purpose>Function call operator.</purpose>
<description>
<simpara>Invokes
<code><functionname>apply_visitor</functionname></code> on the
stored visitor using the given operands.</simpara>
</description>
</overloaded-method>
</method-group>
</class>
<overloaded-function name="apply_visitor">
<signature>
<template>
<template-type-parameter name="Visitor"/>
<template-type-parameter name="Variant"/>
</template>
<type>typename Visitor::result_type</type>
<parameter name="visitor">
<paramtype>Visitor &amp;</paramtype>
</parameter>
<parameter name="operand">
<paramtype>Variant&amp;&amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Visitor"/>
<template-type-parameter name="Variant"/>
</template>
<type>typename Visitor::result_type</type>
<parameter name="visitor">
<paramtype>const Visitor &amp;</paramtype>
</parameter>
<parameter name="operand">
<paramtype>Variant&amp;&amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="BinaryVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
</template>
<type>typename BinaryVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>BinaryVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="BinaryVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
</template>
<type>typename BinaryVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>const BinaryVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="MultiVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
<template-type-parameter name="Variant3"/>
</template>
<type>typename MultiVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>MultiVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
<parameter name="operand3">
<paramtype>Variant3&amp;&amp;</paramtype>
</parameter>
<parameter name="other_operands">
<paramtype>...</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="MultiVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
<template-type-parameter name="Variant3"/>
</template>
<type>typename MultiVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>const MultiVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
<parameter name="operand3">
<paramtype>Variant3&amp;&amp;</paramtype>
</parameter>
<parameter name="other_operands">
<paramtype>...</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Visitor"/>
</template>
<type><classname>apply_visitor_delayed_t</classname>&lt;Visitor&gt;</type>
<parameter name="visitor">
<paramtype>Visitor &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="Visitor"/>
</template>
<type><classname>apply_visitor_delayed_cpp14_t</classname>&lt;Visitor&gt;</type>
<parameter name="visitor">
<paramtype>Visitor &amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Allows compile-time checked type-safe application of the
given visitor to the content of the given variant, ensuring that all
types are handled by the visitor.</simpara>
</purpose>
<description>
<simpara>The behavior of <code>apply_visitor</code> is dependent on
the number of arguments on which it operates (i.e., other than the
visitor). If your compiler does not support the rvalue references or reference qualifiers then all the
forwarding references from above degrade to non const lvalue reference. The function behaves as follows:
<itemizedlist>
<listitem>Overloads accepting one operand invoke the unary function
call operator of the given visitor on the content of the given
<code><classname>variant</classname></code> operand.</listitem>
<listitem>Overloads accepting two operands invoke the binary
function call operator of the given visitor on the content of
the given <code><classname>variant</classname></code>
operands.</listitem>
<listitem>Overloads accepting three or more operands invoke the
function call operator of the given visitor on the content of
the given <code><classname>variant</classname></code>
operands. Maximum amount of parameters controlled by
<code><emphasis role="bold"><macroname>BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS</macroname></emphasis></code>
macro. Those functions are actually defined in a header <code>boost/variant/multivisitors.hpp</code>
(See <xref linkend="header.boost.variant.multivisitors_hpp"/>). That header must be manually included
if multi visitors are meant for use.</listitem>
<listitem>The overloads accepting only a visitor return a
<classname alt="boost::apply_visitor_delayed_t">C++03 compatible generic function object</classname>
or
<classname alt="boost::apply_visitor_delayed_cpp14_t">C++14 compatible generic function object</classname>
that accepts either one, two or arbitrary count of arguments and invoke
<code><functionname>apply_visitor</functionname></code> using
these arguments and <code>visitor</code>, thus behaving as
specified above. (This behavior is particularly useful, for
example, when one needs to operate on each element of a sequence
of variant objects using a standard library
algorithm.)</listitem>
</itemizedlist>
</simpara>
</description>
<returns>
<simpara>The overloads acccepting operands return the result of
applying the given visitor to the content of the given operands.
The overload accepting only a visitor return a function object, thus
delaying application of the visitor to any operands.</simpara>
</returns>
<requires>
<simpara>The given visitor must fulfill the
<link linkend="variant.concepts.static-visitor"><emphasis>StaticVisitor</emphasis></link>
concept requirements with respect to each of the bounded types of the
given <code>variant</code>.</simpara>
</requires>
<throws>
<simpara>The overloads accepting operands throw only if the given
visitor throws when applied. The overload accepting only a visitor
will not throw. (Note, however, that the returned
<classname alt="boost::apply_visitor_delayed_t">function object</classname>
may throw when invoked.)</simpara>
</throws>
</overloaded-function>
</namespace>
</header>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/bad_visit.hpp">
<namespace name="boost">
<class name="bad_visit">
<inherit access="public">
<classname>std::exception</classname>
</inherit>
<purpose>
<simpara>The exception thrown in the event of a visitor
unable to handle the visited value.</simpara>
</purpose>
<method name="what" specifiers="virtual" cv="const">
<type>const char *</type>
</method>
</class>
</namespace>
</header>

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.concepts">
<title>Concepts</title>
<using-namespace name="boost"/>
<section id="variant.concepts.bounded-type">
<title><emphasis>BoundedType</emphasis></title>
<para>The requirements on a <emphasis role="bold">bounded type</emphasis>
are as follows:</para>
<itemizedlist>
<listitem><conceptname>CopyConstructible</conceptname> or <conceptname>MoveConstructible</conceptname>.</listitem>
<listitem>Destructor upholds the no-throw exception-safety
guarantee.</listitem>
<listitem>Complete at the point of <code>variant</code> template
instantiation. (See
<code><classname>boost::recursive_wrapper</classname>&lt;T&gt;</code>
for a type wrapper that accepts incomplete types to enable recursive
<code>variant</code> types.)</listitem>
</itemizedlist>
<para>Every type specified as a template argument to
<code><classname>variant</classname></code> must at minimum fulfill the
above requirements. In addition, certain features of <code>variant</code>
are available only if its bounded types meet the requirements of these
following additional concepts:</para>
<itemizedlist>
<listitem><conceptname>Assignable</conceptname>:
<code>variant</code> is itself <emphasis>Assignable</emphasis> if and
only if every one of its bounded types meets the requirements of the
concept. (Note that top-level <code>const</code>-qualified types and
reference types do <emphasis>not</emphasis> meet these
requirements.)</listitem>
<listitem><conceptname>MoveAssignable</conceptname>:
<code>variant</code> is itself <emphasis>MoveAssignable</emphasis> if and
only if every one of its bounded types meets the requirements of the
concept. (Note that top-level <code>const</code>-qualified types and
reference types do <emphasis>not</emphasis> meet these
requirements.)</listitem>
<listitem><conceptname>DefaultConstructible</conceptname> [20.1.4]:
<code>variant</code> is itself
<conceptname>DefaultConstructible</conceptname> if and only if its first
bounded type (i.e., <code>T1</code>) meets the requirements of the
concept.</listitem>
<listitem><conceptname>EqualityComparable</conceptname>:
<code>variant</code> is itself <conceptname>EqualityComparable</conceptname>
if and only if every one of its bounded types meets the requirements
of the concept.</listitem>
<listitem><conceptname>LessThanComparable</conceptname>:
<code>variant</code> is itself <conceptname>LessThanComparable</conceptname>
if and only if every one of its bounded types meets the requirements
of the concept.</listitem>
<listitem><link linkend="variant.concepts.output-streamable"><emphasis>OutputStreamable</emphasis></link>:
<code>variant</code> is itself <emphasis>OutputStreamable</emphasis>
if and only if every one of its bounded types meets the requirements
of the concept.</listitem>
<listitem><link linkend="variant.concepts.hashable"><emphasis>Hashable</emphasis></link>:
<code>variant</code> is itself <emphasis>Hashable</emphasis>
if and only if every one of its bounded types meets the requirements
of the concept.</listitem>
</itemizedlist>
</section>
<section id="variant.concepts.static-visitor">
<title><emphasis>StaticVisitor</emphasis></title>
<para>The requirements on a <emphasis role="bold">static
visitor</emphasis> of a type <code>T</code> are as follows:</para>
<itemizedlist>
<listitem>Must allow invocation as a function by overloading
<code>operator()</code>, unambiguously accepting any value of type
<code>T</code>.</listitem>
<listitem>Must expose inner type <code>result_type</code>. C++14 compatible compilers
could detect <code>result_type</code> automatically, but will stick to
<code>result_type</code> if it is defined. (See
<code><functionname>boost::visitor_ptr</functionname></code> for a
solution to using functions as visitors.)</listitem>
<listitem>If <code>result_type</code> is not <code>void</code>, then
each operation of the function object must return a value implicitly
convertible to <code>result_type</code>.</listitem>
</itemizedlist>
<section id="variant.concepts.static-visitor.examples">
<title>Examples</title>
<para>The following class satisfies the requirements of a static visitor
of several types (i.e., explicitly: <code>int</code> and
<code>std::string</code>; or, e.g., implicitly: <code>short</code> and
<code>const char *</code>; etc.):</para>
<programlisting>class my_visitor
: public <classname>boost::static_visitor</classname>&lt;int&gt;
{
public:
int operator()(int i)
{
return i * 2;
}
int operator()(const std::string&amp; s)
{
return s.length();
}
};</programlisting>
<para>Another example is the following class, whose function-call
operator is a member template, allowing it to operate on values of many
types. Thus, the following class is a visitor of any type that supports
streaming output (e.g., <code>int</code>, <code>double</code>,
<code>std::string</code>, etc.):</para>
<programlisting>class printer
: public <classname>boost::static_visitor</classname>&lt;&gt;
{
template &lt;typename T&gt;
void operator()(const T&amp; t)
{
std::cout &lt;&lt; t &lt;&lt; std::endl;
}
};</programlisting>
<para>C++14 compatible compilers detect <code>result_type</code> automatically:</para>
<programlisting>
<classname>boost::variant</classname>&lt;int, float&gt; v;
// ...
<functionname>boost::apply_visitor</functionname>(
[](auto val) { return std::to_string(val); },
v
);
</programlisting>
</section>
</section>
<section id="variant.concepts.output-streamable">
<title><emphasis>OutputStreamable</emphasis></title>
<para>The requirements on an <emphasis role="bold">output
streamable</emphasis> type <code>T</code> are as follows:</para>
<itemizedlist>
<listitem>For any object <code>t</code> of type <code>T</code>,
<code>std::cout &lt;&lt; t</code> must be a valid
expression.</listitem>
</itemizedlist>
</section>
<section id="variant.concepts.hashable">
<title><emphasis>Hashable</emphasis></title>
<para>The requirements on an <emphasis role="bold">hashable</emphasis> type <code>T</code> are as follows:</para>
<itemizedlist>
<listitem>For any object <code>t</code> of type <code>T</code>,
<code>boost::hash&lt;T&gt;()(t)</code> must be a valid
expression.</listitem>
</itemizedlist>
</section>
</section>

View File

@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/get.hpp">
<namespace name="boost">
<class name="bad_get">
<inherit access="public">
<classname>std::exception</classname>
</inherit>
<purpose>
<simpara>The exception thrown in the event of a failed application of
<code><functionname>boost::get</functionname></code> on the given
operand value.</simpara>
</purpose>
<method name="what" specifiers="virtual" cv="const">
<type>const char *</type>
</method>
</class>
<overloaded-function name="relaxed_get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;&amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;&amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>. </simpara>
<simpara>Unlike <functionname>strict_get</functionname> does not assert at compile time
that type <code>U</code> is one of the types that can be stored in variant.</simpara>
</purpose>
<description>
<simpara>The <code>get</code> function allows run-time checked,
type-safe retrieval of the content of the given
<code><classname>variant</classname></code>. The function succeeds
only if the content is of the specified type <code>U</code>, with
failure indicated as described below.</simpara>
<simpara><emphasis role="bold">Recomendation</emphasis>: Use
<functionname>get</functionname> or <functionname>strict_get</functionname> in new code.
<functionname>strict_get</functionname>
provides more compile time checks and its behavior is closer to <code>std::get</code>
from C++ Standard Library.</simpara>
<simpara><emphasis role="bold">Warning</emphasis>: After either
<code>operand</code> or its content is destroyed (e.g., when the
given <code><classname>variant</classname></code> is assigned a
value of different type), the returned reference is invalidated.
Thus, significant care and caution must be extended when handling
the returned reference.</simpara>
</description>
<notes>
<simpara>As part of its guarantee of type-safety, <code>get</code>
enforces <code>const</code>-correctness. Thus, the specified type
<code>U</code> must be <code>const</code>-qualified whenever
<code>operand</code> or its content is likewise
<code>const</code>-qualified. The converse, however, is not required:
that is, the specified type <code>U</code> may be
<code>const</code>-qualified even when <code>operand</code> and its
content are not.</simpara>
</notes>
<returns>
<simpara>If passed a pointer, <code>get</code> returns a pointer to
the value content if it is of the specified type <code>U</code>;
otherwise, a null pointer is returned. If passed a reference,
<code>get</code> returns a reference to the value content if it is of
the specified type <code>U</code>; otherwise, an exception is thrown
(see below).</simpara>
</returns>
<throws>
<simpara>Overloads taking a
<code><classname>variant</classname></code> pointer will not
throw; the overloads taking a
<code><classname>variant</classname></code> reference throw
<code><classname>bad_get</classname></code> if the content is not of
the specified type <code>U</code>.</simpara>
</throws>
<rationale>
<simpara>While visitation via
<code><functionname>apply_visitor</functionname></code>
is generally preferred due to its greater safety, <code>get</code> may
may be more convenient in some cases due to its straightforward
usage.</simpara>
</rationale>
</overloaded-function>
<overloaded-function name="strict_get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;&amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;&amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<simpara>Acts exactly like <functionname>relaxed_get</functionname> but does a compile time check
that type <code>U</code> is one of the types that can be stored in variant.</simpara>
</description>
</overloaded-function>
<overloaded-function name="get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;&amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;&amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<simpara>Evaluates to <functionname>strict_get</functionname> if <code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>
is not defined. If <code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>
is defined then evaluates to <functionname>relaxed_get</functionname>. </simpara>
<simpara><emphasis role="bold">Recomendation</emphasis>: Use
<functionname>get</functionname> in new code without defining
<code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>. In that way <functionname>get</functionname>
provides more compile time checks and its behavior is closer to <code>std::get</code>
from C++ Standard Library.</simpara>
</description>
</overloaded-function>
</namespace>
</header>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2013-2022 Antony Polukhin.
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)
-->
<header name="boost/variant/multivisitors.hpp">
<using-namespace name="boost"/>
<para>Provides declarations of <functionname>apply_visitor</functionname> for three or more
<code><classname>variant</classname></code> parameters.</para>
<macro name="BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS">
<purpose>
<simpara>Controls maximum amount of <code><classname>variant</classname></code>
parameters for multi visistors. Not used when <code>std::tuple</code> is available and
<code><macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname></code>
is not defined.</simpara>
</purpose>
<description>
<para><emphasis role="bold">Note</emphasis>: Default amount is 4. Define it
to bigger value before including &lt;boost/variant/multivisitors.hpp&gt; to
increase maximum amount of <code><classname>variant</classname></code>
parameters for <functionname>apply_visitor</functionname>.</para>
</description>
</macro>
<namespace name="boost">
<overloaded-function name="apply_visitor /*three or more variant parameters*/">
<description>
<simpara>Allows compile-time checked type-safe application of the
given visitor to the content of the given variant, ensuring that all
types are handled by the visitor. See <functionname>apply_visitor</functionname>
for more information.</simpara>
</description>
<signature>
<template>
<template-type-parameter name="MultiVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
<template-type-parameter name="Variant3"/>
</template>
<type>typename MultiVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>MultiVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
<parameter name="operand3">
<paramtype>Variant3&amp;&amp;</paramtype>
</parameter>
<parameter name="other_operands">
<paramtype>...</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="MultiVisitor"/>
<template-type-parameter name="Variant1"/>
<template-type-parameter name="Variant2"/>
<template-type-parameter name="Variant3"/>
</template>
<type>typename MultiVisitor::result_type OR decltype(auto)</type>
<parameter name="visitor">
<paramtype>const MultiVisitor &amp;</paramtype>
</parameter>
<parameter name="operand1">
<paramtype>Variant1&amp;&amp;</paramtype>
</parameter>
<parameter name="operand2">
<paramtype>Variant2&amp;&amp;</paramtype>
</parameter>
<parameter name="operand3">
<paramtype>Variant3&amp;&amp;</paramtype>
</parameter>
<parameter name="other_operands">
<paramtype>...</paramtype>
</parameter>
</signature>
</overloaded-function>
</namespace>
</header>

View File

@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2013-2022 Antony Polukhin.
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)
-->
<header name="boost/variant/polymorphic_get.hpp">
<namespace name="boost">
<class name="bad_polymorphic_get">
<inherit access="public">
<classname>boost::bad_get</classname>
</inherit>
<purpose>
<simpara>The exception thrown in the event of a failed application of
<code><functionname>boost::polymorphic_get</functionname></code> on the given
operand value.</simpara>
</purpose>
<method name="what" specifiers="virtual" cv="const">
<type>const char *</type>
</method>
</class>
<overloaded-function name="polymorphic_relaxed_get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>.</simpara>
<simpara>Unlike <functionname>polymorphic_strict_get</functionname> does not assert at compile time
that type <code>U</code> is one of the types that can be stored in variant.</simpara>
</purpose>
<description>
<simpara>The <code>polymorphic_get</code> function allows run-time checked,
type-safe retrieval of the content of the given
<code><classname>variant</classname></code>. The function succeeds
only if the content is of the specified type <code>U</code> or of type
derived from type <code>U</code>, with
failure indicated as described below.</simpara>
<simpara><emphasis role="bold">Recomendation</emphasis>: Use
<functionname>polymorphic_get</functionname> or <functionname>polymorphic_strict_get</functionname>
in new code.
<functionname>polymorphic_strict_get</functionname>
provides more compile time checks and its behavior is closer to <code>std::get</code>
from C++ Standard Library.</simpara>
<simpara><emphasis role="bold">Warning</emphasis>: After either
<code>operand</code> or its content is destroyed (e.g., when the
given <code><classname>variant</classname></code> is assigned a
value of different type), the returned reference is invalidated.
Thus, significant care and caution must be extended when handling
the returned reference.</simpara>
</description>
<notes>
<simpara>As part of its guarantee of type-safety, <code>polymorphic_get</code>
enforces <code>const</code>-correctness. Thus, the specified type
<code>U</code> must be <code>const</code>-qualified whenever
<code>operand</code> or its content is likewise
<code>const</code>-qualified. The converse, however, is not required:
that is, the specified type <code>U</code> may be
<code>const</code>-qualified even when <code>operand</code> and its
content are not.</simpara>
</notes>
<returns>
<simpara>If passed a pointer, <code>polymorphic_get</code> returns a pointer to
the value content if it is of the specified type <code>U</code> or of type
derived from type <code>U</code>;
otherwise, a null pointer is returned. If passed a reference,
<code>polymorphic_get</code> returns a reference to the value content if it is of
the specified type <code>U</code> or of type
derived from type <code>U</code>; otherwise, an exception is thrown
(see below).</simpara>
</returns>
<throws>
<simpara>Overloads taking a
<code><classname>variant</classname></code> pointer will not
throw; the overloads taking a
<code><classname>variant</classname></code> reference throw
<code><classname>bad_polymorphic_get</classname></code> if the content is not of
the specified type <code>U</code>or of type
derived from type <code>U</code>.</simpara>
</throws>
<rationale>
<simpara>While visitation via
<code><functionname>apply_visitor</functionname></code>
is generally preferred due to its greater safety, <code>polymorphic_get</code> may
may be more convenient in some cases due to its straightforward
usage.</simpara>
</rationale>
</overloaded-function>
<overloaded-function name="polymorphic_strict_get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<simpara>Acts exactly like <functionname>polymorphic_relaxed_get</functionname> but does a compile time check
that type <code>U</code> is one of the types that can be stored in variant.</simpara>
</description>
</overloaded-function>
<overloaded-function name="polymorphic_get">
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U *</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U *</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; *</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>U &amp;</type>
<parameter name="operand">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>const U &amp;</type>
<parameter name="operand">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
</signature>
<purpose>
<simpara>Retrieves a value of a specified type from a given
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<simpara>Evaluates to <functionname>polymorphic_strict_get</functionname>
if <code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>
is not defined. If <code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>
is defined then evaluates to <functionname>polymorphic_relaxed_get</functionname>. </simpara>
<simpara><emphasis role="bold">Recomendation</emphasis>: Use
<functionname>polymorphic_get</functionname> in new code without defining
<code>BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT</code>. In that way
<functionname>polymorphic_get</functionname>
provides more compile time checks and its behavior is closer to <code>std::get</code>
from C++ Standard Library.</simpara>
</description>
</overloaded-function>
</namespace>
</header>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/recursive_variant.hpp">
<namespace name="boost">
<typedef name="recursive_variant_">
<type><emphasis>unspecified</emphasis></type>
</typedef>
<class name="make_recursive_variant">
<purpose>Simplifies declaration of recursive <code>variant</code> types.</purpose>
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2">
<default><emphasis>unspecified</emphasis></default>
</template-type-parameter>
<template-varargs/>
<template-type-parameter name="TN">
<default><emphasis>unspecified</emphasis></default>
</template-type-parameter>
</template>
<description>
<para><code>type</code> has behavior equivalent in every respect to
some <code>variant&lt; U1, U2, ..., UN &gt;</code>, where each type
<code>U<emphasis>i</emphasis></code> is the result of the
corresponding type <code>T<emphasis>i</emphasis></code> undergone a
transformation function. The following pseudo-code specifies the
behavior of this transformation (call it <code>substitute</code>):
<itemizedlist>
<listitem>If <code>T<emphasis>i</emphasis></code> is
<code>boost::recursive_variant_</code> then:
<code>variant&lt; U1, U2, ..., UN &gt;</code>;</listitem>
<listitem>Else if <code>T<emphasis>i</emphasis></code> is of the
form <code>X *</code> then:
<code>substitute(X) *</code>;</listitem>
<listitem>Else if <code>T<emphasis>i</emphasis></code> is of the
form <code>X &amp;</code> then:
<code>substitute(X) &amp;</code>;</listitem>
<listitem>Else if <code>T<emphasis>i</emphasis></code> is of the
form <code>R (*)( X1, X2, ..., XN )</code> then:
<code>substitute(R) (*)( substitute(X1), substitute(X2), ..., substitute(XN) )</code>;</listitem>
<listitem>Else if <code>T<emphasis>i</emphasis></code> is of the
form <code>F &lt; X1, X2, ..., XN &gt;</code> then:
<code>F&lt; substitute(X1), substitute(X2), ..., substitute(XN) &gt;</code>;</listitem>
<listitem>Else: <code>T<emphasis>i</emphasis></code>.</listitem>
</itemizedlist>
</para>
<para>Note that cv-qualifiers are preserved and that the actual
process is generally a bit more complicated. However, the above does
convey the essential idea as well as describe the extent of the
substititions.</para>
<para>Use of <code>make_recursive_variant</code> is demonstrated in
<xref linkend="variant.tutorial.recursive.recursive-variant"/>.</para>
<para><emphasis role="bold">Portability</emphasis>: Due to standard
conformance issues in several compilers,
<code>make_recursive_variant</code> is not universally supported. On
these compilers the library indicates its lack of support via the
definition of the preprocessor symbol
<code><macroname>BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT</macroname></code>.</para>
</description>
<typedef name="type">
<type><classname>boost::variant</classname>&lt; <emphasis>unspecified</emphasis> &gt;</type>
</typedef>
</class>
<class name="make_recursive_variant_over">
<purpose>
<simpara>Exposes a recursive <code>variant</code> whose bounded types
are the elements of the given type sequence.</simpara>
</purpose>
<template>
<template-type-parameter name="Sequence"/>
</template>
<typedef name="type">
<type>variant&lt; <emphasis>unspecified</emphasis> &gt;</type>
</typedef>
<description>
<simpara><code>type</code> has behavior equivalent in every respect to
<code><classname>make_recursive_variant</classname>&lt; Sequence[0], Sequence[1], ... &gt;::type</code>
(where <code>Sequence[<emphasis>i</emphasis>]</code> denotes the
<emphasis>i</emphasis>-th element of <code>Sequence</code>), except
that no upper limit is imposed on the number of types.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:</simpara>
<itemizedlist>
<listitem><code>Sequence</code> must meet the requirements of
<libraryname>MPL</libraryname>'s <emphasis>Sequence</emphasis>
concept.</listitem>
<listitem>Due to standard conformance problems in several compilers,
<code>make_recursive_variant_over</code> may not be supported on
your compiler. See
<code><macroname>BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT</macroname></code>
for more information.</listitem>
</itemizedlist>
</description>
</class>
</namespace>
</header>

View File

@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/recursive_wrapper.hpp">
<namespace name="boost">
<class name="recursive_wrapper">
<purpose>Solves circular dependencies, enabling recursive types.</purpose>
<template>
<template-type-parameter name="T"/>
</template>
<description>
<simpara>The <code>recursive_wrapper</code> class template has an
interface similar to a simple value container, but its content is
allocated dynamically. This allows <code>recursive_wrapper</code> to
hold types <code>T</code> whose member data leads to a circular
dependency (e.g., a data member of <code>T</code> has a data member
of type <code>T</code>).</simpara>
<simpara>The application of <code>recursive_wrapper</code> is easiest
understood in context. See
<xref linkend="variant.tutorial.recursive.recursive-wrapper"/> for a
demonstration of a common use of the class template.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:</simpara>
<itemizedlist>
<listitem>Any type specified as the template argument to
<code>recursive_wrapper</code> must be capable of construction via
<code>operator new</code>. Thus, for instance, references are not
supported.</listitem>
</itemizedlist>
</description>
<typedef name="type">
<type>T</type>
</typedef>
<destructor>
<purpose>Destructor.</purpose>
<description>
<simpara>Deletes the content of <code>*this</code>.</simpara>
</description>
<throws>Will not throw.</throws>
</destructor>
<constructor>
<purpose>Default constructor.</purpose>
<description>
<simpara>Initializes <code>*this</code> by default construction of
<code>T</code>.</simpara>
</description>
<requires>
<simpara><code>T</code> must fulfill the requirements of the
<emphasis>DefaultConstructible</emphasis> [20.1.4]
concept.</simpara>
</requires>
<throws>
<simpara>May fail with any exceptions arising from the default
constructor of <code>T</code> or, in the event of
insufficient memory, with <code>std::bad_alloc</code>.</simpara>
</throws>
</constructor>
<constructor>
<parameter name="other">
<paramtype>const recursive_wrapper &amp;</paramtype>
</parameter>
<purpose>Copy constructor.</purpose>
<description>
<simpara>Copies the content of <code>other</code> into
<code>*this</code>.</simpara>
</description>
<throws>
<simpara>May fail with any exceptions arising from the
copy constructor of <code>T</code> or, in the event of
insufficient memory, with <code>std::bad_alloc</code>.</simpara>
</throws>
</constructor>
<constructor>
<parameter name="operand">
<paramtype>const T &amp;</paramtype>
</parameter>
<purpose>Value constructor.</purpose>
<description>
<simpara>Copies <code>operand</code> into
<code>*this</code>.</simpara>
</description>
<throws>
<simpara>May fail with any exceptions arising from the
copy constructor of <code>T</code> or, in the event of
insufficient memory, with <code>std::bad_alloc</code>.</simpara>
</throws>
</constructor>
<method-group name="modifiers">
<method name="swap">
<type>void</type>
<parameter name="other">
<paramtype>recursive_wrapper &amp;</paramtype>
</parameter>
<description>
<simpara>Exchanges contents of <code>*this</code> and
<code>other</code>.</simpara>
</description>
<throws>Will not throw.</throws>
</method>
<method name="operator=">
<type>recursive_wrapper &amp;</type>
<parameter name="rhs">
<paramtype>const recursive_wrapper &amp;</paramtype>
</parameter>
<purpose>Copy assignment operator.</purpose>
<description>
<simpara>Assigns the content of <code>rhs</code> to the content of
<code>*this</code>.</simpara>
</description>
<requires>
<simpara><code>T</code> must fulfill the requirements of
the <conceptname>Assignable</conceptname>
concept.</simpara>
</requires>
<throws>
<simpara>May fail with any exceptions arising from the assignment
operator of <code>T</code>.</simpara>
</throws>
</method>
<method name="operator=">
<type>recursive_wrapper &amp;</type>
<parameter name="rhs">
<paramtype>const T &amp;</paramtype>
</parameter>
<purpose>Value assignment operator.</purpose>
<description>
<simpara>Assigns <code>rhs</code> into the content of
<code>*this</code>.</simpara>
</description>
<requires>
<simpara><code>T</code> must fulfill the requirements of the
<conceptname>Assignable</conceptname>
concept.</simpara>
</requires>
<throws>
<simpara>May fail with any exceptions arising from the assignment
operator of <code>T</code>.</simpara>
</throws>
</method>
</method-group>
<method-group name="queries">
<overloaded-method name="get">
<signature>
<type>T &amp;</type>
</signature>
<signature cv="const">
<type>const T &amp;</type>
</signature>
<description>
<simpara>Returns a reference to the content of
<code>*this</code>.</simpara>
</description>
<throws>Will not throw.</throws>
</overloaded-method>
<overloaded-method name="get_pointer">
<signature>
<type>T *</type>
</signature>
<signature cv="const">
<type>const T *</type>
</signature>
<description>
<simpara>Returns a pointer to the content of
<code>*this</code>.</simpara>
</description>
<throws>Will not throw.</throws>
</overloaded-method>
</method-group>
</class>
<class name="is_recursive_wrapper">
<purpose>
<simpara>Determines whether the specified type is a specialization of
<code>recursive_wrapper</code>.</simpara>
</purpose>
<template>
<template-type-parameter name="T"/>
</template>
<description>
<simpara>Value is true iff <code>T</code> is a specialization of
<code><classname>recursive_wrapper</classname></code>.</simpara>
<simpara><emphasis role="bold">Note</emphasis>:
<code>is_recursive_wrapper</code> is a model of
<libraryname>MPL</libraryname>'s
<emphasis>IntegralConstant</emphasis> concept.</simpara>
</description>
<typedef name="type">
<type><emphasis>unspecified</emphasis></type>
</typedef>
<static-constant name="value">
<type>bool</type>
<default><emphasis>unspecified</emphasis></default>
</static-constant>
</class>
<class name="unwrap_recursive_wrapper">
<purpose>
<simpara>Unwraps the specified argument if given a specialization of
<code><classname>recursive_wrapper</classname></code>.</simpara>
</purpose>
<template>
<template-type-parameter name="T"/>
</template>
<description>
<simpara><code>type</code> is equivalent to <code>T::type</code> if
<code>T</code> is a specialization of
<code><classname>recursive_wrapper</classname></code>. Otherwise,
<code>type</code> is equivalent to <code>T</code>.</simpara>
</description>
<typedef name="type">
<type><emphasis>unspecified</emphasis></type>
</typedef>
</class>
</namespace>
</header>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library-reference PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<library-reference xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="concepts.xml"/>
<header name="boost/variant.hpp">
<section id="variant.header.include-all">
<para>This header exists simply as a convenience to the user, including
all of the headers in the <code>boost/variant</code> directory except &lt;boost/multivisiors.hpp&gt;.</para>
</section>
</header>
<xi:include href="variant_fwd.xml"/>
<xi:include href="variant.xml"/>
<xi:include href="recursive_variant.xml"/>
<xi:include href="recursive_wrapper.xml"/>
<xi:include href="apply_visitor.xml"/>
<xi:include href="multivisitor.xml"/>
<xi:include href="get.xml"/>
<xi:include href="polymorphic_get.xml"/>
<xi:include href="bad_visit.xml"/>
<xi:include href="static_visitor.xml"/>
<xi:include href="visitor_ptr.xml"/>
</library-reference>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/static_visitor.hpp">
<namespace name="boost">
<class name="static_visitor">
<template>
<template-type-parameter name="ResultType"/>
</template>
<purpose>Convenient base type for static visitors.</purpose>
<description>
<simpara>Denotes the intent of the deriving class as meeting the
requirements of a static visitor of some type. Also exposes the
inner type <code>result_type</code> as required by the
<link linkend="variant.concepts.static-visitor"><emphasis>StaticVisitor</emphasis></link>
concept.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:
<code>static_visitor</code> is intended for use as a base type only
and is therefore noninstantiable.</simpara>
</description>
<typedef name="result_type">
<type>ResultType</type>
<purpose>Exposes result_type member as required by StaticVisitor concept.</purpose>
</typedef>
</class>
</namespace>
</header>

View File

@@ -0,0 +1,963 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/variant.hpp">
<namespace name="boost">
<class name="variant">
<purpose>Safe, generic, stack-based discriminated union container.</purpose>
<description>
<simpara>The <code>variant</code> class template (inspired by Andrei
Alexandrescu's class of the same name
[<link linkend="variant.refs.ale01a">Ale01A</link>]) is an efficient,
<link linkend="variant.tutorial.recursive">recursive-capable</link>,
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
<code>variant</code> whose bounded types are each convertible to one
of the destination <code>variant</code>'s bounded types. As well,
through <code><functionname>apply_visitor</functionname></code>,
<code>variant</code> supports compile-time checked, type-safe
visitation; and through <code><functionname>get</functionname></code>,
<code>variant</code> supports run-time checked, type-safe value
retrieval.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:</simpara>
<itemizedlist>
<listitem>The bounded types of the <code>variant</code> are exposed
via the nested typedef <code>types</code>, which is an
<libraryname>MPL</libraryname>-compatible Sequence containing the
set of types that must be handled by any
<link linkend="variant.concepts.static-visitor">visitor</link> to
the <code>variant</code>.</listitem>
<listitem>All members of <code>variant</code> satisfy at least the
basic guarantee of exception-safety. That is, all operations on
a <code>variant</code> remain defined even after previous
operations have failed.</listitem>
<listitem>Each type specified as a template argument to
<code>variant</code> must meet the requirements of the
<emphasis><link linkend="variant.concepts.bounded-type">BoundedType</link></emphasis>
concept.</listitem>
<listitem>Each type specified as a template argument to
<code>variant</code> must be distinct after removal of qualifiers.
Thus, for instance, both <code>variant&lt;int, int&gt;</code> and
<code>variant&lt;int, const int&gt;</code> have undefined
behavior.</listitem>
<listitem>Conforming implementations of <code>variant</code> must
allow at least ten types as template arguments. The exact number
of allowed arguments is exposed by the preprocessor macro
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname></code>.
(See <code><classname>make_variant_over</classname></code> for a
means to specify the bounded types of a <code>variant</code> by
the elements of an <libraryname>MPL</libraryname> or compatible
Sequence, thus overcoming this limitation.)</listitem>
</itemizedlist>
</description>
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2">
<default><emphasis>unspecified</emphasis></default>
</template-type-parameter>
<template-varargs/>
<template-type-parameter name="TN">
<default><emphasis>unspecified</emphasis></default>
</template-type-parameter>
</template>
<typedef name="types">
<type><emphasis>unspecified</emphasis></type>
</typedef>
<destructor>
<effects>
<simpara>Destroys the content of <code>*this</code>.</simpara>
</effects>
<throws>Will not throw.</throws>
</destructor>
<constructor>
<requires>
<simpara>The first bounded type of the <code>variant</code> (i.e.,
<code>T1</code>) must fulfill the requirements of the
<emphasis>DefaultConstructible</emphasis> [20.1.4]
concept.</simpara>
</requires>
<postconditions>
<simpara>Content of <code>*this</code> is the default value of the
first bounded type (i.e, <code>T1</code>).</simpara>
</postconditions>
<throws>
<simpara>May fail with any exceptions arising from the default
constructor of <code>T1</code>.</simpara>
</throws>
</constructor>
<constructor>
<parameter name="other">
<paramtype>const variant &amp;</paramtype>
</parameter>
<postconditions>
<simpara>Content of <code>*this</code> is a copy of the content of
<code>other</code>.</simpara>
</postconditions>
<throws>
<simpara>May fail with any exceptions arising from the
copy constructor of <code>other</code>'s contained type.</simpara>
</throws>
</constructor>
<constructor>
<parameter name="other">
<paramtype>variant &amp;&amp;</paramtype>
</parameter>
<requires>
<simpara>C++11 compatible compiler.</simpara>
</requires>
<postconditions>
<simpara>Content of <code>*this</code> is move constructed from the content of
<code>other</code>.</simpara>
</postconditions>
<throws>
<simpara>May fail with any exceptions arising from the
move constructor of <code>other</code>'s contained type.</simpara>
</throws>
</constructor>
<constructor>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="operand">
<paramtype>T &amp;</paramtype>
</parameter>
<requires>
<simpara><code>T</code> must be unambiguously convertible to one of
the bounded types (i.e., <code>T1</code>, <code>T2</code>,
etc.).</simpara>
</requires>
<postconditions>
<simpara>Content of <code>*this</code> is the best conversion of
<code>operand</code> to one of the bounded types, as determined
by standard overload resolution rules.</simpara>
</postconditions>
<throws>
<simpara>May fail with any exceptions arising from the conversion of
<code>operand</code> to one of the bounded types.</simpara>
</throws>
</constructor>
<constructor>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="operand">
<paramtype>const T &amp;</paramtype>
</parameter>
<notes>
<simpara>Same semantics as previous constructor, but allows
construction from temporaries.</simpara>
</notes>
</constructor>
<constructor>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="operand">
<paramtype>T &amp;&amp;</paramtype>
</parameter>
<requires>
<simpara>C++11 compatible compiler.</simpara>
</requires>
<notes>
<simpara>Same semantics as previous constructor, but allows
move construction if <code>operand</code> is an rvalue.</simpara>
</notes>
</constructor>
<constructor>
<template>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
</template>
<parameter name="operand">
<paramtype>variant&lt;U1, U2, ..., UN&gt; &amp;</paramtype>
</parameter>
<requires>
<simpara><emphasis>Every</emphasis> one of <code>U1</code>,
<code>U2</code>, ..., <code>UN</code> must have an unambiguous
conversion to one of the bounded types (i.e., <code>T1</code>,
<code>T2</code>, ..., <code>TN</code>).</simpara>
</requires>
<postconditions>
<simpara>If <code>variant&lt;U1, U2, ..., UN&gt;</code> is itself
one of the bounded types, then content of <code>*this</code> is a
copy of <code>operand</code>. Otherwise, content of
<code>*this</code> is the best conversion of the content of
<code>operand</code> to one of the bounded types, as determined
by standard overload resolution rules.</simpara>
</postconditions>
<throws>
<simpara>If <code>variant&lt;U1, U2, ..., UN&gt;</code> is itself
one of the bounded types, then may fail with any exceptions arising
from the copy constructor of
<code>variant&lt;U1, U2, ..., UN&gt;</code>. Otherwise, may fail
with any exceptions arising from the conversion of the content of
<code>operand</code> to one of the bounded types.</simpara>
</throws>
</constructor>
<constructor>
<template>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
</template>
<parameter name="operand">
<paramtype>const variant&lt;U1, U2, ..., UN&gt; &amp;</paramtype>
</parameter>
<notes>
<simpara>Same semantics as previous constructor, but allows
construction from temporaries.</simpara>
</notes>
</constructor>
<constructor>
<template>
<template-type-parameter name="U1"/>
<template-type-parameter name="U2"/>
<template-varargs/>
<template-type-parameter name="UN"/>
</template>
<requires>
<simpara>C++11 compatible compiler.</simpara>
</requires>
<parameter name="operand">
<paramtype>variant&lt;U1, U2, ..., UN&gt; &amp;&amp;</paramtype>
</parameter>
<notes>
<simpara>Same semantics as previous constructor, but allows
move construction.</simpara>
</notes>
</constructor>
<method-group name="modifiers">
<method name="swap">
<type>void</type>
<parameter name="other">
<paramtype>variant &amp;</paramtype>
</parameter>
<requires>
<simpara>Every bounded type must fulfill the requirements of the
<conceptname>MoveAssignable</conceptname>
concept.</simpara>
</requires>
<effects>
<simpara>Interchanges the content of <code>*this</code> and
<code>other</code>.</simpara>
</effects>
<throws>
<simpara>If the contained type of <code>other</code> is the same as
the contained type of <code>*this</code>, then may fail with any
exceptions arising from the <code>swap</code> of the contents of
<code>*this</code> and <code>other</code>. Otherwise, may fail
with any exceptions arising from either of the move or copy constructors
of the contained types. Also, in the event of insufficient
memory, may fail with <code>std::bad_alloc</code>
(<link linkend="variant.design.never-empty.problem">why?</link>).</simpara>
</throws>
</method>
<method name="operator=">
<type>variant &amp;</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
<requires>
<simpara>Every bounded type must fulfill the requirements of the
<conceptname>Assignable</conceptname>
concept.</simpara>
</requires>
<effects>
<simpara>If the contained type of <code>rhs</code> is the same as
the contained type of <code>*this</code>, then assigns the
content of <code>rhs</code> into the content of
<code>*this</code>. Otherwise, makes the content of
<code>*this</code> a copy of the content of <code>rhs</code>,
destroying the previous content of <code>*this</code>.</simpara>
</effects>
<throws>
<simpara>If the contained type of <code>rhs</code> is the same as
the contained type of <code>*this</code>, then may fail with any
exceptions arising from the assignment of the content of
<code>rhs</code> into the content <code>*this</code>. Otherwise,
may fail with any exceptions arising from the copy constructor
of the contained type of <code>rhs</code>. Also, in the event of
insufficient memory, may fail with <code>std::bad_alloc</code>
(<link linkend="variant.design.never-empty.problem">why?</link>).</simpara>
</throws>
</method>
<method name="operator=">
<type>variant &amp;</type>
<parameter name="rhs">
<paramtype>variant &amp;&amp;</paramtype>
</parameter>
<requires>
<itemizedlist>
<listitem>C++11 compatible compiler.</listitem>
<listitem>Every bounded type must fulfill the requirements of the
<conceptname>MoveAssignable</conceptname>
concept.</listitem>
</itemizedlist>
</requires>
<effects>
<simpara>If the contained type of <code>rhs</code> is the same as
the contained type of <code>*this</code>, then move assigns the
content of <code>rhs</code> into the content of
<code>*this</code>. Otherwise, move constructs
<code>*this</code> using the content of <code>rhs</code>,
destroying the previous content of <code>*this</code>.</simpara>
</effects>
<throws>
<simpara>If the contained type of <code>rhs</code> is the same as
the contained type of <code>*this</code>, then may fail with any
exceptions arising from the move assignment of the content of
<code>rhs</code> into the content <code>*this</code>. Otherwise,
may fail with any exceptions arising from the move constructor
of the contained type of <code>rhs</code>. Also, in the event of
insufficient memory, may fail with <code>std::bad_alloc</code>
(<link linkend="variant.design.never-empty.problem">why?</link>).</simpara>
</throws>
</method>
<method name="operator=">
<type>variant &amp;</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="rhs">
<paramtype>const T &amp;</paramtype>
</parameter>
<requires>
<itemizedlist>
<listitem><code>T</code> must be unambiguously convertible to
one of the bounded types (i.e., <code>T1</code>,
<code>T2</code>, etc.).</listitem>
<listitem>Every bounded type must fulfill the requirements of the
<conceptname>Assignable</conceptname>
concept.</listitem>
</itemizedlist>
</requires>
<effects>
<simpara>If the contained type of <code>*this</code> is
<code>T</code>, then assigns <code>rhs</code> into the content
of <code>*this</code>. Otherwise, makes the content of
<code>*this</code> the best conversion of <code>rhs</code> to
one of the bounded types, as determined by standard overload
resolution rules, destroying the previous content of
<code>*this</code>.</simpara>
</effects>
<throws>
<simpara>If the contained type of <code>*this</code> is
<code>T</code>, then may fail with any exceptions arising from
the assignment of <code>rhs</code> into the content
<code>*this</code>. Otherwise, may fail with any exceptions
arising from the conversion of <code>rhs</code> to one of the
bounded types. Also, in the event of insufficient memory, may
fail with <code>std::bad_alloc</code>
(<link linkend="variant.design.never-empty.problem">why?</link>).</simpara>
</throws>
</method>
<method name="operator=">
<type>variant &amp;</type>
<template>
<template-type-parameter name="T"/>
</template>
<parameter name="rhs">
<paramtype>T &amp;&amp;</paramtype>
</parameter>
<requires>
<itemizedlist>
<listitem>C++11 compatible compiler.</listitem>
<listitem><code>rhs</code> is an rvalue. Otherwise previous operator will be used.</listitem>
<listitem><code>T</code> must be unambiguously convertible to
one of the bounded types (i.e., <code>T1</code>,
<code>T2</code>, etc.).</listitem>
<listitem>Every bounded type must fulfill the requirements of the
<conceptname>MoveAssignable</conceptname>
concept.</listitem>
</itemizedlist>
</requires>
<effects>
<simpara>If the contained type of <code>*this</code> is
<code>T</code>, then move assigns <code>rhs</code> into the content
of <code>*this</code>. Otherwise, makes the content of
<code>*this</code> the best conversion of <code>rhs</code> to
one of the bounded types, as determined by standard overload
resolution rules, destroying the previous content of
<code>*this</code>(conversion is usually done via move construction).</simpara>
</effects>
<throws>
<simpara>If the contained type of <code>*this</code> is
<code>T</code>, then may fail with any exceptions arising from
the move assignment of <code>rhs</code> into the content
<code>*this</code>. Otherwise, may fail with any exceptions
arising from the conversion of <code>rhs</code> to one of the
bounded types. Also, in the event of insufficient memory, may
fail with <code>std::bad_alloc</code>
(<link linkend="variant.design.never-empty.problem">why?</link>).</simpara>
</throws>
</method>
</method-group>
<method-group name="queries">
<method name="which" cv="const">
<type>int</type>
<returns>
<simpara>The zero-based index into the set of bounded types
of the contained type of <code>*this</code>. (For instance, if
called on a <code>variant&lt;int, std::string&gt;</code> object
containing a <code>std::string</code>, <code>which()</code>
would return <code>1</code>.)</simpara>
</returns>
<throws>Will not throw.</throws>
</method>
<method name="empty" cv="const">
<type>bool</type>
<returns>
<simpara><code>false</code>: <code>variant</code> always contains
exactly one of its bounded types. (See
<xref linkend="variant.design.never-empty"/>
for more information.)</simpara>
</returns>
<rationale>
<simpara>Facilitates generic compatibility with
<classname>boost::any</classname>.</simpara>
</rationale>
<throws>Will not throw.</throws>
</method>
<method name="type" cv="const">
<type>const std::type_info &amp;</type>
<notes>
<simpara><code>boost::variant</code> usues Boost.TypeIndex library so actually
<code>const boost::typeindex::type_info &amp;</code> is returned.
This method is available even if RTTI is off.</simpara>
</notes>
<returns>
<simpara><code>typeid(x)</code>, where <code>x</code> is the the
content of <code>*this</code>.</simpara>
</returns>
<throws>Will not throw.</throws>
</method>
</method-group>
<method-group name="relational">
<overloaded-method name="operator==" cv="const">
<purpose>Equality comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>EqualityComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara><code>true</code> if <code>which() == rhs.which()</code>
<emphasis>and</emphasis>
<code>content_this == content_rhs</code>, where
<code>content_this</code> is the content of <code>*this</code>
and <code>content_rhs</code> is the content of
<code>rhs</code>.</simpara>
</returns>
<throws>
<simpara>If <code>which() == rhs.which()</code> then may fail with
any exceptions arising from <code>operator==(T,T)</code>, where
<code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
<overloaded-method name="operator!=" cv="const">
<purpose>InEquality comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>EqualityComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara><code>true</code> if <code>!(*this == rhs)</code>.</simpara>
</returns>
<throws>
<simpara>If <code>which() == rhs.which()</code> then may fail with
any exceptions arising from <code>operator==(T,T)</code>, where
<code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
<overloaded-method name="operator&lt;">
<purpose>LessThan comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>LessThanComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara>If <code>which() == rhs.which()</code> then:
<code>content_this &lt; content_rhs</code>, where
<code>content_this</code> is the content of <code>*this</code>
and <code>content_rhs</code> is the content of <code>rhs</code>.
Otherwise: <code>which() &lt; rhs.which()</code>.</simpara>
</returns>
<throws>
<simpara>If <code>which() == rhs.which()</code> then may fail with
any exceptions arising from <code>operator&lt;(T,T)</code>,
where <code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
<overloaded-method name="operator&gt;">
<purpose>GreaterThan comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>LessThanComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara>true if <code>rhs &lt; *this</code>.</simpara>
</returns>
<throws>
<simpara>May fail with
any exceptions arising from <code>operator&lt;(T,T)</code>,
where <code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
<overloaded-method name="operator&lt;=">
<purpose>LessThan or Equal comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>LessThanComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara>true if <code>!(*this > rhs)</code>.</simpara>
</returns>
<throws>
<simpara>May fail with
any exceptions arising from <code>operator&lt;(T,T)</code>,
where <code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
<overloaded-method name="operator&gt;=">
<purpose>GreaterThan or Equal comparison.</purpose>
<signature cv="const">
<type>bool</type>
<parameter name="rhs">
<paramtype>const variant &amp;</paramtype>
</parameter>
</signature>
<signature cv="const">
<type>void</type>
<template>
<template-type-parameter name="U"/>
</template>
<parameter>
<paramtype>const U &amp;</paramtype>
</parameter>
</signature>
<notes>
<simpara>The overload returning <code>void</code> exists only to
prohibit implicit conversion of the operator's right-hand side
to <code>variant</code>; thus, its use will (purposefully)
result in a compile-time error.</simpara>
</notes>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<conceptname>LessThanComparable</conceptname>
concept.</simpara>
</requires>
<returns>
<simpara>true if <code>!(*this &lt; lhs)</code>.</simpara>
</returns>
<throws>
<simpara>May fail with
any exceptions arising from <code>operator&lt;(T,T)</code>,
where <code>T</code> is the contained type of
<code>*this</code>.</simpara>
</throws>
</overloaded-method>
</method-group>
</class>
<function name="swap">
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>void</type>
<parameter name="lhs">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
<parameter name="rhs">
<paramtype><classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
<effects>
<simpara>Swaps <code>lhs</code> with <code>rhs</code> by application
of <code><methodname>variant::swap</methodname></code>.</simpara>
</effects>
<throws>
<simpara>May fail with any exception arising from
<code><methodname>variant::swap</methodname></code>.</simpara>
</throws>
</function>
<function name="operator&lt;&lt;">
<purpose>Provides streaming output for <code>variant</code> types.</purpose>
<template>
<template-type-parameter name="ElemType"/>
<template-type-parameter name="Traits"/>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>std::basic_ostream&lt;ElemType,Traits&gt; &amp;</type>
<parameter name="out">
<paramtype>std::basic_ostream&lt;ElemType,Traits&gt; &amp;</paramtype>
</parameter>
<parameter name="rhs">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<link linkend="variant.concepts.output-streamable"><emphasis>OutputStreamable</emphasis></link>
concept.</simpara>
</requires>
<effects>
<simpara>Calls <code>out &lt;&lt; x</code>, where <code>x</code> is
the content of <code>rhs</code>.</simpara>
</effects>
<notes>
<simpara>Not available when <code>BOOST_NO_IOSTREAM</code> is
defined.</simpara>
</notes>
</function>
<function name="hash_value">
<purpose>Provides hashing for <code>variant</code> types so
that <code>boost::hash</code> may compute hash.</purpose>
<template>
<template-type-parameter name="T1"/>
<template-type-parameter name="T2"/>
<template-varargs/>
<template-type-parameter name="TN"/>
</template>
<type>std::size_t</type>
<parameter name="rhs">
<paramtype>const <classname>variant</classname>&lt;T1, T2, ..., TN&gt; &amp;</paramtype>
</parameter>
<requires>
<simpara>Every bounded type of the <code>variant</code> must
fulfill the requirements of the
<link linkend="variant.concepts.hashable"><emphasis>Hashable</emphasis></link>
concept.</simpara>
</requires>
<effects>
<simpara>Calls <code>boost::hash&lt;T&gt;()(x)</code>, where <code>x</code> is
the content of <code>rhs</code> and <code>T</code> is its type.</simpara>
</effects>
<notes>
<simpara>Actually, this function is defined in
<code>&lt;boost/variant/detail/hash_variant.hpp&gt;</code>
header.</simpara>
</notes>
</function>
<class name="make_variant_over">
<purpose>
<simpara>Exposes a <code>variant</code> whose bounded types are the
elements of the given type sequence.</simpara>
</purpose>
<template>
<template-type-parameter name="Sequence"/>
</template>
<typedef name="type">
<type>variant&lt; <emphasis>unspecified</emphasis> &gt;</type>
</typedef>
<description>
<simpara><code>type</code> has behavior equivalent in every respect to
<code><classname>variant</classname>&lt; Sequence[0], Sequence[1], ... &gt;</code>
(where <code>Sequence[<emphasis>i</emphasis>]</code> denotes the
<emphasis>i</emphasis>-th element of <code>Sequence</code>), except
that no upper limit is imposed on the number of types.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:</simpara>
<itemizedlist>
<listitem><code>Sequence</code> must meet the requirements of
<libraryname>MPL</libraryname>'s <emphasis>Sequence</emphasis>
concept.</listitem>
<listitem>Due to standard conformance problems in several compilers,
<code>make_variant_over</code> may not be supported on your
compiler. See
<code><macroname>BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT</macroname></code>
for more information.</listitem>
</itemizedlist>
</description>
</class>
</namespace>
</header>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Copyright 2016-2022 Antony Polukhin.
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)
-->
<header name="boost/variant/variant_fwd.hpp">
<using-namespace name="boost"/>
<para>Provides forward declarations of the
<code><classname>boost::variant</classname></code>,
<code><classname>boost::make_variant_over</classname></code>,
<code><classname>boost::make_recursive_variant</classname></code>, and
<code><classname>boost::make_recursive_variant_over</classname></code>
class templates and the <code>boost::recursive_variant_</code> tag type.
Also defines several preprocessor symbols, as described below.</para>
<macro name="BOOST_VARIANT_LIMIT_TYPES">
<purpose>
<simpara>Expands to the length of the
template parameter list for
<code><classname>variant</classname></code>. Not used if
<code><macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname></code>
is not defined.
</simpara>
</purpose>
<description>
<para><emphasis role="bold">Note</emphasis>: Conforming
implementations of <code>variant</code> must allow at least ten
template arguments. That is, BOOST_VARIANT_LIMIT_TYPES must be greater
or equal to <code>10</code>.</para>
</description>
</macro>
<macro name="BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES">
<purpose>
<simpara>If this macro is defined, then library won't use C++11 variadic templates.
Users may define this macro to make
<code><macroname>BOOST_VARIANT_ENUM_PARAMS</macroname></code>
and <code><macroname>BOOST_VARIANT_ENUM_SHIFTED_PARAMS</macroname></code> expand
to a comma-separated sequence instead of variadic templates. Define this macro if
your compiler has problems with compilation of variadic templates.
</simpara>
</purpose>
</macro>
<macro name="BOOST_VARIANT_ENUM_PARAMS" kind="functionlike">
<macro-parameter name="param"/>
<purpose>
<simpara>Enumerate parameters for use with
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<para> When variadic templates are available and
<code><macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname></code>
is not defined, expands to variadic template list in the following manner:
<code><programlisting>
BOOST_VARIANT_ENUM_PARAMS(T) => T0, TN...
BOOST_VARIANT_ENUM_PARAMS(class T) => class T0, class... TN
BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN
BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN
BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
</programlisting></code>
</para>
<para>
Otherwise expands to a comma-separated sequence of length
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname></code>, where
each element in the sequence consists of the concatenation of
<emphasis>param</emphasis> with its zero-based index into the
sequence. That is,
<code>param ## 0, param ## 1, ..., param ## BOOST_VARIANT_LIMIT_TYPES - 1</code>.</para>
<para><emphasis role="bold">Rationale</emphasis>: This macro greatly
simplifies for the user the process of declaring
<code><classname>variant</classname></code> types
in function templates or explicit partial specializations of class
templates, as shown in the
<link linkend="variant.tutorial.preprocessor">tutorial</link>.</para>
</description>
</macro>
<macro name="BOOST_VARIANT_ENUM_SHIFTED_PARAMS" kind="functionlike">
<macro-parameter name="param"/>
<purpose>
<simpara>Enumerate all but the first parameter for use with
<code><classname>variant</classname></code>.</simpara>
</purpose>
<description>
<para> When variadic templates are available and
<code><macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname></code>
is not defined, expands to variadic template list in the following manner:
<code><programlisting>
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) => TN...
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class T) => class... TN
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
</programlisting></code>
</para>
<para>
Otherwise expands to a comma-separated sequence of length
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname> - 1</code>,
where each element in the sequence consists of the concatenation of
<emphasis>param</emphasis> with its one-based index into the sequence.
That is,
<code>param ## 1, ..., param ## BOOST_VARIANT_LIMIT_TYPES - 1</code>.</para>
<para><emphasis role="bold">Note</emphasis>: This macro results in the
same expansion as
<code><macroname>BOOST_VARIANT_ENUM_PARAMS</macroname></code> -- but
without the first term.</para>
</description>
</macro>
<macro name="BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT">
<purpose>
<simpara>Indicates absence of support for specifying the bounded types
of a <code><classname>variant</classname></code> by the elements of a
type sequence.</simpara>
</purpose>
<description>
<para>Defined only if
<code><classname>make_variant_over</classname></code> and
<code><classname>make_recursive_variant_over</classname></code>
are not supported for some reason on the target compiler.</para>
</description>
</macro>
<macro name="BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH">
<purpose>
<simpara>Define this macro if you do not wish to have a <code><classname>std::hash</classname></code> specialization for
<code><classname>boost::variant</classname></code>.</simpara>
</purpose>
</macro>
<macro name="BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT">
<purpose>
<simpara>Indicates
<code><classname>make_recursive_variant</classname></code> operates in
an implementation-defined manner.</simpara>
</purpose>
<description>
<para>Defined only if
<code><classname>make_recursive_variant</classname></code> does not
operate as documented on the target compiler, but rather in an
implementation-defined manner.</para>
<para><emphasis role="bold">Implementation Note</emphasis>: If
<code>BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT</code> is
defined for the target compiler, the current implementation uses the
<libraryname>MPL</libraryname> lambda mechanism to approximate the
desired behavior. (In most cases, however, such compilers do not have
full lambda support either.)</para>
</description>
</macro>
</header>

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<header name="boost/variant/visitor_ptr.hpp">
<namespace name="boost">
<class name="visitor_ptr_t">
<template>
<template-type-parameter name="T"/>
<template-type-parameter name="R"/>
</template>
<purpose>Adapts a function pointer for use as a static visitor.</purpose>
<description>
<simpara>Adapts the function given at construction for use as a
<link linkend="variant.concepts.static-visitor">static visitor</link>
of type <code>T</code> with result type <code>R</code>.</simpara>
</description>
<inherit access="public"><classname>static_visitor</classname>&lt;R&gt;</inherit>
<constructor specifiers="explicit">
<parameter>
<paramtype>R (*)(T)</paramtype>
</parameter>
<effects>
<simpara>Constructs the visitor with the given function.</simpara>
</effects>
</constructor>
<method-group name="static visitor interfaces">
<overloaded-method name="operator()">
<signature>
<type>R</type>
<parameter name="operand">
<paramtype><emphasis>unspecified-forwarding-type</emphasis></paramtype>
</parameter>
</signature>
<signature>
<template>
<template-type-parameter name="U"/>
</template>
<type>void</type>
<parameter>
<paramtype>const U&amp;</paramtype>
</parameter>
</signature>
<effects>
<simpara>If passed a value or reference of type
<code>T</code>, it invokes the function given at
construction, appropriately forwarding
<code>operand</code>.</simpara>
</effects>
<returns>Returns the result of the function invocation.</returns>
<throws id="visitor_ptr_t.visit.throws">
<simpara>The overload taking a value or reference of type
<code>T</code> throws if the invoked function throws.
The overload taking all other values <emphasis>always</emphasis>
throws <code><classname>bad_visit</classname></code>.</simpara>
</throws>
</overloaded-method>
</method-group>
</class>
<function name="visitor_ptr">
<purpose>
<simpara>Returns a visitor object that adapts function pointers for
use as a static visitor.</simpara>
</purpose>
<description>
<simpara>Constructs and returns a
<code><classname>visitor_ptr_t</classname></code> adaptor over the
given function.</simpara>
</description>
<template>
<template-type-parameter name="R"/>
<template-type-parameter name="T"/>
</template>
<type><classname>visitor_ptr_t</classname>&lt;T,R&gt;</type>
<parameter>
<paramtype>R (*)(T)</paramtype>
</parameter>
<returns>
<simpara>Returns a <code><classname>visitor_ptr_t</classname></code>
visitor object that, when applied, invokes the given
function.</simpara>
</returns>
<throws>
<simpara>Will not throw. (Note, however, that the returned
<classname alt="boost::visitor_ptr_t">visitor object</classname> may
throw when applied.)</simpara>
</throws>
</function>
</namespace>
</header>

View File

@@ -0,0 +1,419 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Copyright 2013-2022 Antony Polukhin.
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)
-->
<section id="variant.tutorial.advanced">
<title>Advanced Topics</title>
<using-namespace name="boost"/>
<using-class name="boost::variant"/>
<para>This section discusses several features of the library often required
for advanced uses of <code>variant</code>. Unlike in the above section, each
feature presented below is largely independent of the others. Accordingly,
this section is not necessarily intended to be read linearly or in its
entirety.</para>
<section id="variant.tutorial.preprocessor">
<title>Preprocessor macros</title>
<para>While the <code>variant</code> class template's variadic parameter
list greatly simplifies use for specific instantiations of the template,
it significantly complicates use for generic instantiations. For instance,
while it is immediately clear how one might write a function accepting a
specific <code>variant</code> instantiation, say
<code>variant&lt;int, std::string&gt;</code>, it is less clear how one
might write a function accepting any given <code>variant</code>.</para>
<para>Due to the lack of support for true variadic template parameter lists
in the C++98 standard, the preprocessor is needed. While the
<libraryname>Preprocessor</libraryname> library provides a general and
powerful solution, the need to repeat
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname></code>
unnecessarily clutters otherwise simple code. Therefore, for common
use-cases, this library provides its own macro
<code><emphasis role="bold"><macroname>BOOST_VARIANT_ENUM_PARAMS</macroname></emphasis></code>.</para>
<para>This macro simplifies for the user the process of declaring
<code>variant</code> types in function templates or explicit partial
specializations of class templates, as shown in the following:
<programlisting>// general cases
template &lt;typename T&gt; void some_func(const T &amp;);
template &lt;typename T&gt; class some_class;
// function template overload
template &lt;<macroname>BOOST_VARIANT_ENUM_PARAMS</macroname>(typename T)&gt;
void some_func(const <classname>boost::variant</classname>&lt;<macroname>BOOST_VARIANT_ENUM_PARAMS</macroname>(T)&gt; &amp;);
// explicit partial specialization
template &lt;<macroname>BOOST_VARIANT_ENUM_PARAMS</macroname>(typename T)&gt;
class some_class&lt; <classname>boost::variant</classname>&lt;<macroname>BOOST_VARIANT_ENUM_PARAMS</macroname>(T)&gt; &gt;;</programlisting>
</para>
</section>
<section id="variant.tutorial.over-sequence">
<title>Using a type sequence to specify bounded types</title>
<para>While convenient for typical uses, the <code>variant</code> class
template's variadic template parameter list is limiting in two significant
dimensions. First, due to the lack of support for true variadic template
parameter lists in C++, the number of parameters must be limited to some
implementation-defined maximum (namely,
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname></code>).
Second, the nature of parameter lists in general makes compile-time
manipulation of the lists excessively difficult.</para>
<para>To solve these problems,
<code>make_variant_over&lt; <emphasis>Sequence</emphasis> &gt;</code>
exposes a <code>variant</code> whose bounded types are the elements of
<code>Sequence</code> (where <code>Sequence</code> is any type fulfilling
the requirements of <libraryname>MPL</libraryname>'s
<emphasis>Sequence</emphasis> concept). For instance,
<programlisting>typedef <classname>mpl::vector</classname>&lt; std::string &gt; types_initial;
typedef <classname>mpl::push_front</classname>&lt; types_initial, int &gt;::type types;
<classname>boost::make_variant_over</classname>&lt; types &gt;::type v1;</programlisting>
behaves equivalently to
<programlisting><classname>boost::variant</classname>&lt; int, std::string &gt; v2;</programlisting>
</para>
<para><emphasis role="bold">Portability</emphasis>: Unfortunately, due to
standard conformance issues in several compilers,
<code>make_variant_over</code> is not universally available. On these
compilers the library indicates its lack of support for the syntax via the
definition of the preprocessor symbol
<code><macroname>BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT</macroname></code>.</para>
</section>
<section id="variant.tutorial.recursive">
<title>Recursive <code>variant</code> types</title>
<para>Recursive types facilitate the construction of complex semantics from
simple syntax. For instance, nearly every programmer is familiar with the
canonical definition of a linked list implementation, whose simple
definition allows sequences of unlimited length:
<programlisting>template &lt;typename T&gt;
struct list_node
{
T data;
list_node * next;
};</programlisting>
</para>
<para>The nature of <code>variant</code> as a generic class template
unfortunately precludes the straightforward construction of recursive
<code>variant</code> types. Consider the following attempt to construct
a structure for simple mathematical expressions:
<programlisting>struct add;
struct sub;
template &lt;typename OpTag&gt; struct binary_op;
typedef <classname>boost::variant</classname>&lt;
int
, binary_op&lt;add&gt;
, binary_op&lt;sub&gt;
> expression;
template &lt;typename OpTag&gt;
struct binary_op
{
expression left; // <emphasis>variant instantiated here...</emphasis>
expression right;
binary_op( const expression &amp; lhs, const expression &amp; rhs )
: left(lhs), right(rhs)
{
}
}; // <emphasis>...but binary_op not complete until here!</emphasis></programlisting>
</para>
<para>While well-intentioned, the above approach will not compile because
<code>binary_op</code> is still incomplete when the <code>variant</code>
type <code>expression</code> is instantiated. Further, the approach suffers
from a more significant logical flaw: even if C++ syntax were different
such that the above example could be made to &quot;work,&quot;
<code>expression</code> would need to be of infinite size, which is
clearly impossible.</para>
<para>To overcome these difficulties, <code>variant</code> includes special
support for the
<code><classname>boost::recursive_wrapper</classname></code> class
template, which breaks the circular dependency at the heart of these
problems. Further,
<code><classname>boost::make_recursive_variant</classname></code> provides
a more convenient syntax for declaring recursive <code>variant</code>
types. Tutorials for use of these facilities is described in
<xref linkend="variant.tutorial.recursive.recursive-wrapper"/> and
<xref linkend="variant.tutorial.recursive.recursive-variant"/>.</para>
<section id="variant.tutorial.recursive.recursive-wrapper">
<title>Recursive types with <code>recursive_wrapper</code></title>
<para>The following example demonstrates how <code>recursive_wrapper</code>
could be used to solve the problem presented in
<xref linkend="variant.tutorial.recursive"/>:
<programlisting>typedef <classname>boost::variant</classname>&lt;
int
, <classname>boost::recursive_wrapper</classname>&lt; binary_op&lt;add&gt; &gt;
, <classname>boost::recursive_wrapper</classname>&lt; binary_op&lt;sub&gt; &gt;
&gt; expression;</programlisting>
</para>
<para>Because <code>variant</code> provides special support for
<code>recursive_wrapper</code>, clients may treat the resultant
<code>variant</code> as though the wrapper were not present. This is seen
in the implementation of the following visitor, which calculates the value
of an <code>expression</code> without any reference to
<code>recursive_wrapper</code>:
<programlisting>class calculator : public <classname>boost::static_visitor&lt;int&gt;</classname>
{
public:
int operator()(int value) const
{
return value;
}
int operator()(const binary_op&lt;add&gt; &amp; binary) const
{
return <functionname>boost::apply_visitor</functionname>( calculator(), binary.left )
+ <functionname>boost::apply_visitor</functionname>( calculator(), binary.right );
}
int operator()(const binary_op&lt;sub&gt; &amp; binary) const
{
return <functionname>boost::apply_visitor</functionname>( calculator(), binary.left )
- <functionname>boost::apply_visitor</functionname>( calculator(), binary.right );
}
};</programlisting>
</para>
<para>Finally, we can demonstrate <code>expression</code> in action:
<programlisting>void f()
{
// result = ((7-3)+8) = 12
expression result(
binary_op&lt;add&gt;(
binary_op&lt;sub&gt;(7,3)
, 8
)
);
assert( <functionname>boost::apply_visitor</functionname>(calculator(),result) == 12 );
}</programlisting>
</para>
<para><emphasis role="bold">Performance</emphasis>: <classname>boost::recursive_wrapper</classname>
has no empty state, which makes its move constructor not very optimal. Consider using <code>std::unique_ptr</code>
or some other safe pointer for better performance on C++11 compatible compilers.</para>
</section>
<section id="variant.tutorial.recursive.recursive-variant">
<title>Recursive types with <code>make_recursive_variant</code></title>
<para>For some applications of recursive <code>variant</code> types, a user
may be able to sacrifice the full flexibility of using
<code>recursive_wrapper</code> with <code>variant</code> for the following
convenient syntax:
<programlisting>typedef <classname>boost::make_recursive_variant</classname>&lt;
int
, std::vector&lt; boost::recursive_variant_ &gt;
&gt;::type int_tree_t;</programlisting>
</para>
<para>Use of the resultant <code>variant</code> type is as expected:
<programlisting>std::vector&lt; int_tree_t &gt; subresult;
subresult.push_back(3);
subresult.push_back(5);
std::vector&lt; int_tree_t &gt; result;
result.push_back(1);
result.push_back(subresult);
result.push_back(7);
int_tree_t var(result);</programlisting>
</para>
<para>To be clear, one might represent the resultant content of
<code>var</code> as <code>( 1 ( 3 5 ) 7 )</code>.</para>
<para>Finally, note that a type sequence can be used to specify the bounded
types of a recursive <code>variant</code> via the use of
<code><classname>boost::make_recursive_variant_over</classname></code>,
whose semantics are the same as <code>make_variant_over</code> (which is
described in <xref linkend="variant.tutorial.over-sequence"/>).</para>
<para><emphasis role="bold">Portability</emphasis>: Unfortunately, due to
standard conformance issues in several compilers,
<code>make_recursive_variant</code> is not universally supported. On these
compilers the library indicates its lack of support via the definition
of the preprocessor symbol
<code><macroname>BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT</macroname></code>.
Thus, unless working with highly-conformant compilers, maximum portability
will be achieved by instead using <code>recursive_wrapper</code>, as
described in
<xref linkend="variant.tutorial.recursive.recursive-wrapper"/>.</para>
</section>
</section> <!--/tutorial.recursive-->
<section id="variant.tutorial.binary-visitation">
<title>Binary visitation</title>
<para>As the tutorial above demonstrates, visitation is a powerful mechanism
for manipulating <code>variant</code> content. Binary visitation further
extends the power and flexibility of visitation by allowing simultaneous
visitation of the content of two different <code>variant</code>
objects.</para>
<para>Notably this feature requires that binary visitors are incompatible
with the visitor objects discussed in the tutorial above, as they must
operate on two arguments. The following demonstrates the implementation of
a binary visitor:
<programlisting>class are_strict_equals
: public <classname>boost::static_visitor</classname>&lt;bool&gt;
{
public:
template &lt;typename T, typename U&gt;
bool operator()( const T &amp;, const U &amp; ) const
{
return false; // cannot compare different types
}
template &lt;typename T&gt;
bool operator()( const T &amp; lhs, const T &amp; rhs ) const
{
return lhs == rhs;
}
};</programlisting>
</para>
<para>As expected, the visitor is applied to two <code>variant</code>
arguments by means of <code>apply_visitor</code>:
<programlisting><classname>boost::variant</classname>&lt; int, std::string &gt; v1( "hello" );
<classname>boost::variant</classname>&lt; double, std::string &gt; v2( "hello" );
assert( <functionname>boost::apply_visitor</functionname>(are_strict_equals(), v1, v2) );
<classname>boost::variant</classname>&lt; int, const char * &gt; v3( "hello" );
assert( !<functionname>boost::apply_visitor</functionname>(are_strict_equals(), v1, v3) );</programlisting>
</para>
<para>Finally, we must note that the function object returned from the
&quot;delayed&quot; form of
<code><functionname>apply_visitor</functionname></code> also supports
binary visitation, as the following demonstrates:
<programlisting>typedef <classname>boost::variant</classname>&lt;double, std::string&gt; my_variant;
std::vector&lt; my_variant &gt; seq1;
seq1.push_back("pi is close to ");
seq1.push_back(3.14);
std::list&lt; my_variant &gt; seq2;
seq2.push_back("pi is close to ");
seq2.push_back(3.14);
are_strict_equals visitor;
assert( std::equal(
seq1.begin(), seq1.end(), seq2.begin()
, <functionname>boost::apply_visitor</functionname>( visitor )
) );</programlisting>
</para>
</section>
<section id="variant.tutorial.multi-visitation">
<title>Multi visitation</title>
<para>Multi visitation extends the power and flexibility of visitation by allowing simultaneous
visitation of the content of three and more different <code>variant</code>
objects. Note that header for multi visitors shall be included separately.</para>
<para>Notably this feature requires that multi visitors are incompatible
with the visitor objects discussed in the tutorial above, as they must
operate on same amout of arguments that was passed to <code>apply_visitor</code>.
The following demonstrates the implementation of a multi visitor for three parameters:
<programlisting>
#include &lt;boost/variant/multivisitors.hpp&gt;
typedef <classname>boost::variant</classname>&lt;int, double, bool&gt; bool_like_t;
typedef <classname>boost::variant</classname>&lt;int, double&gt; arithmetics_t;
struct if_visitor: public <classname>boost::static_visitor</classname>&lt;arithmetics_t&gt; {
template &lt;class T1, class T2&gt;
arithmetics_t operator()(bool b, T1 v1, T2 v2) const {
if (b) {
return v1;
} else {
return v2;
}
}
};
</programlisting>
</para>
<para>As expected, the visitor is applied to three <code>variant</code>
arguments by means of <code>apply_visitor</code>:
<programlisting>
bool_like_t v0(true), v1(1), v2(2.0);
assert(
<functionname>boost::apply_visitor</functionname>(if_visitor(), v0, v1, v2)
==
arithmetics_t(1)
);
</programlisting>
</para>
<para>Finally, we must note that multi visitation does not support
&quot;delayed&quot; form of
<code><functionname>apply_visitor</functionname> if
<macroname>BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES</macroname> is defined</code>.
</para>
</section>
</section>

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section id="variant.tutorial.basic">
<title>Basic Usage</title>
<using-namespace name="boost"/>
<using-class name="boost::variant"/>
<para>A discriminated union container on some set of types is defined by
instantiating the <code><classname>boost::variant</classname></code> class
template with the desired types. These types are called
<emphasis role="bold">bounded types</emphasis> and are subject to the
requirements of the
<link linkend="variant.concepts.bounded-type"><emphasis>BoundedType</emphasis></link>
concept. Any number of bounded types may be specified, up to some
implementation-defined limit (see
<code><macroname>BOOST_VARIANT_LIMIT_TYPES</macroname></code>).</para>
<para>For example, the following declares a discriminated union container on
<code>int</code> and <code>std::string</code>:
<programlisting><classname>boost::variant</classname>&lt; int, std::string &gt; v;</programlisting>
</para>
<para>By default, a <code>variant</code> default-constructs its first
bounded type, so <code>v</code> initially contains <code>int(0)</code>. If
this is not desired, or if the first bounded type is not
default-constructible, a <code>variant</code> can be constructed
directly from any value convertible to one of its bounded types. Similarly,
a <code>variant</code> can be assigned any value convertible to one of its
bounded types, as demonstrated in the following:
<programlisting>v = "hello";</programlisting>
</para>
<para>Now <code>v</code> contains a <code>std::string</code> equal to
<code>"hello"</code>. We can demonstrate this by
<emphasis role="bold">streaming</emphasis>&nbsp;<code>v</code> to standard
output:
<programlisting>std::cout &lt;&lt; v &lt;&lt; std::endl;</programlisting>
</para>
<para>Usually though, we would like to do more with the content of a
<code>variant</code> than streaming. Thus, we need some way to access the
contained value. There are two ways to accomplish this:
<code><functionname>apply_visitor</functionname></code>, which is safest
and very powerful, and
<code><functionname>get</functionname>&lt;T&gt;</code>, which is
sometimes more convenient to use.</para>
<para>For instance, suppose we wanted to concatenate to the string contained
in <code>v</code>. With <emphasis role="bold">value retrieval</emphasis>
by <code><functionname>get</functionname></code>, this may be accomplished
quite simply, as seen in the following:
<programlisting>std::string&amp; str = <functionname>boost::get</functionname>&lt;std::string&gt;(v);
str += " world! ";</programlisting>
</para>
<para>As desired, the <code>std::string</code> contained by <code>v</code> now
is equal to <code>"hello world! "</code>. Again, we can demonstrate this by
streaming <code>v</code> to standard output:
<programlisting>std::cout &lt;&lt; v &lt;&lt; std::endl;</programlisting>
</para>
<para>While use of <code>get</code> is perfectly acceptable in this trivial
example, <code>get</code> generally suffers from several significant
shortcomings. For instance, if we were to write a function accepting a
<code>variant&lt;int, std::string&gt;</code>, we would not know whether
the passed <code>variant</code> contained an <code>int</code> or a
<code>std::string</code>. If we insisted upon continued use of
<code>get</code>, we would need to query the <code>variant</code> for its
contained type. The following function, which &quot;doubles&quot; the
content of the given <code>variant</code>, demonstrates this approach:
<programlisting>void times_two( boost::variant&lt; int, std::string &gt; &amp; operand )
{
if ( int* pi = <functionname>boost::get</functionname>&lt;int&gt;( &amp;operand ) )
*pi *= 2;
else if ( std::string* pstr = <functionname>boost::get</functionname>&lt;std::string&gt;( &amp;operand ) )
*pstr += *pstr;
}</programlisting>
</para>
<para>However, such code is quite brittle, and without careful attention will
likely lead to the introduction of subtle logical errors detectable only at
runtime. For instance, consider if we wished to extend
<code>times_two</code> to operate on a <code>variant</code> with additional
bounded types. Specifically, let's add
<code>std::complex&lt;double&gt;</code> to the set. Clearly, we would need
to at least change the function declaration:
<programlisting>void times_two( boost::variant&lt; int, std::string, std::complex&lt;double&gt; &gt; &amp; operand )
{
// as above...?
}</programlisting>
</para>
<para>Of course, additional changes are required, for currently if the passed
<code>variant</code> in fact contained a <code>std::complex</code> value,
<code>times_two</code> would silently return -- without any of the desired
side-effects and without any error. In this case, the fix is obvious. But in
more complicated programs, it could take considerable time to identify and
locate the error in the first place.</para>
<para>Thus, real-world use of <code>variant</code> typically demands an access
mechanism more robust than <code>get</code>. For this reason,
<code>variant</code> supports compile-time checked
<emphasis role="bold">visitation</emphasis> via
<code><functionname>apply_visitor</functionname></code>. Visitation requires
that the programmer explicitly handle (or ignore) each bounded type. Failure
to do so results in a compile-time error.</para>
<para>Visitation of a <code>variant</code> requires a visitor object. The
following demonstrates one such implementation of a visitor implementating
behavior identical to <code>times_two</code>:
<programlisting>class times_two_visitor
: public <classname>boost::static_visitor</classname>&lt;&gt;
{
public:
void operator()(int &amp; i) const
{
i *= 2;
}
void operator()(std::string &amp; str) const
{
str += str;
}
};</programlisting>
</para>
<para>With the implementation of the above visitor, we can then apply it to
<code>v</code>, as seen in the following:
<programlisting><functionname>boost::apply_visitor</functionname>( times_two_visitor(), v );</programlisting>
</para>
<para>As expected, the content of <code>v</code> is now a
<code>std::string</code> equal to <code>"hello world! hello world! "</code>.
(We'll skip the verification this time.)</para>
<para>In addition to enhanced robustness, visitation provides another
important advantage over <code>get</code>: the ability to write generic
visitors. For instance, the following visitor will &quot;double&quot; the
content of <emphasis>any</emphasis>&nbsp;<code>variant</code> (provided its
bounded types each support operator+=):
<programlisting>class times_two_generic
: public <classname>boost::static_visitor</classname>&lt;&gt;
{
public:
template &lt;typename T&gt;
void operator()( T &amp; operand ) const
{
operand += operand;
}
};</programlisting>
</para>
<para>Again, <code>apply_visitor</code> sets the wheels in motion:
<programlisting><functionname>boost::apply_visitor</functionname>( times_two_generic(), v );</programlisting>
</para>
<para>While the initial setup costs of visitation may exceed that required for
<code>get</code>, the benefits quickly become significant. Before concluding
this section, we should explore one last benefit of visitation with
<code>apply_visitor</code>:
<emphasis role="bold">delayed visitation</emphasis>. Namely, a special form
of <code>apply_visitor</code> is available that does not immediately apply
the given visitor to any <code>variant</code> but rather returns a function
object that operates on any <code>variant</code> given to it. This behavior
is particularly useful when operating on sequences of <code>variant</code>
type, as the following demonstrates:
<programlisting>std::vector&lt; <classname>boost::variant</classname>&lt;int, std::string&gt; &gt; vec;
vec.push_back( 21 );
vec.push_back( "hello " );
times_two_generic visitor;
std::for_each(
vec.begin(), vec.end()
, <functionname>boost::apply_visitor</functionname>(visitor)
);</programlisting>
</para>
</section>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<section xmlns:xi="http://www.w3.org/2001/XInclude" id="variant.tutorial">
<title>Tutorial</title>
<xi:include href="basic.xml"/>
<xi:include href="advanced.xml"/>
</section>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 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)
-->
<library name="Variant" dirname="variant"
xmlns:xi="http://www.w3.org/2001/XInclude" id="variant">
<libraryinfo>
<author>
<firstname>Eric</firstname>
<surname>Friedman</surname>
</author>
<author>
<firstname>Itay</firstname>
<surname>Maman</surname>
</author>
<copyright>
<year>2002</year>
<year>2003</year>
<holder>Eric Friedman</holder>
<holder>Itay Maman</holder>
</copyright>
<copyright>
<year>2014-2022</year>
<holder>Antony Polukhin</holder>
</copyright>
<legalnotice>
<para>Distributed under the Boost Software License, Version 1.0.
(See accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink
url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>)
</para>
</legalnotice>
<librarypurpose>Safe, generic, stack-based discriminated union container</librarypurpose>
<librarycategory name="category:containers"/>
<librarycategory name="category:data-structures"/>
</libraryinfo>
<title>Boost.Variant</title>
<xi:include href="introduction.xml"/>
<xi:include href="tutorial/tutorial.xml"/>
<xi:include href="reference/reference.xml"/>
<xi:include href="design.xml"/>
<!--
<xi:include href="rationale.xml"/>
-->
<xi:include href="misc.xml"/>
<!--
<xi:include href="tests.xml"/>
-->
<xi:include href="biblio.xml"/>
</library>