2
0
mirror of https://github.com/boostorg/variant.git synced 2026-01-19 04:42:16 +00:00

Migrated from Sandbox CVS.

[SVN r18578]
This commit is contained in:
Eric Friedman
2003-05-28 08:05:16 +00:00
commit bb596cae89
41 changed files with 5840 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

81
doc/credits.html Normal file
View File

@@ -0,0 +1,81 @@
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../../index.htm">
<img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">Credits</h2>
</td>
</tr>
</table>
<hr>
<p></p>
<ul>
<li><a href="#Acknowledgments">Acknowledgments</a></li>
<li><a href="#Bibliography">Bibliography</a></li>
</ul>
<hr>
<h2><a name="Acknowledgments">Acknowledgments</a></h2>
<p>Eric Friedman and Itay Maman designed and implemented the initial submission.</p>
<p>Andrei Alexandrescu's work in [<a href="#bib-ale01A">Ale01A</a>] and [<a href="#bib-ale02">Ale02</a>] inspired the
library's design.</p>
<p>Anthony Williams suggested the method [<a href="#bib-wil02">Wil02</a>] by
which <code>variant</code> generally guarantees strong exception-safety.</p>
<p>Douglas Gregor, Dave Abrahams, Fernando Cacciola, Brad King, Giovanni Bajo,
and others provided helpful feedback and suggestions to refine the semantics,
interface, and implementation of the library.</p>
<hr>
<h2><a name="Bibliography">Bibliography</a></h2>
<p>[<a name="bib-ale01A">Ale01A</a>] Andrei Alexandrescu. &quot;<a href="http://www.oonumerics.org/tmpw01/alexandrescu.pdf">An Implementation of Discriminated Unions in C++</a>.&quot; <i>OOPSLA 2001</i>, Second Workshop on C++ Template Programming. Tampa Bay, 14 October 2001.</p>
<p>[<a name="bib-ale01B">Ale01B</a>] Andrei Alexandrescu. <i>
<a href="http://www.moderncppdesign.com/book/main.html">Modern C++ Design</a></i>.
Addison-Wesley, C++ In-Depth series. 2001.</p>
<p>[<a name="bib-ale02">Ale02</a>] Andrei Alexandrescu. &quot;Generic&lt;Programming&gt;:
Discriminated Unions&quot; <a href="http://cuj.com/experts/2004/alexandr.htm">Part 1</a>,
<a HREF="http://cuj.com/experts/2006/alexandr.htm">Part 2</a>,
<a HREF="http://cuj.com/experts/2008/alexandr.htm">Part 3</a>. <i>C/C++ Users
Journal</i>. 2002.</p>
<p>[<a name="bib-boo02">Boo02</a>] Various Boost members. &quot;<a href="http://lists.boost.org/MailArchives/boost/msg30415.php">Proposal
--- A type-safe union</a>.&quot; Boost public discussion. 2002.</p>
<p>[<a name="bib-fri02">Fri02</a>] Eric Friedman. &quot;<a href="http://groups.yahoo.com/group/boost/files/variant-20020701.zip">Variant
(aka Discriminated Union)</a>.&quot; Early implementation. 2002.</p>
<p>[<a name="bib-gre02">Gre02</a>] Doug Gregor. &quot;<a HREF="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?variant">BOOST_USER:
variant</a>.&quot; Boost Wiki paper. 2002.</p>
<p><a name="bib-hen01">[Hen01]</a> Kevlin Henney.
<a href="http://www.boost.org/libs/any/index.html">The Boost Any Library</a>.
2001. </p>
<p>[<a name="bib-sut00">Sut00</a>] Herb Sutter. <i>
<a href="http://www.gotw.ca/publications/xc++.htm">Exceptional C++: 47
Engineering Puzzles, Programming Problems, and Solutions</a></i>.
Addison-Wesley, C++ In-Depth series. 2000.</p>
<p>[<a name="bib-wil02">Wil02</a>] Anthony Williams.
<a href="http://aspn.activestate.com/ASPN/Mail/Message/boost/1314807">
Double-Storage Proposal</a>. 2002. </p>
<hr>
<p>Revised 13 February 2003</p>
<p><i>© Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

117
doc/index.html Normal file
View File

@@ -0,0 +1,117 @@
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../index.htm"> <img src="../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a>
</h3>
</td>
<td valign="top">
<h1 align="center">boost::variant</h1>
<h2 align="center">Index</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<ul>
<li>
<a href="overview.html">Overview</a><ul>
<li>
<a href="overview.html#Introduction">Introduction</a></li>
<li>
<a href="overview.html#Motivation">Motivation</a></li>
</ul>
</li>
<li>
<a href="tutorial.html">Tutorial</a>
<ul>
<li>
<a href="tutorial.html#FirstVariantProgram">First variant program</a></li>
<li>
<a href="tutorial.html#Instantiation">Instantiation</a></li>
<li>
<a href="tutorial.html#ValueSemantics">Value semantics</a></li>
<li>
<a href="tutorial.html#FunctorBasedVisitation">Functor-based visitation</a></li>
</ul>
</li>
<li>
<a href="reference.html">Reference</a>
<ul>
<li>
Header &quot;boost/variant.hpp&quot;
<ul>
<li>
<a href="reference.html#Synopsis">Synopsis</a></li>
<li>
Concept: <a href="reference.html#BoundedType">BoundedType</a></li>
<li>
Concept: <a href="reference.html#Visitor">Visitor</a></li>
<li>
<a HREF="reference.html#BoostVariantLimitTypes">BOOST_VARIANT_LIMIT_TYPES</a></li>
<li>
<code><a href="reference.html#variant">variant</a></code></li>
</ul>
</li>
<li>
Header &quot;boost/apply_visitor.hpp&quot;: <a href="reference.html#Visitation"><code>apply_visitor</code></a></li>
<li>
Header &quot;boost/static_visitor.hpp&quot;: <a href="reference.html#StaticVisitor"><code>static_visitor</code></a></li>
<li>
Header &quot;boost/extract.hpp&quot;: <a href="reference.html#ValueExtraction"><code>extract</code></a></li>
<li>
Header &quot;boost/incomplete.hpp&quot;: <a href="reference.html#incomplete"><code>incomplete</code></a></li>
</ul>
</li>
<li>
<a href="sample.html">Sample programs</a><ul>
<li>
<a href="sample.html#quick">A quick example</a></li>
<li>
<a href="sample.html#tree">A binary tree implementation</a></li>
<li>
<a href="sample.html#poly">Polymorphism: Inheritance vs. Variants</a></li>
</ul>
</li>
<li>
<a href="misc.html">Miscellaneous</a>
<ul>
<li>
<a href="misc.html#HeaderFiles">Header files</a></li>
<li>
<a href="misc.html#Compatibility">Compatibility</a></li>
<li>
<a href="misc.html#Troubleshooting">Troubleshooting</a></li>
</ul>
</li>
<li>
<a href="credits.html">Credits</a><ul>
<li>
<a href="credits.html#Acknowledgments">Acknowledgments</a></li>
<li>
<a href="credits.html#Bibliography">Bibliography</a></li>
</ul>
</li>
</ul>
<hr>
<p>Revised 14 February 2003</p>
<p><i>© Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied
warranty.</p>
</body>
</html>

102
doc/misc.html Normal file
View File

@@ -0,0 +1,102 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3>
<A HREF="../../../index.htm">
<img src="../../../c++boost.gif" alt="C++ Boost"
width="277" height="86" BORDER=0> </A>
</h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</A></h1>
<h2 align="center">Miscellaneous</h2>
</td>
</tr>
</table>
<hr>
<UL>
<LI><a href="#HeaderFiles">Header files</a></LI>
<LI><a href="#Compatibility">Compatibility</a></LI>
<LI><a href="#Troubleshooting">Troubleshooting</a></lI>
</UL>
<hr>
<h2><a name="HeaderFiles">Header files</a></h2>
<ul>
<li><a href="../../../boost/variant.hpp">boost/variant.hpp</a> - Defines
<code><a href="reference.html#Synopsis">boost::variant</a></code>
<li><a href="../../../boost/incomplete.hpp">boost/incomplete.hpp</a>
- Defines template class <code><a href="reference.html#Incomplete">boost::incomplete</a></code>.
<li><a href="../../../boost/apply_visitor.hpp">boost/apply_visitor.hpp</a> -
Defines the overloaded template function <code>
<a href="reference.html#Visitation">boost::apply_visitor</a></code>
<li><a href="../../../boost/static_visitor.hpp">boost/static_visitor.hpp</a>
- Defines template class <code><a href="reference.html#StaticVisitor">
boost::static_visitor</a></code>.
<li><a href="../../../boost/extract.hpp">boost/extract.hpp</a>
- Defines template class<code>
<a href="reference.html#ValueExtraction">boost::extract</a></code>.</ul>
<hr>
<h2><a name="Compatibility">Compatibility</a></h2>
<p>To date the code and test harness have been compiled and tested successfully
using Microsoft Visual C++ 7.0 and GNU C++ 2.95/3.1.</p>
The GNU C++ implementation of <a href="reference.html#ValueExtraction">extract</a> offers an
implicit type conversion operator, which is not supported by the MSVC7 implementation.<br>
<br>
<hr>
<h2><a name="Troubleshooting">Troubleshooting</a></h2>
<ul>
<li><u>Compiler</u>: GNU C++. Error message:<br>
<table>
<tr>
<td width = "50"></td>
<td>
<code>
<br>
variant.hpp: template instantiation depth exceeds maximum of 17<br>
variant.hpp: (use -ftemplate-depth-NN to increase the maximum)
<br>
<br>
</code></td></tr></table>
<u>Solution</u>: Passing <code>-ftemplate-depth-50</code> to the compiler.
This will increase the maximum depth to 50.<br>
<br><br>
<li><u>Compiler</u>: MSVC7. Error message:<br>
<table>
<tr>
<td width = "50"></td>
<td>
<code>
<br>
boost\mpl\clear.hpp(36) : fatal error C1076: compiler limit : internal heap
limit reached;<br>
use /Zm to specify a higher limit
<br>
<br>
</code></td></tr></table>
<u>Solution</u>: Passing <code>/Zm200</code> to the compiler. This will increase
the heap by a factor of 200%.</ul>
<hr>
<p>Revised 10 February 2003</p>
<p><i>&copy; Copyright Eric Friedman and Itay Maman 2002-2003. All rights
reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation. Eric Friedman and Itay Maman make no
representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>

118
doc/overview.html Normal file
View File

@@ -0,0 +1,118 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="2" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3>
<A HREF="../../index.htm"><img src="../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</A>
</h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">
Overview</h2>
</td>
</tr>
</table>
<hr>
<p>
<UL>
<LI>
<a href="#Introduction">Introduction</a></LI>
<LI>
<a href="#Motivation">Motivation</a></LI>
</UL>
<hr>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>variant</code> template class offers a simple, type-safe solution for
manipulating an object from an inhomogeneous set of&nbsp; types in a uniform
manner. Whereas standard containers such as <code>std::vector</code> may be
thought of as "<b>multi-value, single type</b>," <code>variant</code> is "<b>multi-type,
single value</b>.&quot; This reduces code duplication and enhances
maintainability.</p>
<p>Specific features of <CODE>boost::variant</CODE> include:</p>
<UL>
<LI>
Full value semantics, including adherence to standard overload resolution
rules.</LI>
<LI>
Strong exception-safety guarantee for all operations.</LI>
<LI>
Compile-time type-safe value visitation.</LI>
<LI>
Run-time checked explicit value extraction.</LI>
<LI>
Support for incomplete types and recursive variant types.</LI>
<LI>
Efficient, stack-based implementation.</LI>
</UL>
<hr>
<h2><a name="Motivation">Motivation</a></h2>
<p>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,&nbsp;C++ features&nbsp;direct language support for such types through
its <code>union</code> keyword:
</p>
<blockquote>
<pre>union { int i; double d; } u;
u.d = 3.14;
u.i = 3; // overwrites u.d (OK: u.d is a POD type)</pre>
</blockquote>
<p>C++'s <code>union</code> construct, however,&nbsp;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 types, and
so does not accept types exhibiting non-trivial construction or destruction:</p>
<blockquote>
<pre>union {
int i;
std::string s; // illegal: std::string is not a POD type!
};</pre>
</blockquote>
<p>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 [<a href="credits.html#bib-hen01">Hen01</a>]&nbsp;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>).</p>
<p>However, solutions of this sort are highly error-prone, due to the following:</p>
<ul>
<li>
<i>Downcast errors cannot be detected at compile-time</i>. Thus, incorrect
usage of downcast constructs will lead to bugs detectable only at run-time.</li>
<li>
<i>Addition of new concrete types may be ignored</i>. 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.</li>
</ul>
<p>Furthermore, even when properly implemented, these solutions incur a relatively
significant&nbsp;abstraction penalty due to the use of the free store, virtual
function calls, and polymorphic downcasts.</p>
<p>The <code>variant</code> template class (inspired by Andrei Alexandrescu's class
of the same name described in [<a href="credits.html#bib-ale02">Ale02</a>]) is
an efficient, recursive-capable, bounded discriminated union value type capable
of containing both POD and non-POD value types. It supports direct
initialization 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, <code>variant</code>
supports both compile-time checked, type-safe <a href="reference.html#Visitation">visitation</a>
and explicit, run-time checked, type-safe <a href="reference.html#ValueExtraction">value
extraction</a>.</p>
<hr>
<p>Revised 13 February 2003</p>
<p><i>&copy; Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied
warranty.</p>

478
doc/reference.html Normal file
View File

@@ -0,0 +1,478 @@
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../../index.htm"> <img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a>
</h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">Reference</h2>
</td>
</tr>
</table>
<hr>
<p></p>
<ul>
<li>
Header &quot;boost/variant.hpp&quot;<ul>
<li>
<a href="#Synopsis">Synopsis</a></li>
<li>
<a href="#BoundedType">BoundedType</a> concept</li>
<li>
<a href="#Visitor">Visitor</a> concept</li>
<li>
<a HREF="#BoostVariantLimitTypes">BOOST_VARIANT_LIMIT_TYPES</a></li>
<li>
<code><a href="#variant">variant</a></code></li>
</ul>
</li>
<li>
Header &quot;boost/apply_visitor.hpp&quot;: <a href="#Visitation"><code>apply_visitor</code></a></li>
<li>
Header &quot;boost/static_visitor.hpp&quot;: <a href="#StaticVisitor"><code>static_visitor</code></a></li>
<li>
Header &quot;boost/extract.hpp&quot;: <a href="#ValueExtraction"><code>extract</code></a></li>
<li>
Header &quot;boost/incomplete.hpp&quot;: <a href="#incomplete"><code>incomplete</code></a></li>
</ul>
<hr>
<h2>Header <code>&quot;boost/variant.hpp&quot;</code></h2>
<h3><a name="Synopsis">Synopsis</a></h3>
<p>Dependencies and library features defined in <code><a href="../../../../../../../boost/variant.hpp">
&quot;</a></code><a href="../../../../../../../boost/variant.hpp"><code>boost/variant.hpp&quot;</code></a>:
</p>
<pre>#include &lt;typeinfo&gt;
#define <a href="#BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a> <i>implementation-defined</i>
namespace boost
{
template
&lt;
typename T1,
typename T2,
...
typename T<i>n</i> = <em>implementation-defined</em>
&gt;
class <a href="#variant">variant</a>;
template &lt;typename T1, typename T2, ... , typename T<i>n</i>&gt;
void swap(
variant&lt;T1, T2, ... , T<i>n</i>&gt; &amp;
, variant&lt;T1, T2, ... , T<i>n</i>&gt; &amp;
);
}
</pre>
<p>Test harnesses provided in <code>&quot;libs/variant/test&quot;</code> directory.</p>
<p></p>
<hr>
<h2><a name="BoundedType"><i>BoundedType</i>&nbsp;Concept</a></h2>
<p>Given <a href="#variant"><code>variant</code></a><code>&lt;T1, T2, ... , T<i>n</i>&gt;</code>,
each type <code>T<i>i</i></code> is a <b>bounded type</b> of the <code>variant</code>.</p>
<p>The requirements on bounded types are as follows:</p>
<ul>
<li>
<i>CopyConstructible</i> [20.1.3].</li>
<LI>
<I>Assignable</I>.</LI>
<li>
Destructor upholds the no-throw exception-safety guarantee.</li>
<li>
Not top-level <code>const</code>-qualified.</li>
<li>
Complete at the point of variant template instantiation. (See <code><a href="#incomplete">
incomplete&lt;T&gt;</a></code> wrapper for a solution to containing
incomplete types.)</li>
</ul>
<p>A <code>variant</code>'s first bounded type has the additional requirement that
it&nbsp;is <em>DefaultConstructible</em> [??].</p>
<hr>
<h2><a name="Visitor"><i>Visitor</i> Concept</a></h2>
<p>Given <a href="#variant"><code>variant</code></a><code>&lt;T1, T2, ... , T<i>n</i>&gt;</code>,
a function object which unambiguously accepts any value of
each of the variant's <A HREF=#BoundedType">bounded types</A>, is a
<B>Visitor</B> of of the <CODE>variant</CODE>.
<p>Additional requirements on visitors are as follows:</p>
<ul>
<li>
Must expose inner type <code>result_type</code>. <!-- (See
<code><a href="#visitor_ptr">visitor_ptr</a></code>
wrapper for a solution to functions as visitors.)--> </li>
<li>
Each operation of the function object must return a value
implicitly-convertible to <code>result_type</code>.</li>
</ul>
<h3><b>Examples:</b></h3>
<p>The following class is a visitor of a number of <code>variant</code> types
(e.g., explicitly: <code>variant&lt;int, std::string&gt;</code>, or implicitly: <code>
variant&lt;short, std::string&gt;</code>, etc.):</p>
<pre>class my_visitor
{
typedef int result_type;
int operator()(int i)
{
return i * 2;
}
int operator()(std::string&amp; s)
{
return s.length();
}
};</pre>
<p>Another example is the following class, which exposes a templated function
operator, allowing it to operate on values of many types. Thus, the following
class is a visitor of any <code>variant</code> whose bounded types each support
streaming output:</p>
<pre>class printer
{
typedef void result_type;
template &lt;typename T&gt;
void operator()(const T&amp; t)
{
std::cout &lt;&lt; t &lt;&lt; '\n';
}
};</pre>
<hr>
<h3><a name="BoostVariantLimitTypes">BOOST_VARIANT_LIMIT_TYPES</a></h3>
<pre>#define BOOST_VARIANT_LIMIT_TYPES <i>implementation-defined</i></pre>
<p><i>Implementation-defined</i>. Equal to the length of the template parameter
list for <code>variant</code>.</p>
<p><b>Note:</b> Conforming implementations of <code>variant</code> must allow at
least ten bounded types. That is, <code>BOOST_VARIANT_LIMIT_TYPES &gt;= 10</code>
must evaluate true.</p>
<hr>
<h2><a name="variant"><code>variant</code></a></h2>
<pre>template
&lt;
typename T1,
typename T2,
...
typename T<i>n</i> = <em>implementation-defined</em>
&gt;
class variant
{
public: // <i><a href="#variant-structors">structors</a></i>
<a href="#variant-default-ctor">variant</a>();
<a href="#variant-copy-ctor">variant</a>(const variant &amp;);
template &lt;typename OperandType&gt;
<a href="#variant-template-ctor">variant</a>(const OperandType &amp;);
<a href="#dtor">~variant</a>();
public: // <i><a href="#variant-modifiers">modifiers</a></i>
variant &amp; <a href="#variant-swap">swap</a>(variant &amp;);
variant &amp; <a href="#variant-copy-assign">operator=</a>(const variant &amp;);
template &lt;typename OperandType&gt;
variant &amp; <a href="#variant-template-assign">operator=</a>(const OperandType &amp;);
public: // <i><a href="#variant-queries">queries</a></i>
int <a href="#variant-which">which</a>() const;
const std::type_info &amp; <a href="#variant-type">type</a>() const;
bool <a href="#variant-empty">empty</a>() const; // always false (<a href="../../any/index.html#any">boost::any</a> compatibility)
private: // <i>representation</i>
...
};</pre>
<p>An instance of <code>variant</code> contains exactly one instance of one of its
bounded types, which are specified as arguments to <code>variant</code>'s
template parameter list. The length of <code>variant</code>'s template
parameter list is equal to the implementation defined value <a href="#BOOST_VARIANT_LIMIT_TYPES">
<code>BOOST_VARIANT_LIMIT_TYPES</code></a>.</p>
<p>Each type specified as a bounded type must satisfy the <a href="#BoundedType"><i>BoundedType</i></a>
requirements. Note that&nbsp; <code>variant</code> itself satisfies <a href="#BoundedType">
<i>BoundedType</i></a> requirements with default construction.
</p>
<p>All members of <code>variant</code> satisfy the strong guarantee of
exception-safety, unless otherwise specified.</p>
<blockquote>
<hr>
<h3><a name="variant-structors">Structors</a></h3>
<pre><a name="variant-default-ctor">variant</a>();</pre>
<p>Default constructor. Initializes <code>*this</code> with the default value of
the first bounded type (i.e, <code>T1</code>). May fail with any exceptions
arising from the default constructor of <code>T1</code>.<br>
</p>
<pre><a name="variant-copy-ctor">variant</a>(const variant&amp; other);
</pre>
<p>Copy constructor. Copies the content of <code>other</code> into <code>*this</code>.
May fail with any exceptions arising from the copy constructor of <code>other</code>'s
contained type.<br>
</p>
<pre>template &lt;typename OperandType&gt;
<a name="variant-template-ctor">variant</a>(const OperandType &amp; operand);
</pre>
<p>Templated constructor. Initializes <code>*this</code> according to the following
logic:</p>
<ol>
<li>
If <code>OperandType</code> is <b>not a <code>variant</code></b>:<ul>
<li>
If <code>OperandType</code> is one of the bounded types of the <code>variant</code>,
initialize <code>*this</code> with a copy of <code>operand</code>.</li>
<li>
Otherwise, use overload resolution rules to find the best conversion for <code>OperandType</code>,
and initialize <code>*this</code> with a copy of the converted <code>operand</code>.
(However, if the conversion is ambiguous, or if none exists, a compiler error
is generated.)</li>
</ul>
</li>
<li>
Otherwise (i.e: <code>OperandType</code> <b>is a <code>variant</code></b>):
<ul>
<li>
If <code>OperandType</code> does not appear on <code>*this</code>'s set of
types, then <code>*this</code> is initialized with <code>operand</code>'s held
value (as described in item 1, above).</li>
<li>
Otherwise, <code>operand</code> is assigned, as-is, into <code>*this</code>.
Hence, the held value of <code>*this</code> is, by itself, a variant.</li>
</ul>
</li>
</ol>
<p>May fail with any exceptions arising from the copy constructor of <code>OperandType</code>.<br>
</p>
<pre><a name="variant-dtor">~variant</a>();
</pre>
<p>Non-throwing destructor that releases all resources used in management of <code>*this</code>,
including the currently contained value.
</p>
<h3>Modifiers</h3>
<pre>void <a name="variant-swap">swap</a>(variant&amp; other);
</pre>
<p>Exchanges contents of <code>*this</code> and <code>other</code>. May fail with
any exceptions arising from the copy constructors of the contained types of <code>*this</code>
or <code>other</code>, or from the swap primitive of the held values, if <code>this-&gt;type()
== other.type()</code>.<br>
</p>
<pre>variant&amp; <a name="variant-copy-assign">operator=</a>(const variant&amp; rhs);
</pre>
<p>Copy assignment. Assigns <code>rhs</code>'s contained value into <code>*this</code>.
The old value contained by <code>*this</code> is properly destroyed.</p>
<p>Note: this operator follows the same logic as the <a href="#CopyConstructor">copy
constructor</a>.</p>
<pre>template&lt;class OperandType&gt;
variant&amp; operator=(const OperandType &amp;);
</pre>
<p>Templated assignment. Assigns <code>rhs</code> into <code>*this</code>. The old
value held by <code>*this</code> is properly destroyed.</p>
<p>Note: This operator follows the same logic as the <a href="#TemplatedConstructor">templated
constructor</a>.</p>
<h3>Queries</h3>
<pre>const std::type_info &amp; type() const;
</pre>
<p>Non-throwing query that returns the <code>typeid()</code> of the contained value</p>
<pre>bool empty() const;
</pre>
<p>Always returns <code>false</code>. This non-throwing member function is provided
for <a HREF="../../any/index.html">boost::any</a> compatibility.</p>
<p>Note: a <code>variant</code> object is never empty. (See the <a href="#variant-default-ctor">
default constructor</a>.)</p>
<pre>int which() const;
</pre>
<p>Non-throwing query that returns the zero-based index of the bounded type of the
contained value.<br>
</p>
</blockquote>
<hr>
<h2><a name="Visitation">Visitation: <code>apply_visitor</code></a></h2>
<pre>// Binary form
template&lt;typename VisitorType, typename VariantType&gt;
typename VisitorType::result_type apply_visitor(VisitorType&amp; visitor,
VariantType&amp; var_inst);
// Unary form
template&lt;class VisitorType&gt;
boost::apply_visitor_t&lt;VisitorType&gt; apply_visitor(VisitorType&amp; visitor);
template &lt;typename VisitorType&gt;
class apply_visitor_t
{
public:
typedef typename VisitorType::result_type result_type;
template &lt;typename VariantType&gt;
result_type operator()(VariantType&amp; var_inst);
...
};
</pre>
<p><code>boost::apply_visitor(visitor, var_inst)</code> passes the variant object, <code>
var_inst</code>, to the given visitor (<code>visitor</code>). This is
equivalent to calling <code>visitor</code>'s function-call operator, with <code>var_inst</code>'s
currently held value.<br>
<code>VisitorType</code> must be a <a href="#Visitor">visitor of</a> <code>VariantType</code>.
See <a HREF="tutorial.html#FunctorBasedVisitation">Functor-based visitation</a>
for an in-depth description of visitors.<br>
<br>
The unary form of <code>apply_visitor()</code> tranforms the given visitor into
a unary function object which accepts a variant object, thus, the following two
lines are equivalent:<br>
</p>
<pre> boost::apply_visitor(visitor, var_inst); // Binary form
boost::apply_visitor(visitor)(var_inst); // Unary form
</pre>
<p>Consequently, the unary <code>apply_visitor()</code> function, is highly useful
when <code>std::for_each</code> (or a similar STL algorithm) needs to be
applied on a sequence of <code>variant</code> objects, as illustrated in the <a href="sample.html#poly">
Polymorphism: Inheritance Vs. Variants</a> sample.<br>
</p>
<hr>
<h2><a name="StaticVisitor">Visitation: <code>static_visitor</code></a></h2>
<pre>template&lt;typename R = void&gt;
struct static_visitor
{
typedef R result_type;
};
</pre>
<p><code>static_visitor</code> defines the nested type <code>result_type</code>,
which is required from each <a href="#Visitor">visitor</a> class.
<br>
</p>
<hr>
<h2><a name="ValueExtraction">Value Extraction: <code>extract</code></a></h2>
<pre></pre>
<pre>class bad_extract : public std::exception
{
public:
virtual const char* what() const throw();
};
template &lt;typename ToType&gt;
struct extract
{
public: // typedefs
typedef ToType&amp; result_type;
public: // structors
template &lt;typename VariantType&gt;
extract(VariantType &amp;);
template &lt;typename VariantType&gt;
extract(const VariantType &amp;);
public: // queries
bool check() const;
ToType&amp; operator()() const;
operator ToType&amp;() const; // Not supported on MSVC
};
</pre>
<pre></pre>
<p><code>boost::extract</code> is a facility for extracting a reference to a value
held by a <code>variant</code> object. The 'extraction' succeeds only if the
type of the held value is identical to the <code>ToType</code> template
parameter. Usage:<br>
</p>
<ol>
<li>
<code>extract&lt;RR&gt;(var_inst)();</code> Initializes a temporary <code>extract</code>object
and converts it to <code>RR&amp;</code>. If the given <code>variant</code>
object, <code>var_inst</code> does not hold a value of type <code>RR</code>, a <code>
bad_extract</code> exception is thrown.
</li>
<li>
<code>extract&lt;RR&gt; ex(var_inst);</code> Initalizes an extract object, <code>ex</code>.
Subsequently, client code can issue an <code>ex.check()</code> call, to
determine whether <code>var_inst</code> is holding a value of type <code>RR</code>.
</li>
</ol>
<h3>Constructors</h3>
<pre> template&lt;VariantType&gt;
extract(const VariantType&amp; from);
template&lt;VariantType&gt;
extract(VariantType&amp; from);
</pre>
<p>Sets up an <code>extract</code> object which is associated with the given <code>variant</code>
object (<code>from</code>).<br>
</p>
<h3>Queries</h3>
<pre> bool check() const;
</pre>
<p><code>check()</code> is a non throwing member function which return <code>true</code>,
if, and only if, the associated <code>variant</code> object is holding a value
of type <code>ToType</code>.</p>
<pre> result_type operator()() const;
operator result_type() const; // Not supported on MSVC
</pre>
<p>If <code>check()</code> is <code>true</code> - <code>operator()</code> returns a
reference to the value held by the associated <code>variant</code> object.
Otherwise - a <code>bad_extract</code> exception is thrown.<br>
<code>operator result_type()</code> supplies an implicit conversion to <code>ToType&amp;</code>.
It is semantically identical to <code>operator()</code>. Note that the MSVC7 implementation does not support
this operator.<br>
</p>
<hr>
<h2><a name="incomplete"><code>incomplete</code></a></h2>
<p><code>incomplete&lt;T&gt;</code> is a template class, which allows a <code>variant</code>
type to be instantiated with incomplete types.<br>
By specifying <code>incomplete&lt;T&gt;</code> as one of the actual template
parameters, the instantiated variant will be able to handle values of type <code>T</code>,
although <code>T</code> is incomplete at the instantiation point.<br>
<code>incomplete&lt;&gt;</code> is typically used for solving circular
dependencies, but, more importantly, it also enables the creation of <b>recursive</b>,
variant-based, constructs.<br>
The snip below demonstrates the usage of <code>Incomplete&lt;&gt;</code>. A
complete sample program is available <a HREF="sample.html#tree">here</a>.
</p>
<pre> using boost::variant;
using boost::incomplete;
struct non_leaf_node; // Forward declaration
// Define a tree_node variant with these two types:
// (1) int, (2) non_leaf node
typedef variant
&lt;
int,
incomplete&lt;non_leaf_node&gt; // non_leaf_node is incomplete at
// this point so it must be wrapperd
// by incomplete&lt;&gt;
&gt; tree_node;
struct non_leaf_node
{
non_leaf_node(const non_leaf_node&amp; other)
: left_(other.left_), right_(other.right_), num_(other.num_)
{ }
int num_;
tree_node left_;
tree_node right_;
};
</pre>
<hr>
<p>Revised 14 February 2003</p>
<p><i>© Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied
warranty.</p>
</body>
</html>

335
doc/sample.html Normal file
View File

@@ -0,0 +1,335 @@
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../../index.htm">
<img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">Sample programs</h2>
</td>
</tr>
</table>
<hr>
<p></p>
<ul>
<li><a href="#quick">A quick example</a></li>
<li><a href="#tree">A binary tree implementation</a></li>
<li><a href="#poly">Polymorphism: Inheritance vs. Variants</a></li>
</ul>
<hr>
<h2><a name="quick">A quick example</a></h2>
<p>This program computes the total sum of numerical values of various types.</p>
<p>The code defines a <code>variant</code> object, <code>v1</code>, which can
hold a value of this set of types: <code>short, int, float</code>, and <code>
double</code>.</p>
<p><code>double_sum</code> is a visitor class: Its function-call operator, <code>
double_sum::operator()</code>, accepts a single value, and adds it to the <code>
total_</code> data member. The program uses the construct: &quot;<code>boost::apply_visitor(visitor,
variant);</code>&quot; to invoke the visitor object, <code>(ds)</code> on the
specified variant <code>(v1)</code>.</p>
<p>Naturally, <code>ds.total_</code> holds the total of all previously &quot;visited&quot;
values, and - therefore - at the bottom of <code>main()</code>, its value is: 5
+ 16 + 3.11 + 15.3 = 39.41.</p>
<pre>#include &lt;iostream&gt;
#include &quot;boost/variant.hpp&quot;
#include &quot;boost/apply_visitor.hpp&quot;
#include &quot;boost/static_visitor.hpp&quot;
struct double_sum : boost::static_visitor&lt;double&gt;
{
double_sum() : total_(0.0) { }
template&lt;class X&gt;
double operator()(X x)
{
total_ += x;
return total_;
}
double total_;
};
int main(int, char* [] )
{
double_sum ds;
boost::variant&lt;short, int, float, double&gt; v1;
v1 = short(5);
boost::apply_visitor(ds, v1); // Apply ds to v1 (1st time)
v1 = 16;
boost::apply_visitor(ds, v1); // 2nd time
v1 = 3.11f;
boost::apply_visitor(ds, v1); // 3rd
v1 = 15.3;
double total = boost::apply_visitor(ds, v1); // 4th
// Expected output: &quot;Total = 39.41&quot;
std::cout &lt;&lt; &quot;Total = &quot; &lt;&lt; total &lt;&lt; std::endl;
return 0;
}
</pre>
<hr>
<h2><a name="tree">A binary tree implementation</a></h2>
<p>This sample program shows how <code>incomplete&lt;T&gt;</code> can be used to
define recursive <code>variants</code>.<br>
The code creates a small binary tree and then performs an in-order walk thru
its nodes, producing this output: 3 4 6 10 19 20 23<br>
</p>
<pre>#include &lt;iostream&gt;
#include &quot;boost/variant.hpp&quot;
#include &quot;boost/apply_visitor.hpp&quot;
#include &quot;boost/static_visitor.hpp&quot;
#include &quot;boost/incomplete.hpp&quot;
using boost::variant;
using boost::incomplete;
using std::cout;
using std::endl;
struct non_leaf_node; // Forward declaration
// Define a variant with these two types:
// 1) int
// 2) The (incomplete) non_leaf_node struct
typedef variant&lt;int, incomplete&lt;non_leaf_node&gt; &gt; tree_node;
struct non_leaf_node
{
non_leaf_node(const tree_node&amp; l, int num, const tree_node&amp; r)
: left_(l), right_(r), num_(num) { }
non_leaf_node(const non_leaf_node&amp; other)
: left_(other.left_), right_(other.right_), num_(other.num_) { }
int num_;
tree_node left_;
tree_node right_;
};
struct tree_printer : boost::static_visitor&lt;void&gt;
{
void operator()(int n) const
{
cout &lt;&lt; n &lt;&lt; ' ';
}
void operator()(const non_leaf_node&amp; node) const
{
boost::apply_visitor(*this, node.left_);
cout &lt;&lt; node.num_ &lt;&lt; ' ';
boost::apply_visitor(*this, node.right_);
}
};
int main(int, char* [] )
{
//Build a binary search tree:
non_leaf_node a(3,4, 6);
non_leaf_node b(19, 20, 23);
non_leaf_node c(a,10, b);
tree_node root(c);
//Perform an in-order walk
boost::apply_visitor(tree_printer(), root);
return 0;
}
</pre>
<hr>
<h2><a name="poly">Polymorphism: Inheritance vs. Variants</a></h2>
<p>Let's assume we need to write a program that manipulates instances of <code>
star</code> and <code>space_ship</code>, where each of these two classes
inherits from <code>space_object</code>. The program maintains a <code>vector</code>
of pointers to these objects, which is used to calculate the total weight of
all <code>star</code> objects: </p>
<pre> //
// 'classic' inheritance-based implementation
//
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;iostream&gt;
struct space_object
{
virtual int weight() const = 0;
virtual ~space_object() { }
};
struct space_ship : space_object
{
space_ship(int w = 0) : w_(w) { }
int weight() const { return w_; }
int get_speed() const { return 15; }
int w_;
};
struct star : space_object
{
star(int w = 0) : w_(w) { }
int weight() const { return w_; }
int w_;
};
struct total_weight
{
total_weight() : total_(0) { }
void operator()(space_object* so_p)
{
if(dynamic_cast&lt;star*&gt;(so_p))
total_ += so_p-&gt;weight();
}
int total_;
};
int main(int, char* [] )
{
typedef std::vector&lt;space_object*&gt; main_vec;
main_vec space_objects;
//fill space_objects
// ...
total_weight tw_job;
int total = std::for_each(space_objects.begin(), space_objects.end(),
tw_job).total_;
std::cout &lt;&lt; &quot;Total weight of all stars = &quot; &lt;&lt; total
&lt;&lt; std::endl;
//Apply delete to all pointers stored in space_objects
// ...
return 0;
}
</pre>
<p>The are several issues worth noticing about this sample:<br>
</p>
<ul>
<li>The code is bound to define a vector of pointers, rather than objects.
This incurs considerable time overhead and could cause memory leaks if
destruction is not handled properly. </li>
<li>the dynamic_cast&lt;&gt; used by <code>total_weight::operator()</code> is a
costly operation. Alternatively, one can define an <code>enum</code> type
which will be used to correctly identify the concrete object, but this is an
error prone technique: the author must manually set the correct value for each
new concrete class. </li>
<li><code>total_weight</code> is unsafe when new classes are introduced.
Suppose a new class, <code>black_hole</code> - inherits directly from <code>
space_object</code> - is added to the code. <code>total_weight</code> will
silently ignore this class, possibly creating a havoc of run-time problems.
This is a major flaw from software engineering standpoint. </li>
</ul>
<p>This real-life design problem can be elegantly solved using variants. Here is
the variant-based code: </p>
<pre> //
// Variant-based implementation
//
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &quot;boost/variant.hpp&quot;
#include &quot;boost/apply_visitor.hpp&quot;
#include &quot;boost/static_visitor.hpp&quot;
struct space_ship
{
space_ship(int w = 0) : w_(w) { }
int weight() const { return w_; }
int get_speed() const { return 15; }
int w_;
};
struct star
{
star(int w = 0) : w_(w) { }
int weight() const { return w_; }
int w_;
};
struct total_weight : boost::static_visitor&lt;void&gt;
{
total_weight() : total_(0) { }
void operator()(const star&amp; a_star)
{
total_ += a_star.weight();
}
//space_ship objects are ignored:
void operator()(const space_ship&amp; ) { }
int total_;
};
int main(int, char* [] )
{
typedef boost::variant&lt;star, space_ship&gt; space_var;
typedef std::vector&lt;space_var&gt; main_vec;
main_vec space_objects;
//fill space_objects
// ...
total_weight tw_job;
std::for_each(space_objects.begin(), space_objects.end(),
boost::apply_visitor(tw_job));
std::cout &lt;&lt; &quot;Total weight of all stars = &quot; &lt;&lt; tw_job.total_
&lt;&lt; std::endl;
return 0;
}
</pre>
<p>This implementation directly addresses the three issues raised by the
non-variant implementation: (1) The <code>space_objects</code> vector now holds
<b>objects</b> (rather than pointers), (2) <code>dynamic_cast&lt;&gt;</code>s are <b>
not needed</b> at all, and - most importantly - (3) the compiler <b>will
produce an error</b> if <code>total_weight</code> is not changed, when a new
class is introduced. </p>
<hr>
<p>Revised 14 February 2003</p>
<p><i>© Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

4
doc/styles.css Normal file
View File

@@ -0,0 +1,4 @@
PRE
{
BACKGROUND-COLOR: lightcyan
}

499
doc/tutorial.html Normal file
View File

@@ -0,0 +1,499 @@
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="Variant, design pattern, generic programming, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost::variant</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><a HREF="../../../index.htm">
<img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86" BORDER="0">
</a></h3>
</td>
<td valign="top">
<h1 align="center"><a href="index.html">boost::variant</a></h1>
<h2 align="center">Tutorial</h2>
</td>
</tr>
</table>
<hr>
<p></p>
<ul>
<li><a href="#FirstVariantProgram">First variant program</a></li>
<li><a href="#Instantiation">Instantiation</a></li>
<li><a href="#ValueSemantics">Value semantics</a></li>
<li><a href="#FunctorBasedVisitation">Functor-based visitation</a></li>
</ul>
<hr>
<p>The following sample program illustrates a typical usage of <code>variant</code>.
Additional sample programs may be found <a href="sample.html">here</a>.<br>
</p>
<h2><a name="FirstVariantProgram">First <code>variant</code> program</a></h2>
<p>Let's suppose you need to implement an object factory function, <code>create</code>.
Based on an integer argument to the function, <code>create</code> must
construct and return an object of one of the following types: <code>std::string</code>,
<code>char*</code>, and <code>int</code>. The relationship between the integer
argument, <code>i</code>, and the returned type is specified as follows:<br>
</p>
<pre> 2000 &lt; i -&gt; char*
1000 &lt; i &lt;= 2000 -&gt; std::string
<i>else </i> -&gt; int
</pre>
<p>Typical implementations would probably designate of a virtual base class,
returning objects of the derived types through a pointer to the base class.
However, since none of the desired types may derive from the base class, the
programmer would need to write &quot;adapter&quot; classes derived from the common base
to supply the semantics of the various concrete types (i.e, <code>std::string</code>,
<code>int</code>, and <code>char*</code>). Clients of the factory function
would then check the result using <code>dynamic_cast</code> to determine which
concrete type had in fact been created.</p>
<p>Other implementations might leverage the Boost <code>
<a href="../../any/index.html">any</a></code> class, thus avoiding the hassle
of defining and implementing the virtual base class and the derived adapter
classes. However, this solution still does not avoid the problem of needing to
manually check the result using <code>any_cast</code>.</p>
<p>On the other hand, by returning an object of type <code>variant&lt; std::string,
char*, int &gt;</code> from the factory function, the resultant code is clear and
straight-forward: </p>
<pre>#include &lt;iostream&gt;
#include &lt;string&gt;
#include &quot;boost/variant.hpp&quot;
#include &quot;boost/apply_visitor.hpp&quot;
using std::string;
using boost::variant;
typedef variant&lt;string, char*, int&gt; create_result;
//
// <i>create</i>, our factory function
//
create_result create(int i)
{
// Return char* if (i &gt; 2000):
if (which &gt; 2000) return &quot;JKLM&quot;;
// Return std::string if (1000 &lt; i &lt;= 2000):
if (which &gt; 1000) return string(&quot;QRST&quot;);
// Otherwise, return int:
return 15;
}
//
// <i>printer</i>, a visitor that prints to std::cout
//
struct printer : boost::static_visitor&lt;&gt;
{
template &lt;typename T&gt;
void operator()(const T&amp; t)
{
std::cout &lt;&lt; &quot;operand: &quot; &lt;&lt; t &lt;&lt; std::endl;
}
};
int main(int , char* [] )
{
printer print;
create_result result;
// First, create a char*...
result = create(2500);
// ...and print result by applying print visitor to it:
boost::apply_visitor(a_printer, inst); // Output: &quot;operand: JKLM&quot;
// Now, create a std::string and print it:
result = create(1500);
boost::apply_visitor(a_printer, inst); // Output: &quot;operand: QRST&quot;
// Finally, create an int and print it:
result = create(5);
boost::apply_visitor(a_printer, inst); // Output: &quot;15&quot;
return 0;
}
</pre>
<hr>
<h2><a name="Instantiation">Instantiation</a></h2>
<p>A concrete <code>variant</code> instantiation has this general form: </p>
<pre>typedef boost::variant&lt;T1, T2, ... TN&gt; variant_type;
</pre>
<p>Where the types <code>T1, T2, ... TN</code> must model the
<a href="reference.html#BoundedTypes">BoundedType</a> concept. An instance of
<code>variant_type</code> is capable of holding a value of any of these types.</p>
<h3>Examples: </h3>
<pre> boost::variant&lt;int, char, double&gt; v1; // OK
variant&lt;int, char, double, char&gt; v2; // Error: char appears twice
variant&lt;float&gt; v3; // Error: At least two types must be specified
variant&lt;char, char* const, void*&gt; v4; // Error: top-level const types are illegal
variant&lt;char, const char*, void*&gt; v5; // OK - const char* is not a top-level const type
</pre>
<p>If one of these types is incomplete at the instantiation point, it must be
enclosed inside an <code>incomplete&lt;&gt;</code> wrapper, as shown below:<br>
</p>
<pre> struct jas1; // Forward declaration of jas1 (Just Another Struct)
variant&lt;jas1, double, std::string&gt; v6; // Error: jas1 is incomplete
struct jas1 { ... };
struct jas2; // Forward declaration of jas2
variant&lt;incomplete&lt;jas2&gt;, double, std::string&gt; v7; // OK -
// incomplete&lt;&gt; is used for incomplete types
struct jas2 { ... };
</pre>
<hr>
<h2><a name="ValueSemantics">Value semantics</a></h2>
<p>Once a <code>variant</code> object has been created its value may be changed
by <code>variant</code>'s assingment operator. The right-hand side value of the
assignment is converted to the closet possible type of the assigned variant's
<a href="reference.html#SetOfTypes">set of types</a>, by using overload
resolution rules. Naturally, If there is an exact match, no convesion is
applied, and the right-hand side value is copied as-is. On the other hand, if
no conversion exists, or, if the conversion is ambiguous, a compiler error is
triggered.</p>
<p>The assignment rules (mentioned above) also apply when a variant object is
initalized. Hence, the rest of this section will refer to assignment and
initialization interchangeably. </p>
<pre> variant&lt;int, char, double&gt; v1;
v1 = 5.9; // double -&gt; double (no conversion is needed)
v1 = 3; // int -&gt; int - &quot; -
v1 = 'x'; // char -&gt; char - &quot; -
v1 = short(5); // short -&gt; int
v1 = 5.9f; // float -&gt; double
v1 = static_cast&lt;unsigned char&gt;('x'); // unsigned char -&gt; int
v1 = string(&quot;abc&quot;); // Error! no implicit conversion from
// string to int/char/double
v1 = static_cast&lt;long double&gt;(4.0); // Error! (ambiguity):
// long double -&gt; double conversion
// clashes with long double -&gt; int conversion
variant&lt;std::string, double, int&gt; v2; // Default construction.
// Use default value of first type,
// i.e: v2 = std::string()
struct class1
{
class1(const char* s = 0) { .. }
..
};
struct class2
{
class2(const char* s) { .. }
..
};
variant&lt;class1, double&gt; v3;
v3 = 5; // int -&gt; double
v3 = class1(&quot;abc&quot;); // class1 -&gt; class1
v3 = &quot;abc&quot;; // const char* -&gt; class1
variant&lt;class1, class2&gt; v4;
v4 = class1(&quot;text1&quot;); // class1 -&gt; class1
v4 = class2(&quot;text2&quot;); // class2 -&gt; class2
v4 = &quot;text3&quot;; // Error! (ambiguity):
// class1 clashes with class2
</pre>
<p>Copy assignment: When a variant object is assigned to another variant object
- which is of the same concrete type - the assignee becomes an exact duplicate
of the assigned variant: </p>
<pre> variant&lt;int, char, double&gt; v1, v2;
v1 = 5.9; // v1 = double(5.9)
v2 = v1; // v2 = double(5.9)
v1 = 3; // v1 = int(3)
v2 = v1; // v2 = int(3)
v1 = short(5); // short -&gt; int, hence: v1 = int(5)
v2 = v1; // v2 = int(5)
v1 = 5.7f; // float -&gt; double, hence: v1 = double(5.7)
v2 = v1; // v2 = double(5.7)
</pre>
<p>Variant-to-variant assignment: Consider this case: </p>
<pre> typedef variant&lt;RR, SS, TT, .. &gt; rhs_type;
rhs_type src;
typedef variant&lt;XX, YY, ZZ, .. &gt; lhs_type;
lhs_type trg;
trg = src; // Variant to variant assignment:
// trg and src are two variants of different types
</pre>
<p>What will <code>trg</code>'s value be, following such an assignment?<br>
</p>
<ul>
<li>Case 1: If <code>rhs_type</code> is not part of <code>lhs_type</code>'s
<a href="reference.html#SetOfTypes">set of types</a>, then <code>src</code>'s
value is assigned to <code>trg</code>, using the rules discussed throughout
this section. </li>
<li>Case 2: If <code>rhs_type</code> <b>does</b> appear on <code>lhs_type</code>'s
set of types, then <code>src</code> itself will be assigned into <code>trg</code>,
turning <code>trg</code> into a <b>variant holding a variant</b> </li>
</ul>
<pre> typedef variant&lt;int, std::string&gt; variant_type;
variant_type a;
variant&lt;int, double, std::string&gt; b;
variant&lt;variant_type, int, double, std::string&gt; c;
a = &quot;hello&quot;; // char* converted to std::string
b = a; // b &lt;- value of a, so b holds an std::string (Case 1)
c = a; // c &lt;- a, so c holds a variant_type object holding
// an std::string (Case 2)
</pre>
<p>Note that a variant-to-variant assignment will fail - at compile time - if
one of <code>src</code>'s bounded types cannot be assigned to <code>trg</code>
(due to ambiguity/lack of conversion).<br>
For instance: </p>
<pre> variant&lt;int, std::string&gt; a;
variant&lt;int, const char*&gt; b;
a = b; // OK: int-&gt;int or const char* -&gt; std::string
b = a; // Error!
// std::string is not implicitly convertible to either int
// or const char*, so the compiler will break on this line
</pre>
<hr>
<h2><a name="FunctorBasedVisitation">Functor-based visitation</a></h2>
<p>The visitation facility, implemented via <a href="reference.html#Visitation">
<code>apply_visitor()</code></a>, is the primary mechanism thru which client
code can gain access to a variant-held value.<br>
<br>
Let us consider the following piece of code. </p>
<pre> boost::variant&lt;XX, YY, ZZ, ... &gt; a_variant;
struct visitor_type { ... };
visitor_type visitor;
boost::apply_visitor(visitor, a_variant)
</pre>
<p>In this sample, <code>visitor_type</code> must be a
<a href="reference.html#Visitor">Visitor</a> of <code>a_variant</code>. These
requirements may be informally defined as: <code>visitor_type</code> must be a
unary function object that is capable of accepting a value of any of <code>
a_variant</code>'s <a href="reference.html#BoundedTypes">BoundedTypes</a>. If
<code>visitor_type</code> fails to meet these requirements, (i.e: it cannot
accept one, or more, of the types in <code>a_variant</code>'s set of types) a
compiler error is triggered.</p>
<p>The 'visit' begins when <code>apply_visitor()</code> is called: <code>
apply_visitor(visitor, a_variant)</code> passes <code>a_variant</code>'s
currently held value to <code>visitor</code>. From <code>visitor</code>'s
standpoint, its function-call operator is called with whatever value <code>
a_variant</code> is holding. This gives <code>visitor</code> a chacne to
inspect/modify <code>a_variant</code>'s value.</p>
<p>The following snip demonstrates the visitation facility using a concrete
visitor class, <code>print_int_char_visitor</code>. The code will print &quot;Char
value: 'x'&quot; and &quot;Int value: 77&quot; to <code>std::cout</code>:</p>
<pre> struct print_int_float_visitor
{
//result_type specifies the return type of operator()
typedef void result_type;
// Handle int values
void operator()(int x) const
{
std::cout &lt;&lt; &quot;Int value: &quot; &lt;&lt; x &lt;&lt; std::endl;
}
// Handle char values
void operator()(float x) const
{
std::cout &lt;&lt; &quot;Float value: &quot; &lt;&lt; x &lt;&lt; std::endl;
}
};
.
.
variant&lt;int, float&gt; var = 53.22f;
//Apply print_int_char_visitor to var.
apply_visitor(print_int_float_visitor(), var); // Output: &quot;Float value: 53.22&quot;
var = 77;
apply_visitor(print_int_float_visitor(), var); // Output: &quot;Int value: 77&quot;
</pre>
<p>Note how <code>print_int_char_visitor</code> specifies the type of its return
value thru a nested type - <code>result_type</code>. This return value is also
the value that is returned by <code>boost::apply_visitor()</code> to its
caller.</p>
<p>The next code snip, demonstrate how <code>boost::static_visitor&lt;T&gt;</code> can
be used as a base class to supply <code>result_type</code>'s definition. The
visitor in this snip, <code>multiply_by_two</code> multiplies its operand by
two and returns the result as an <code>int</code> value. </p>
<pre> struct multiply_by_two
: boost::static_visitor&lt;int&gt; // Return type is int,
// so derive from static_visitor&lt;int&gt;
{
template&lt;typename T&gt;
int operator()(T t) const
{
return int(2 * t);
}
};
.
.
variant&lt;int, short, char&gt; a = 9;
int result = apply_visitor(multiply_by_two(), a);
std::cout &lt;&lt; &quot;Result = &quot; &lt;&lt; result &lt;&lt; std::endl; //Output: &quot;Result = 18&quot;
</pre>
<p>If a visitor offers several overloads of <code>operator()</code>, overload
resolution rules are applied to choose the correct form. If a visitor cannot
accept one of the types a variant may hold (due to ambiguity/lack of
conversion), a comiler error is generated. <br>
</p>
<pre> struct print_int_char : boost::static_visitor&lt;void&gt;
{
// Handler *A*
void operator()(int f) const
{
std::cout &lt;&lt; &quot;Int value: &quot; &lt;&lt; f &lt;&lt; std::endl;
}
// Handler *B*
void operator()(char c) const
{
std::cout &lt;&lt; &quot;Char value: '&quot; &lt;&lt; c &lt;&lt; '\''
&lt;&lt; std::endl;
}
};
.
.
variant&lt;short, char&gt; a = static_cast&lt;short&gt;(88);
apply_visitor(print_int_char(), a); // Output: &quot;Int value: 88.0&quot;
// (int value intercepted by handler *A*)
a = 'x'; // a = 'x'
apply_visitor(print_int_char(), a); // Output: &quot;Char value: 'x'&quot;
variant&lt;int, char, void*&gt; b = 88; // b = int(88)
apply_visitor(print_int_char(), b); // Error! -
// void* cannot be handled by neither
// handler (*A* or *B*)
</pre>
<p>&quot;Catch-all&quot; behavior can be achieved by supplying a templated form of <code>
operator(): </code></p>
<pre> struct ignore_non_ints_visitor : boost::static_visitor&lt;void&gt;
{
void operator()(int t) const
{
std::cout &lt;&lt; &quot;Current value: &quot; &lt;&lt; t &lt;&lt; std::endl;
}
template&lt;typename T&gt;
void operator()(const T&amp; t) const
{
// Catch all other types:
std::cout &lt;&lt; &quot;Ignore me&quot; &lt;&lt; std::endl;
}
};
.
.
variant&lt;int, double, std::string&gt; a = &quot;abcde&quot;;
apply_visitor(ignore_non_ints_visitor(), a); //Output: &quot;Ignore me&quot;
a = 22.24;
apply_visitor(ignore_non_ints_visitor(), a); //Output: &quot;Ignore me&quot;
a = 8;
apply_visitor(ignore_non_ints_visitor(), a); //Output: &quot;Current value: 8&quot;
</pre>
<p>A visitor may accept its operand using a &quot;pass-by-reference&quot; parameter
passing scheme. This allows a visitor to mutate the variant-held value: </p>
<pre> struct first_capital : boost::static_visitor&lt;void&gt;
{
void operator()(std::string&amp; str) const
{
str[0] = toupper(str[0]);
}
void operator()(char* str) const
{
*str = toupper(*str);
}
};
struct printer : boost::static_visitor&lt;void&gt;
{
template&lt;typename T&gt;
void operator()(const T&amp; t) const
{
std::cout &lt;&lt; t &lt;&lt; std::endl;
}
};
.
.
variant&lt;std::string, char*&gt; a = std::string(&quot;abcde&quot;);
apply_visitor(printer(), a); //Output: &quot;abcde&quot;
apply_visitor(first_capital(), a); //Invoke the mutating visitor
//(capitalizes the first letter)
apply_visitor(printer(), a); //Output: &quot;Abcde&quot;
</pre>
<p>The last sample shows persistency of visitors. Every visitor is actually a
function object, so its data members can be used to keep persistent data. The
<code>int_accumulator</code> visitor uses <code>total_</code> to keep track of
the total sum of its operands: </p>
<pre> struct int_accumulator : boost::static_visitor&lt;void&gt;
{
int_accumulator() : total_(0) { }
void operator()(int x)
{
total_ += x;
}
int total_;
} ;
.
.
int_accumulator adder;
variant&lt;int, short, char&gt; a = 15;
apply_visitor(adder, a); //adder.total_ += 15
a = short(9);
apply_visitor(adder, a); //adder.total_ += 9
std::cout &lt;&lt; &quot;Total = &quot; &lt;&lt; adder.total_ &lt;&lt; std::endl; //Output: &quot;Total = 24&quot;
</pre>
<p><b>Note:</b> When <code>boost::apply_visitor()</code> is used, the compiler
verifies that the specified visitor type is a valid visitor with respect to the
relevant variant type. If the visitor fails to meet the
<a href="reference.html#Visitor">Visitor</a> requirements, a compiler error is
fired. This allows programming errors to be detected at compile-time rather
than run-time, thus enhancing code safety and stability.</p>
<hr>
<p>Revised 14 February 2003</p>
<p><i>© Copyright Eric Friedman and Itay Maman 2002-2003. All rights reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. Eric Friedman
and Itay Maman make no representations about the suitability of this software
for any purpose. It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

39
include/boost/empty.hpp Normal file
View File

@@ -0,0 +1,39 @@
//-----------------------------------------------------------------------------
// boost empty.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_EMPTY_HPP
#define BOOST_EMPTY_HPP
#include "boost/config.hpp"
#include "boost/mpl/bool.hpp"
#include "boost/type_traits/is_pod.hpp"
namespace boost {
struct empty
{
};
template <>
struct is_pod<empty>
{
BOOST_STATIC_CONSTANT(bool, value = true);
typedef mpl::bool_<value> type;
};
} // namespace boost
#endif // BOOST_EMPTY_HPP

View File

@@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
// boost incomplete.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_INCOMPLETE_HPP
#define BOOST_INCOMPLETE_HPP
#include "boost/incomplete_fwd.hpp"
#include "boost/checked_delete.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class template incomplete
//
// Treats an incomplete type as a value type.
//
template <typename T>
class incomplete
{
public: // representation
T* p_;
public: // structors
~incomplete();
incomplete();
incomplete(const incomplete& operand);
incomplete(const T& operand);
public: // modifiers
incomplete& operator=(incomplete rhs)
{
swap(rhs);
return *this;
}
incomplete& operator=(const T& rhs)
{
incomplete temp(rhs);
swap(temp);
return *this;
}
void swap(incomplete& operand)
{
T* temp = operand.p_;
operand.p_ = p_;
p_ = temp;
}
public: // queries
T& get() { return *get_pointer(); }
const T& get() const { return *get_pointer(); }
T* get_pointer() { return p_; }
const T* get_pointer() const { return p_; }
};
template <typename T>
incomplete<T>::~incomplete()
{
boost::checked_delete(p_);
}
template <typename T>
incomplete<T>::incomplete()
: p_(new T)
{
}
template <typename T>
incomplete<T>::incomplete(const incomplete& operand)
: p_(new T( operand.get() ))
{
}
template <typename T>
incomplete<T>::incomplete(const T& operand)
: p_(new T(operand))
{
}
// function template swap
//
// Swaps two incomplete<T> objects of the same type T.
//
template <typename T>
inline void swap(incomplete<T>& lhs, incomplete<T>& rhs)
{
lhs.swap(rhs);
}
} // namespace boost
#endif // BOOST_INCOMPLETE_HPP

View File

@@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// boost incomplete_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_INCOMPLETE_FWD_HPP
#define BOOST_INCOMPLETE_FWD_HPP
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class template incomplete
//
// Treats an incomplete type as a value type.
//
template <typename T> class incomplete;
} // namespace boost
#endif // BOOST_INCOMPLETE_FWD_HPP

30
include/boost/variant.hpp Normal file
View File

@@ -0,0 +1,30 @@
//-----------------------------------------------------------------------------
// boost variant.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_HPP
#define BOOST_VARIANT_HPP
// variant "main"
#include "boost/variant/variant_fwd.hpp"
#include "boost/variant/variant.hpp"
// common applications
#include "boost/variant/get.hpp"
#include "boost/variant/apply_visitor.hpp"
#include "boost/variant/static_visitor.hpp"
#include "boost/variant/visitor_ptr.hpp"
#endif // BOOST_VARIANT_HPP

View File

@@ -0,0 +1,24 @@
//-----------------------------------------------------------------------------
// boost apply_visitor.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_APPLY_VISITOR_HPP
#define BOOST_APPLY_VISITOR_HPP
#include "boost/variant/detail/apply_visitor_unary.hpp"
#include "boost/variant/detail/apply_visitor_binary.hpp"
#include "boost/variant/detail/apply_visitor_delayed.hpp"
#endif // BOOST_APPLY_VISITOR_HPP

View File

@@ -0,0 +1,43 @@
//-----------------------------------------------------------------------------
// boost visitor/bad_visit.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VISITOR_BAD_VISIT_HPP
#define BOOST_VISITOR_BAD_VISIT_HPP
#include <exception>
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class bad_visit
//
// Exception thrown when a visitation attempt fails due to invalid
// visited subtype or contents.
//
struct bad_visit
: std::exception
{
public:
virtual const char * what() const throw()
{
return "boost::bad_visit: "
"failed visitation using boost::apply_visitor";
}
};
} // namespace boost
#endif // BOOST_VISITOR_BAD_VISIT_HPP

View File

@@ -0,0 +1,133 @@
//-----------------------------------------------------------------------------
// boost variant/detail/apply_visitor_binary.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
#include "boost/variant/detail/apply_visitor_unary.hpp"
#include "boost/variant/detail/define_forwarding_func.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, visitable1, visitable2)
//
// Visits visitable1 and visitable2 such that their values (which we
// shall call x and y, respectively) are used as arguments in the
// expression visitor(x, y).
//
namespace detail { namespace visitor {
template <typename Visitor, typename Value1>
class binary_delay0
{
public:
typedef typename Visitor::result_type
result_type;
private:
Visitor& visitor_;
Value1& value1_;
public:
binary_delay0(Visitor& visitor, Value1& value1)
: visitor_(visitor)
, value1_(value1)
{
}
template <typename Value0>
result_type operator()(Value0& value0)
{
return visitor_(value0, value1_);
}
template <typename Value0>
result_type operator()(const Value0& value0)
{
return visitor_(value0, value1_);
}
};
template <typename Visitor, typename Visitable1>
class binary_delay1
{
public:
typedef typename Visitor::result_type
result_type;
private:
Visitor& visitor_;
Visitable1& visitable1_;
public:
binary_delay1(Visitor& visitor, Visitable1& visitable1)
: visitor_(visitor)
, visitable1_(visitable1)
{
}
# define BOOST_AUX_BINARY_VISITOR_DELAY1_FUNC_OPERATOR(CV__) \
template <typename Visitable2> \
result_type operator()(CV__ Visitable2& visitable2) \
{ \
binary_delay0< \
Visitor \
, CV__ Visitable2 \
> delayer(visitor_, visitable2); \
return boost::apply_visitor(delayer, visitable1_); \
} \
/**/
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC(
BOOST_AUX_BINARY_VISITOR_DELAY1_FUNC_OPERATOR
, 1
)
# undef BOOST_AUX_BINARY_VISITOR_DELAY1_FUNC_OPERATOR
};
}} // namespace detail::visitor
#define BOOST_VARIANT_AUX_APPLY_VISITOR_BINARY(CV1__, CV2__, CV3__) \
template <typename Visitor, typename Visitable1, typename Visitable2> \
inline \
typename Visitor::result_type \
apply_visitor( \
CV1__ Visitor& visitor \
, CV2__ Visitable1& visitable1 \
, CV3__ Visitable2& visitable2 \
) \
{ \
detail::visitor::binary_delay1< \
CV1__ Visitor \
, CV2__ Visitable1 \
> delayer(visitor, visitable1); \
return boost::apply_visitor(delayer, visitable2); \
} \
/**/
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC(
BOOST_VARIANT_AUX_APPLY_VISITOR_BINARY
, 3
)
#undef BOOST_VARIANT_AUX_APPLY_VISITOR_BINARY
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP

View File

@@ -0,0 +1,110 @@
//-----------------------------------------------------------------------------
// boost variant/detail/apply_visitor_delayed.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VISITOR_APPLY_VISITOR_DELAYED_HPP
#define BOOST_VISITOR_APPLY_VISITOR_DELAYED_HPP
#include "boost/variant/detail/apply_visitor_unary.hpp"
#include "boost/variant/detail/apply_visitor_binary.hpp"
#include "boost/variant/detail/define_forwarding_func.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor)
//
// Returns a function object, overloaded for unary and binary usage, that
// visits its arguments using visitor (or a copy of visitor) via
// * apply_visitor( visitor, [argument] )
// under unary invocation, or
// * apply_visitor( visitor, [argument1], [argument2] )
// under binary invocation.
//
// NOTE: Unlike other apply_visitor forms, the visitor object must be
// non-const; this prevents user from giving temporary, to disastrous
// effect (i.e., returned function object would have dead reference).
//
template <typename Visitor>
class apply_visitor_delayed_t
{
public: // typedefs
typedef typename Visitor::result_type
result_type;
private: // representation
Visitor& visitor_;
public: // structors
explicit apply_visitor_delayed_t(Visitor& visitor)
: visitor_(visitor)
{
}
public: // unary function operators
# define BOOST_AUX_APPLY_VISITOR_DELAYED_T_UNARY_FUNC_OPERATOR(CV__) \
template <typename Visitable> \
result_type operator()( \
CV__ Visitable& visitable \
) \
{ \
apply_visitor(visitor_, visitable); \
} \
/**/
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC(
BOOST_AUX_APPLY_VISITOR_DELAYED_T_UNARY_FUNC_OPERATOR
, 1
)
# undef BOOST_AUX_APPLY_VISITOR_DELAYED_T_UNARY_FUNC_OPERATOR
public: // binary function operators
# define BOOST_AUX_APPLY_VISITOR_DELAYED_T_BINARY_FUNC_OPERATOR(CV1__, CV2__) \
template <typename Visitable1, typename Visitable2> \
result_type operator()( \
CV1__ Visitable1& visitable1 \
, CV2__ Visitable2& visitable2 \
) \
{ \
apply_visitor(visitor_, visitable1, visitable2); \
} \
/**/
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC(
BOOST_AUX_APPLY_VISITOR_DELAYED_T_BINARY_FUNC_OPERATOR
, 2
)
# undef BOOST_AUX_APPLY_VISITOR_DELAYED_T_BINARY_FUNC_OPERATOR
};
template <typename Visitor>
inline apply_visitor_delayed_t<Visitor> apply_visitor(Visitor& visitor)
{
return apply_visitor_delayed_t<Visitor>(visitor);
}
} // namespace boost
#endif // BOOST_VISITOR_APPLY_VISITOR_DELAYED_HPP

View File

@@ -0,0 +1,57 @@
//-----------------------------------------------------------------------------
// boost variant/detail/apply_visitor_unary.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
#include "boost/variant/detail/define_forwarding_func.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, variant)
//
// Visits visitable with visitor.
//
#define BOOST_VARIANT_AUX_APPLY_VISITOR_FUNC(CV1_, CV2_) \
template < \
typename Visitor \
, BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, typename T) \
> \
inline \
typename Visitor::result_type \
apply_visitor( \
CV1_ Visitor& visitor \
, CV2_ boost::variant< \
BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, T) \
>& var \
) \
{ \
return var.apply_visitor(visitor); \
} \
/**/
#
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC(
BOOST_VARIANT_AUX_APPLY_VISITOR_FUNC
, 2
)
#
#undef BOOST_VARIANT_AUX_APPLY_VISITOR_FUNC
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP

View File

@@ -0,0 +1,98 @@
//-----------------------------------------------------------------------------
// boost variant/detail/define_forwarding_func.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_DEFINE_FORWARDING_FUNC_HPP
#define BOOST_VARIANT_DETAIL_DEFINE_FORWARDING_FUNC_HPP
#include "boost/preprocessor/debug/assert.hpp"
#include "boost/preprocessor/comparison/less_equal.hpp"
//////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC
// 000
// 001
// 010
// 011 'const pattern' follows binary addition...
// 100 (TODO: generalize with preprocessor to N params)
// 101
// 110
// 111
// support macros
#define BOOST_VARIANT_AUX_NOTHING /**/
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_1(macro) \
macro(BOOST_VARIANT_AUX_NOTHING) \
macro(const) \
/**/
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_2(macro) \
macro(BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING) \
macro(BOOST_VARIANT_AUX_NOTHING,const) \
macro(const,BOOST_VARIANT_AUX_NOTHING) \
macro(const,const) \
/**/
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_3(macro) \
macro(BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING) \
macro(BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING,const) \
macro(BOOST_VARIANT_AUX_NOTHING,const,BOOST_VARIANT_AUX_NOTHING) \
macro(BOOST_VARIANT_AUX_NOTHING,const,const) \
macro(const,BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING) \
macro(const,BOOST_VARIANT_AUX_NOTHING,const) \
macro(const,const,BOOST_VARIANT_AUX_NOTHING) \
macro(const,const,const) \
/**/
#else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_1(macro) \
macro(BOOST_VARIANT_AUX_NOTHING) \
/**/
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_2(macro) \
macro(BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING) \
/**/
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_3(macro) \
macro(BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING,BOOST_VARIANT_AUX_NOTHING) \
/**/
#endif
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_IMPL_MAX 3
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_IMPL_MAX_MSG \
"current implementation of BOOST_DEFINE_FORWARDING_FUNC only supports 3 params"
// actual macro definition:
#define BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC( macro , arg_count ) \
BOOST_PP_ASSERT_MSG( \
BOOST_PP_LESS_EQUAL( \
arg_count \
, BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_IMPL_MAX \
) \
, BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_IMPL_MAX_MSG \
) \
BOOST_PP_CAT( \
BOOST_VARIANT_AUX_DEFINE_FORWARDING_FUNC_ \
, arg_count \
) (macro) \
/**/
#endif // BOOST_VARIANT_DETAIL_DEFINE_FORWARDING_FUNC_HPP

View File

@@ -0,0 +1,106 @@
// (C) Copyright Eric Friedman 2002-2003.
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies. This software
// is provided "as is" without express or implied warranty, and with no claim
// as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_VARIANT_DETAIL_HAS_NOTHROW_MOVE_HPP_INCLUDED
#define BOOST_VARIANT_DETAIL_HAS_NOTHROW_MOVE_HPP_INCLUDED
#include "boost/variant/detail/has_trivial_move.hpp"
#include "boost/type_traits/has_nothrow_copy.hpp"
#include "boost/type_traits/has_nothrow_assign.hpp"
#include "boost/mpl/and.hpp"
#include "boost/mpl/or.hpp"
// should be the last #include
#include "boost/type_traits/detail/bool_trait_def.hpp"
namespace boost {
namespace detail { namespace variant {
// TRAIT: has_nothrow_move
template <typename T>
struct has_nothrow_move_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::or_<
has_trivial_move<T>
, mpl::and_<
has_nothrow_copy<T>
, has_nothrow_assign<T>
>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_nothrow_move
, T
, (::boost::detail::variant::has_nothrow_move_impl<T>::value)
)
// TRAIT: has_nothrow_move_constructor
template <typename T>
struct has_nothrow_move_constructor_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::or_<
has_nothrow_move<T>
, has_trivial_move_constructor<T>
, has_nothrow_copy<T>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_nothrow_move_constructor
, T
, (::boost::detail::variant::has_nothrow_move_constructor_impl<T>::value)
)
// TRAIT: has_nothrow_move_assign
template <typename T>
struct has_nothrow_move_assign_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::or_<
has_nothrow_move<T>
, has_trivial_move_assign<T>
, has_nothrow_assign<T>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_nothrow_move_assign
, T
, (::boost::detail::variant::has_nothrow_move_assign_impl<T>::value)
)
}} // namespace detail::variant
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_nothrow_move)
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_nothrow_move_constructor)
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_nothrow_move_assign)
} // namespace boost
#include "boost/type_traits/detail/bool_trait_undef.hpp"
#endif // BOOST_VARIANT_DETAIL_HAS_NOTHROW_MOVE_HPP_INCLUDED

View File

@@ -0,0 +1,100 @@
// (C) Copyright Eric Friedman 2002-2003.
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies. This software
// is provided "as is" without express or implied warranty, and with no claim
// as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_VARIANT_DETAIL_HAS_TRIVIAL_MOVE_HPP_INCLUDED
#define BOOST_VARIANT_DETAIL_HAS_TRIVIAL_MOVE_HPP_INCLUDED
#include "boost/type_traits/has_trivial_copy.hpp"
#include "boost/type_traits/has_trivial_assign.hpp"
#include "boost/mpl/and.hpp"
#include "boost/mpl/or.hpp"
// should be the last #include
#include "boost/type_traits/detail/bool_trait_def.hpp"
namespace boost {
namespace detail { namespace variant {
// TRAIT: has_trivial_move
template <typename T>
struct has_trivial_move_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::and_<
has_trivial_copy<T>
, has_trivial_assign<T>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_trivial_move
, T
, (::boost::detail::variant::has_trivial_move_impl<T>::value)
)
// TRAIT: has_trivial_move_constructor
template <typename T>
struct has_trivial_move_constructor_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::or_<
has_trivial_move<T>
, has_trivial_copy<T>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_trivial_move_constructor
, T
, (::boost::detail::variant::has_trivial_move_constructor_impl<T>::value)
)
// TRAIT: has_trivial_move_assign
template <typename T>
struct has_trivial_move_assign_impl
{
BOOST_STATIC_CONSTANT(
bool, value = (
mpl::or_<
has_trivial_move<T>
, has_trivial_assign<T>
>::type::value
)
);
};
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
has_trivial_move_assign
, T
, (::boost::detail::variant::has_trivial_move_assign_impl<T>::value)
)
}} // namespace detail::variant
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_trivial_move)
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_trivial_move_constructor)
BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,::boost::detail::variant::has_trivial_move_assign)
} // namespace boost
#include "boost/type_traits/detail/bool_trait_undef.hpp"
#endif // BOOST_VARIANT_DETAIL_HAS_TRIVIAL_MOVE_HPP_INCLUDED

View File

@@ -0,0 +1,169 @@
//-----------------------------------------------------------------------------
// boost variant/detail/move.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// See below original copyright by Andrei Alexandrescu.
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_DETAIL_MOVE_HPP
#define BOOST_VARIANT_DETAIL_MOVE_HPP
#include <iterator> // for iterator_traits
#include <new> // for placement new
#include "boost/config.hpp"
#include "boost/detail/workaround.hpp"
#include "boost/mpl/if.hpp"
#include "boost/type_traits/is_base_and_derived.hpp"
namespace boost {
namespace detail { namespace variant {
//////////////////////////////////////////////////////////////////////////
// forward declares
//
template <typename Deriving> class moveable;
template <typename T> class move_source;
template <typename T> class move_return;
//////////////////////////////////////////////////////////////////////////
// function template move
//
// Takes a T& and returns, if T derives moveable<T>, a move_source<T> for
// the object; else, returns the T&.
//
namespace detail {
// (detail) class template move
//
// Metafunction that, given moveable T, provides move_source<T>, else T&.
//
template <typename T>
struct move_type
{
public: // metafunction result
typedef typename mpl::if_<
is_base_and_derived<moveable<T>, T>
, move_source<T>
, T&
>::type type;
};
} // namespace detail
template <typename T>
inline
typename detail::move_type<T>::type
move(T& source)
{
typedef typename detail::move_type<T>::type
move_t;
return move_t(source);
}
//////////////////////////////////////////////////////////////////////////
// class template return_t
//
// Metafunction that, given moveable T, provides move_return<T>, else T.
//
template <typename T>
struct return_t
{
public: // metafunction result
typedef typename mpl::if_<
is_base_and_derived<moveable<T>, T>
, move_return<T>
, T
>::type type;
};
//////////////////////////////////////////////////////////////////////////
// function template move_swap
//
// Swaps using Koenig lookup but falls back to move-swap for primitive
// types and on non-conforming compilers.
//
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \
|| BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(2))
// [Indicate that move_swap by overload is disabled...]
#define BOOST_NO_MOVE_SWAP_BY_OVERLOAD
// [...and provide straight swap-by-move implementation:]
template <typename T>
inline void move_swap(T& lhs, T& rhs)
{
T tmp( boost::detail::variant::move(lhs) );
lhs = boost::detail::variant::move(rhs);
rhs = boost::detail::variant::move(tmp);
}
#else// !workaround
namespace detail { namespace move_swap {
template <typename T>
inline void swap(T& lhs, T& rhs)
{
T tmp( boost::detail::variant::move(lhs) );
lhs = boost::detail::variant::move(rhs);
rhs = boost::detail::variant::move(tmp);
}
}} // namespace detail::move_swap
template <typename T>
inline void move_swap(T& lhs, T& rhs)
{
using detail::move_swap::swap;
swap(lhs, rhs);
}
#endif // workaround
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MOVE_HPP
/* This file derivative of MoJO. Much thanks to Andrei for his initial work.
* See <http://www.cuj.com/experts/2102/alexandr.htm> for information on MOJO.
* Original copyright -- on mojo.h -- follows:
////////////////////////////////////////////////////////////////////////////////
// MOJO: MOving Joint Objects
// Copyright (c) 2002 by Andrei Alexandrescu
//
// Created by Andrei Alexandrescu
//
// Permission to use, copy, modify, distribute and sell this software for any
// purpose is hereby granted without fee, provided that the above copyright
// notice appear in all copies and that both that copyright notice and this
// permission notice appear in supporting documentation.
// The author makes no representations about the suitability of this software
// for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
*/

View File

@@ -0,0 +1,130 @@
//-----------------------------------------------------------------------------
// boost variant/get.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_GET_HPP
#define BOOST_VARIANT_GET_HPP
#include <exception>
#include "boost/preprocessor/enum_params.hpp"
#include "boost/utility/addressof.hpp"
#include "boost/variant/variant_fwd.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class bad_get
//
// The exception thrown in the event of a failed get of a value.
//
class bad_get
: public std::exception
{
public: // std::exception implementation
virtual const char * what() const throw()
{
return "boost::bad_get: "
"failed value get using boost::get";
}
};
//////////////////////////////////////////////////////////////////////////
// function template get<T>
//
// Retrieves content of given variant object if content is of type T.
// Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
//
namespace detail { namespace variant {
// (detail) class template get_visitor
//
// Generic static visitor that: if the value is of the specified type,
// returns a pointer to the value it visits; else a null pointer.
//
template <typename T>
struct get_visitor
{
public: // typedefs
typedef T* result_type;
public: // visitor interfaces
template <typename U>
T* operator()(U&) const
{
return static_cast<T*>(0);
}
T* operator()(T& operand) const
{
return boost::addressof(operand);
}
};
}} // namespace detail::variant
template <typename U, BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, typename T) >
inline U* get(
boost::variant< BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, T) >* operand
)
{
if (!operand) return static_cast<U*>(0);
detail::variant::get_visitor<U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, typename T) >
inline U* get(
const boost::variant< BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, T) >* operand
)
{
if (!operand) return static_cast<U*>(0);
detail::variant::get_visitor<U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, typename T) >
inline U& get(
boost::variant< BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, T) >& operand
)
{
U* result = get<U>(&operand);
if (!result)
throw bad_get();
return *result;
}
template <typename U, BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, typename T) >
inline U& get(
const boost::variant< BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, T) >& operand
)
{
U* result = get<U>(&operand);
if (!result)
throw bad_get();
return *result;
}
} // namespace boost
#endif // BOOST_VARIANT_GET_HPP

View File

@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// boost visitor/static_visitor.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_STATIC_VISITOR_HPP
#define BOOST_STATIC_VISITOR_HPP
#include "boost/config.hpp"
#include "boost/type_traits/is_base_and_derived.hpp"
#include "boost/mpl/aux_/lambda_support.hpp" // used by is_static_visitor
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class template static_visitor
//
// An empty base class that typedefs the return type of a deriving static
// visitor. The class is analogous to std::unary_function in this role.
//
namespace detail {
struct is_static_visitor_tag { };
} // namespace detail
template <typename R = void>
struct static_visitor
: public detail::is_static_visitor_tag
{
typedef R result_type;
protected:
~static_visitor() { }
};
//////////////////////////////////////////////////////////////////////////
// metafunction is_static_visitor
//
// Value metafunction indicates whether the specified type is a static
// visitor of any types.
//
// NOTE: This template never needs to be specialized!
//
template <typename T>
struct is_static_visitor
{
typedef typename is_base_and_derived<
detail::is_static_visitor_tag
, T
>::type type;
BOOST_STATIC_CONSTANT(bool, value = type::value);
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_static_visitor,(T))
};
} // namespace boost
#endif // BOOST_STATIC_VISITOR_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
//-----------------------------------------------------------------------------
// boost variant/variant_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_VARIANT_FWD_HPP
#define BOOST_VARIANT_VARIANT_FWD_HPP
#include "boost/config.hpp"
#include "boost/preprocessor/enum_params_with_a_default.hpp"
#include "boost/preprocessor/enum_params_with_defaults.hpp"
#include "boost/mpl/limits/list.hpp"
#include "boost/mpl/void.hpp"
//////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_LIMIT_TYPES
//
// Implementation-defined preprocessor symbol describing the actual
// length of variant's pseudo-variadic template parameter list.
//
#define BOOST_VARIANT_LIMIT_TYPES \
BOOST_MPL_LIMIT_LIST_SIZE
namespace boost {
namespace detail { namespace variant {
//////////////////////////////////////////////////////////////////////////
// (detail) class void_ and class template convert_void
//
// Provides the mechanism by which void(NN) types are converted to
// mpl::void_ (and thus can be passed to mpl::list).
//
// Rationale: This is particularly needed for the using-declarations
// workaround (below), but also to avoid associating mpl namespace with
// variant in argument dependent lookups (which used to happen because of
// defaulting of template parameters to mpl::void_).
//
struct void_;
template <typename T>
struct convert_void
{
typedef T type;
};
template <>
struct convert_void< void_ >
{
typedef mpl::void_ type;
};
//////////////////////////////////////////////////////////////////////////
// (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE
//
// Needed to work around compilers that don't support using-declaration
// overloads. (See the variant::initializer workarounds below.)
//
#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES)
//
// Defines void types that are each unique and specializations of
// convert_void that yields mpl::void_ for each voidNN type.
//
#define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \
struct BOOST_PP_CAT(void,N); \
\
template <> \
struct convert_void< BOOST_PP_CAT(void,N) > \
{ \
typedef mpl::void_ type; \
}; \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_DETAIL_DEFINE_VOID_N
, _
)
#undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
}} // namespace detail::variant
//////////////////////////////////////////////////////////////////////////
// class template variant (concept inspired by Andrei Alexandrescu)
//
// Efficient, type-safe bounded discriminated union.
//
// Preconditions:
// - Each type must be unique.
// - No type may be const-qualified.
//
// Proper declaration form:
// variant<types> (where types is a type-sequence)
// or
// variant<T0,T1,...,Tn> (where T0 is NOT a type-sequence)
// or
// variant<>, which acts like variant<boost::empty>
//
template <
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
BOOST_VARIANT_LIMIT_TYPES
, typename T
, detail::variant::void_
)
#else// defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS(
BOOST_VARIANT_LIMIT_TYPES
, typename T
, detail::variant::void//NN
)
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
>
class variant;
} // namespace boost
#endif // BOOST_VARIANT_VARIANT_FWD_HPP

View File

@@ -0,0 +1,82 @@
//-----------------------------------------------------------------------------
// boost variant/visitor_ptr.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appears in all copies and
// that both the copyright notice and this permission notice appear in
// supporting documentation. No representations are made about the
// suitability of this software for any purpose. It is provided "as is"
// without express or implied warranty.
#ifndef BOOST_VARIANT_VISITOR_PTR_HPP
#define BOOST_VARIANT_VISITOR_PTR_HPP
#include "boost/variant/bad_visit.hpp"
#include "boost/variant/static_visitor.hpp"
#include "boost/type_traits/add_reference.hpp"
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template visitor_ptr
//
// Adapts a function pointer for use as visitor capable of handling
// values of a single type. Throws bad_visit if inappropriately applied.
//
template <typename T, typename R>
class visitor_ptr_t
: public static_visitor<R>
{
private: // representation
typedef R (*visitor_t)(T);
visitor_t visitor_;
public: // typedefs
typedef R result_type;
private: // private typedefs
typedef typename add_reference<T>::type
argument_fwd_type;
public: // structors
explicit visitor_ptr_t(visitor_t visitor)
: visitor_(visitor)
{
}
public: // static visitor interfaces
result_type operator()(argument_fwd_type operand) const
{
return visitor_(operand);
}
template <typename U>
result_type operator()(const U& operand) const
{
throw bad_visit();
}
};
template <typename R, typename T>
inline visitor_ptr_t<T,R> visitor_ptr(R (*visitor)(T))
{
return visitor_ptr_t<T,R>(visitor);
}
} // namespace boost
#endif// BOOST_VISITOR_VISITOR_PTR_HPP

8
index.html Normal file
View File

@@ -0,0 +1,8 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">
</head>
<body>
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
</body>
</html>

20
test/Jamfile Normal file
View File

@@ -0,0 +1,20 @@
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# Make tests run by default.
DEPENDS all : test ;
{
test-suite variant
:
[ run test1.cpp class_a.cpp ]
[ run test2.cpp ]
[ run test3.cpp ]
[ run test4.cpp class_a.cpp ]
[ run test5.cpp ]
[ run test6.cpp ]
[ run test7.cpp ]
[ run test8.cpp ]
;
}

55
test/class_a.cpp Normal file
View File

@@ -0,0 +1,55 @@
//File: class_a.cpp
#include <sstream>
#include <iostream>
#include <assert.h>
#include "class_a.h"
using namespace std;
class_a::~class_a()
{
assert(self_p_ == this);
}
class_a::class_a(int n)
{
n_ = n;
self_p_ = this;
}
class_a::class_a(const class_a& other)
{
n_ = other.n_;
self_p_ = this;
}
class_a& class_a::operator=(const class_a& rhs)
{
class_a temp(rhs);
swap(temp);
return *this;
}
void class_a::swap(class_a& other)
{
std::swap(n_, other.n_);
}
int class_a::get() const
{
return n_;
}
std::ostream& operator<<(std::ostream& strm, const class_a& a)
{
return strm << "class_a(" << a.get() << ")";
}

30
test/class_a.h Normal file
View File

@@ -0,0 +1,30 @@
//File: class_a.h
#ifndef _CLASSA_H_INC_
#define _CLASSA_H_INC_
#include <iosfwd>
struct class_a
{
~class_a();
class_a(int n = 5511);
class_a(const class_a& other);
class_a& operator=(const class_a& rhs);
void swap(class_a& other);
int get() const;
private:
int n_;
class_a* self_p_;
}; //Class_a
std::ostream& operator<<(std::ostream& strm, const class_a& a);
#endif //_CLASSA_H_INC_

310
test/jobs.h Normal file
View File

@@ -0,0 +1,310 @@
//File: jobs.h
#ifndef _JOBSH_INC_
#define _JOBSH_INC_
#include <vector>
#include <sstream>
#include <algorithm>
#include <typeinfo>
#include "boost/variant/get.hpp"
#include "boost/variant/apply_visitor.hpp"
#include "boost/variant/static_visitor.hpp"
#include "varout.h"
struct total_sizeof : boost::static_visitor<int>
{
total_sizeof() : total_(0) { }
template<class Value>
int operator()(const Value& value) const
{
total_ += sizeof(value);
return total_;
}
int result() const
{
return total_;
}
mutable int total_;
}; // total_sizeof
//Function object: sum_int
//Description: Compute total sum of a series of numbers, (when called successively)
//Use sizeof(T) if applied with a non-integral type
struct sum_int : boost::static_visitor<int>
{
sum_int() : total_(0) { }
template<int n>
struct int_to_type
{
BOOST_STATIC_CONSTANT(int, value = n);
};
//Integral type - add numerical value
template<typename T>
void add(T t, int_to_type<true> ) const
{
total_ += t;
}
//Other types - add sizeof<T>
template<typename T>
void add(T& , int_to_type<false> ) const
{
total_ += sizeof(T);
}
template<typename T>
int operator()(const T& t) const
{
//Int_to_type is used to select the correct add() overload
add(t, int_to_type<boost::is_integral<T>::value>());
return total_;
}
int result() const
{
return total_;
}
private:
mutable int total_;
}; //sum_int
//Function object: sum_double
//Description: Compute total sum of a series of numbers, (when called successively)
//Accpetable input types: float, double (Other types are silently ignored)
struct sum_double : boost::static_visitor<double>
{
sum_double() : total_(0) { }
void operator()(float value) const
{
total_ += value;
}
void operator()(double value) const
{
total_ += value;
}
template<typename T>
void operator()(const T&) const
{
//Do nothing
}
double result() const
{
return total_;
}
private:
mutable double total_;
}; //sum_double
struct int_printer : boost::static_visitor<std::string>
{
int_printer(std::string prefix_s = "") : prefix_s_(prefix_s) { }
int_printer(const int_printer& other) : prefix_s_(other.prefix_s_)
{
ost_ << other.str();
}
std::string operator()(int x) const
{
ost_ << prefix_s_ << x;
return str();
}
std::string operator()(const std::vector<int>& x) const
{
ost_ << prefix_s_;
//Use another Int_printer object for printing a list of all integers
int_printer job(",");
ost_ << std::for_each(x.begin(), x.end(), job).str();
return str();
}
std::string str() const
{
return ost_.str();
}
private:
std::string prefix_s_;
mutable std::ostringstream ost_;
}; //int_printer
struct int_adder : boost::static_visitor<void>
{
int_adder(int rhs) : rhs_(rhs) { }
void operator()(int& lhs) const
{
lhs += rhs_;
}
template<typename T>
void operator()(const T& ) const
{
//Do nothing
}
int rhs_;
}; //int_adder
struct held_type_name : boost::static_visitor<std::string>
{
template<typename T>
std::string operator()(const T& ) const
{
ost_ << '[' << typeid(T).name() << ']';
return result();
}
std::string result() const
{
return ost_.str();
}
mutable std::ostringstream ost_;
}; //held_type_name
template<typename T>
struct spec
{
typedef T result;
};
template<typename VariantType, typename S>
void verify(const VariantType& vari, spec<S>, std::string str = "")
{
using namespace boost;
BOOST_CHECK(apply_visitor(total_sizeof(), vari) == sizeof(S));
BOOST_CHECK(vari.type() == typeid(S));
VariantType& mut_vari = const_cast<VariantType&>(vari);
//
// Check get<>()
//
BOOST_CHECK(get<const S>(&vari));
BOOST_CHECK(get<S>(&mut_vari));
const S* ptr1 = 0;
const S* ptr2 = 0;
int count = 0;
try
{
const S& r = get<const S>(vari);
ptr1 = &r;
}
catch(bad_get& )
{
count += 1;
}
try
{
S& mut_r = get<S>(mut_vari);
ptr2 = &mut_r;
}
catch(bad_get& )
{
count += 1;
}
BOOST_CHECK(count == 0);
BOOST_CHECK(ptr1 != 0 && ptr2 == ptr1);
//
// Check string content
//
if(str.length() > 0)
{
std::string temp = apply_visitor(to_text(), vari);
std::cout << "temp = " << temp << ", str = " << str << std::endl;
BOOST_CHECK(temp == str);
}
}
template<typename VariantType, typename S>
void verify_not(const VariantType& vari, spec<S>)
{
using namespace boost;
BOOST_CHECK(vari.type() != typeid(S));
//
// Check get<>()
//
BOOST_CHECK(!get<const S>(&vari));
VariantType& mut_vari = const_cast<VariantType&>(vari);
BOOST_CHECK(!get<S>(&mut_vari));
const S* ptr1 = 0;
const S* ptr2 = 0;
int count = 0;
try
{
const S& r = get<const S>(vari);
ptr1 = &r;
}
catch(bad_get& )
{
count += 1;
}
try
{
S& mut_r = get<S>(mut_vari);
ptr2 = &mut_r;
}
catch(bad_get& )
{
count += 1;
}
BOOST_CHECK(count == 2);
BOOST_CHECK(ptr1 == 0 && ptr2 == 0);
}
#endif //_JOBSH_INC_

135
test/test1.cpp Normal file
View File

@@ -0,0 +1,135 @@
//File: test1.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "class_a.h"
#include "jobs.h"
#include "varout.h"
#include <iostream>
#include <string>
#include <vector>
void run()
{
using boost::apply_visitor;
using boost::variant;
using std::string;
using std::vector;
using std::cout;
using std::endl;
typedef variant< char*, string, short > t_var0;
typedef variant< int, string, double > t_var1;
typedef variant< short, const char* > t_var2;
typedef variant< string, char > t_var3;
typedef variant< unsigned short, const char* > t_var4;
typedef variant< unsigned short, const char*, t_var2 > t_var5;
typedef variant< unsigned short, const char*, t_var5 > t_var6;
typedef variant< class_a, const void* > t_var7;
typedef variant< t_var6, int > t_var8;
typedef variant< t_var8, unsigned short > t_var9;
typedef variant< char, unsigned char > t_var10;
typedef variant< short, int, vector<int>, long> t_var11;
t_var1 v1;
t_var0 v0;
t_var2 v2;
t_var3 v3;
t_var4 v4;
t_var5 v5;
t_var6 v6;
t_var7 v7;
t_var8 v8;
t_var9 v9;
t_var10 v10;
t_var11 v11;
//
// Check assignment rules
//
v2 = 4;
v4 = v2;
verify(v4, spec<unsigned short>());
v2 = "abc";
v4 = v2;
verify(v4, spec<const char*>(), "[V] abc");
v5 = "def";
verify(v5, spec<const char*>(), "[V] def");
v5 = v2;
verify(v5, spec<t_var2>(), "[V] [V] abc");
v6 = 58;
verify(v6, spec<unsigned short>(), "[V] 58");
v6 = v5;
verify(v6, spec<t_var5>(), "[V] [V] [V] abc");
v8 = v2;
verify(v8, spec<t_var6>(), "[V] [V] abc");
v8 = v6;
verify(v8, spec<t_var6>(), "[V] [V] [V] [V] abc");
v7 = v2;
verify(v7, spec<const void*>());
v7 = 199;
verify(v7, spec<class_a>(), "[V] class_a(199)");
v2 = 200;
v7 = v2;
verify(v7, spec<class_a>(), "[V] class_a(200)");
//
// Check sizes of held values
//
total_sizeof ts;
v1 = 5.9;
apply_visitor(ts, v1);
v1 = 'B';
apply_visitor(ts, v1);
v1 = 3.4f;
apply_visitor(ts, v1);
BOOST_TEST(ts.result() == sizeof(int) + sizeof(double)*2);
v11 = 5;
string res_s = apply_visitor(int_printer(), v11);
BOOST_TEST(res_s == "5");
//
// A variant object holding an std::vector
//
vector<int> int_vec_1;
int_vec_1.push_back(512);
int_vec_1.push_back(256);
int_vec_1.push_back(128);
int_vec_1.push_back(64);
v11 = int_vec_1;
res_s = apply_visitor(int_printer(), v11);
BOOST_TEST(res_s == ",512,256,128,64");
}
int test_main(int , char* [])
{
run();
return 0;
}

129
test/test2.cpp Normal file
View File

@@ -0,0 +1,129 @@
// File: test2.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include "varout.h"
#include <cassert>
#include <iostream>
#include <algorithm>
using boost::apply_visitor;
struct short_string
{
BOOST_STATIC_CONSTANT(size_t, e_limit = 101);
short_string() : len_(0)
{
buffer_[0] = '\0';
}
short_string(const char* src)
{
size_t src_len = strlen(src);
len_ = std::min(src_len, e_limit-1);
std::copy(src, src + len_, buffer_);
buffer_[len_] = '\0';
}
short_string(const short_string& other) : len_(other.len_)
{
std::copy(other.buffer_, other.buffer_ + e_limit, buffer_);
}
void swap(short_string& other)
{
char temp[e_limit];
std::copy(buffer_, buffer_ + e_limit, temp);
std::copy(other.buffer_, other.buffer_ + e_limit, buffer_);
std::copy(temp, temp + e_limit, other.buffer_);
std::swap(len_, other.len_);
}
short_string& operator=(const short_string& rhs)
{
short_string temp(rhs);
swap(temp);
return *this;
}
operator const char*() const
{
return buffer_;
}
private:
char buffer_[e_limit];
size_t len_;
}; //short_string
std::ostream& operator<<(std::ostream& out, const short_string& s)
{
out << static_cast<const char*>(s);
return out;
}
void run()
{
using boost::variant;
variant<short, short_string> v0;
variant<char, const char*> v1;
variant<short_string, char > v2;
//
// Default construction
//
verify(v0, spec<short>());
verify(v1, spec<char>());
verify(v2, spec<short_string>());
//
// Implicit conversion to bounded type
//
v1 = "I am v1";
verify(v1, spec<const char*>(), "[V] I am v1");
v2 = "I am v2";
verify(v2, spec<short_string>(), "[V] I am v2");
//
// Variant-to-variant assignment
//
v0 = v1;
verify(v0, spec<short_string>(), "[V] I am v1");
v1 = v0;
verify(v1, spec<const char*>(), "[V] I am v1");
const int n0 = 88;
v1 = n0;
v0 = v1;
//
// Implicit conversion to bounded type
//
verify(v0, spec<short>(), "[V] 88");
verify(v1, spec<char>(), "[V] X");
}
int test_main(int , char* [])
{
run();
return 0;
}

144
test/test3.cpp Normal file
View File

@@ -0,0 +1,144 @@
// File: test3.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "boost/incomplete.hpp"
#include <iostream>
#include <sstream>
#include <string>
/////////////////////////////////////////////////////////////////////
using boost::variant;
using boost::incomplete;
using std::cout;
using std::endl;
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
struct Add;
struct Sub;
typedef variant<int, incomplete<Add>, incomplete<Sub> > Expr;
struct Sub
{
Sub();
Sub(const Expr& l, const Expr& r);
Sub(const Sub& other);
Expr lhs_;
Expr rhs_;
};
struct Add
{
Add() { }
Add(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { }
Add(const Add& other) : lhs_(other.lhs_), rhs_(other.rhs_) { }
Expr lhs_;
Expr rhs_;
};
Sub::Sub() { }
Sub::Sub(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { }
Sub::Sub(const Sub& other) : lhs_(other.lhs_), rhs_(other.rhs_) { }
//
// insert-to operators
//
std::ostream& operator<<(std::ostream& out, const Expr& a);
std::ostream& operator<<(std::ostream& out, const Add& a)
{
out << '(' << a.lhs_ << '+' << a.rhs_ << ')';
return out;
}
std::ostream& operator<<(std::ostream& out, const Sub& a)
{
out << '(' << a.lhs_ << '-' << a.rhs_ << ')';
return out;
}
struct raw_text_maker : boost::static_visitor<std::string>
{
template<typename T>
std::string operator()(const T& t) const
{
std::ostringstream ost;
ost << t;
return ost.str();
}
};
std::ostream& operator<<(std::ostream& out, const Expr& a)
{
std::string temp = boost::apply_visitor(raw_text_maker(), a);
out << temp;
return out;
}
//
// Expression evaluation visitor
//
struct Calculator : boost::static_visitor<int>
{
Calculator() { }
int operator()(Add& x) const
{
Calculator calc;
int n1 = boost::apply_visitor(calc, x.lhs_);
int n2 = boost::apply_visitor(calc, x.rhs_);
return n1 + n2;
}
int operator()(Sub& x) const
{
return boost::apply_visitor(Calculator(), x.lhs_)
- boost::apply_visitor(Calculator(), x.rhs_);
}
int operator()(Expr& x) const
{
Calculator calc;
return boost::apply_visitor(calc, x);
}
int operator()(int x) const
{
return x;
}
}; // Calculator
/////////////////////////////////////////////////////////////////////
int test_main(int, char* [])
{
int n = 13;
Expr e1( Add(n, Sub(Add(40,2),Add(10,4))) ); //n + (40+2)-(10+14) = n+28
BOOST_CHECK(e1.type() == typeid(Add));
BOOST_CHECK(boost::apply_visitor(raw_text_maker(), e1) ==
"(13+((40+2)-(10+4)))");
//Evaluate expression
int res = boost::apply_visitor(Calculator(), e1);
BOOST_CHECK(res == n + 28);
return 0;
}

46
test/test4.cpp Normal file
View File

@@ -0,0 +1,46 @@
// File: test4.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "boost/incomplete.hpp"
#include "varout.h"
#include "jobs.h"
#include <string>
struct class_a;
using boost::incomplete;
using boost::variant;
typedef variant<std::string, incomplete<class_a>, float> var_type_1;
typedef variant<std::string, incomplete<class_a>, short> var_type_2;
#include "class_a.h"
int test_main(int , char* [])
{
using namespace boost;
var_type_1 v1;
var_type_2 v2;
v1 = class_a();
verify(v1, spec<class_a>(), "[V] class_a(5511)");
verify(v2, spec<std::string>(), "[V] ");
v2 = "abcde";
verify(v2, spec<std::string>(), "[V] abcde");
v2 = v1;
verify(v2, spec<class_a>(), "[V] class_a(5511)");
v2 = 5;
v1 = v2;
return 0;
}

83
test/test5.cpp Normal file
View File

@@ -0,0 +1,83 @@
// File: test5.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include "varout.h"
#include <assert.h>
#include <iostream>
#include <string>
#include <vector>
void run()
{
using std::string;
using boost::variant;
using boost::apply_visitor;
typedef variant<int, float, unsigned short, unsigned char> t_var1;
typedef variant<int, t_var1, unsigned short, unsigned char> t_var2;
typedef variant<string, int, t_var2> t_var3;
t_var1 v1;
t_var2 v2;
t_var2 v2_second;
t_var3 v3;
const char c0 = 'x';
v1 = c0;
//v2 and v3 are holding (aka: containing) a variant
v2 = v1;
v3 = v2;
verify(v1, spec<int>());
verify(v2, spec<t_var1>());
verify(v3, spec<t_var2>());
//
// assignment from const char (Converted to int)
//
v2 = c0;
v3 = c0;
verify(v2, spec<int>());
verify(v3, spec<int>());
BOOST_TEST(apply_visitor(sum_int(), v2) == c0);
BOOST_TEST(apply_visitor(sum_int(), v3) == c0);
sum_int adder;
apply_visitor(adder, v2);
apply_visitor(adder, v3);
BOOST_TEST(adder.result() == 2*c0);
//
// A variant holding a variant
//
typedef variant<unsigned char, float> t_var4;
typedef variant<string, t_var4> t_var5;
t_var4 v4;
t_var5 v5;
v5 = 22.5f;
verify(v5, spec<t_var4>(), "[V] [V] 22.5");
}
int test_main(int , char* [])
{
run();
return 0;
}

66
test/test6.cpp Normal file
View File

@@ -0,0 +1,66 @@
// File: test6.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include <iostream>
#include "jobs.h"
#include "varout.h"
//Just Another Class
struct jac
{
jac() { }
jac(int ) { }
jac(const char* ) { }
}; //jac
std::ostream& operator<<(std::ostream& out, const jac& )
{
out << "jac ";
return out;
};
void run()
{
using boost::variant;
variant<jac, int, double*, const double*> v1;
variant<int, char, double*, const double*, char*> v2;
v1 = v2;
verify(v1, spec<int>());
verify(v2, spec<int>());
verify_not(v1, spec<jac>());
verify_not(v1, spec<double*>());
verify_not(v1, spec<const double*>());
verify_not(v2, spec<char>());
verify_not(v2, spec<double*>());
verify_not(v2, spec<const double*>());
verify_not(v2, spec<char*>());
variant<jac, const double*> v3;
variant<int, unsigned char, double*> v4;
v3 = v4;
verify(v3, spec<jac>());
verify(v4, spec<int>());
verify_not(v4, spec<unsigned char>());
}
int test_main(int , char* [])
{
run();
return 0;
}

202
test/test7.cpp Normal file
View File

@@ -0,0 +1,202 @@
// File: test7.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include "varout.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
using namespace boost;
using namespace std;
struct jas
{
jas(int n = 364);
jas(const jas& other);
~jas();
jas& operator=(const jas& other);
void swap(jas& other);
int n_;
int sn_;
static int s_inst_id_;
};
struct Tracker
{
typedef map<const jas*,int> table_type;
typedef table_type::iterator iterator_type;
static table_type s_this_to_sn_;
static void insert(const jas& j)
{
s_this_to_sn_[&j] = j.sn_;
cout << "jas( " << j.sn_ << ") Registered" << endl;
}
static void remove(const jas& j)
{
iterator_type iter = s_this_to_sn_.find(&j);
BOOST_CHECK(iter != s_this_to_sn_.end());
BOOST_CHECK( ((*iter).second) == j.sn_);
int sn = (*iter).second;
if(sn != j.sn_)
{
cout << "Mismatch: this = " << (*iter).first << ", sn_ = " << sn
<< ", other: this = " << &j << ", j.sn_ = " << j.sn_ << endl;
}
BOOST_CHECK(sn == j.sn_);
s_this_to_sn_.erase(&j);
cout << "jas( " << j.sn_ << ") Removed" << endl;
}
static void check()
{
BOOST_CHECK(s_this_to_sn_.empty());
}
};
Tracker::table_type Tracker::s_this_to_sn_;
jas::jas(int n) : n_(n)
{
sn_ = s_inst_id_;
s_inst_id_ += 1;
Tracker::insert(*this);
}
jas::jas(const jas& other) : n_(other.n_)
{
sn_ = s_inst_id_;
s_inst_id_ += 1;
Tracker::insert(*this);
}
jas::~jas()
{
Tracker::remove(*this);
}
jas& jas::operator=(const jas& other)
{
jas temp(other);
swap(temp);
return *this;
}
void jas::swap(jas& other)
{
Tracker::remove(*this);
Tracker::remove(other);
std::swap(n_, other.n_);
std::swap(sn_, other.sn_);
Tracker::insert(*this);
Tracker::insert(other);
}
int jas::s_inst_id_ = 0;
bool operator==(const jas& a, const jas& b)
{
return a.n_ == b.n_;
}
ostream& operator<<(ostream& out, const jas& a)
{
cout << "jas::n_ = " << a.n_;
return out;
}
template<typename ValueType>
struct compare_helper : boost::static_visitor<bool>
{
compare_helper(ValueType& expected) : expected_(expected) { }
bool operator()(const ValueType& value)
{
return value == expected_;
}
template<typename T>
bool operator()(const T& )
{
return false;
}
ValueType& expected_;
};
template<typename VariantType, typename ExpectedType>
void var_compare(const VariantType& v, ExpectedType expected)
{
compare_helper<ExpectedType> ch(expected);
bool checks = boost::apply_visitor(ch, v);
BOOST_CHECK(checks);
}
void run()
{
variant<string, short> v0;
var_compare(v0, string(""));
v0 = 8;
var_compare(v0, static_cast<short>(8));
v0 = "penny lane";
var_compare(v0, string("penny lane"));
variant<jas, string, int> v1, v2 = jas(195);
var_compare(v1, jas(364));
v1 = jas(500);
v1.swap(v2);
var_compare(v1, jas(195));
var_compare(v2, jas(500));
variant<string, int> v3;
var_compare(v3, string(""));
}
int test_main(int , char* [])
{
run();
Tracker::check();
return 0;
}

101
test/test8.cpp Normal file
View File

@@ -0,0 +1,101 @@
// File: test8.cpp
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
using namespace boost;
typedef variant<float, std::string, int, std::vector<std::string> > t_var1;
struct int_sum : static_visitor<void>
{
int_sum() : result_(0) { }
void operator()(int t)
{
result_ += t;
}
void operator()(float ) { }
void operator()(const std::string& ) { }
void operator()(const std::vector<std::string>& ) { }
int result_;
};
template <typename T, typename Variant>
T& check_pass(Variant& v, T value)
{
BOOST_CHECK(get<T>(&v));
try
{
T& r = get<T>(v);
BOOST_CHECK(r == value);
return r;
}
catch(boost::bad_get&)
{
throw; // must never reach
}
}
template <typename T, typename Variant>
void check_fail(Variant& v)
{
BOOST_CHECK(!get<T>(&v));
try
{
T& r = get<T>(v);
BOOST_CHECK(false && &r); // should never reach
}
catch(boost::bad_get&)
{
// (do nothing here)
}
}
int test_main(int , char* [])
{
int_sum acc;
t_var1 v1 = 800;
// check get on non-const variant
{
int& r1 = check_pass<int>(v1, 800);
check_fail<const int>(v1);
check_fail<float>(v1);
check_fail<const float>(v1);
check_fail<short>(v1);
check_fail<const short>(v1);
apply_visitor(acc, v1);
BOOST_CHECK(acc.result_ == 800);
r1 = 920; // NOTE: modifies content of v1
apply_visitor(acc, v1);
BOOST_CHECK(acc.result_ == 800 + 920);
}
// check const correctness:
{
const t_var1& c = v1;
check_pass<const int>(c, 920);
check_fail<int>(c);
check_fail<const float>(c);
check_fail<float>(c);
check_fail<const short>(c);
check_fail<short>(c);
}
return boost::exit_success;
}

36
test/varout.h Normal file
View File

@@ -0,0 +1,36 @@
//File: varout.h
#ifndef _VAROUTH_INC_
#define _VAROUTH_INC_
#include <sstream>
#include <string>
#include <iostream>
struct to_text : boost::static_visitor<std::string>
{
template<class Value>
std::string operator()(const Value& value) const
{
std::ostringstream ost;
ost << "[V] " << value;
return ost.str();
}
}; //to_text
template<typename T0, typename T1, typename T2, typename T3>
std::ostream& operator<<(std::ostream& out,
const boost::variant<T0, T1, T2, T3>& a)
{
out << boost::apply_visitor(to_text(), a);
return out;
}
#endif //_VAROUTH_INC_