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:
96
.gitattributes
vendored
Normal file
96
.gitattributes
vendored
Normal 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
81
doc/credits.html
Normal 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. "<a href="http://www.oonumerics.org/tmpw01/alexandrescu.pdf">An Implementation of Discriminated Unions in C++</a>." <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. "Generic<Programming>:
|
||||
Discriminated Unions" <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. "<a href="http://lists.boost.org/MailArchives/boost/msg30415.php">Proposal
|
||||
--- A type-safe union</a>." Boost public discussion. 2002.</p>
|
||||
<p>[<a name="bib-fri02">Fri02</a>] Eric Friedman. "<a href="http://groups.yahoo.com/group/boost/files/variant-20020701.zip">Variant
|
||||
(aka Discriminated Union)</a>." Early implementation. 2002.</p>
|
||||
<p>[<a name="bib-gre02">Gre02</a>] Doug Gregor. "<a HREF="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?variant">BOOST_USER:
|
||||
variant</a>." 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 "as is" without express or implied warranty.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
117
doc/index.html
Normal file
117
doc/index.html
Normal 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 "boost/variant.hpp"
|
||||
<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 "boost/apply_visitor.hpp": <a href="reference.html#Visitation"><code>apply_visitor</code></a></li>
|
||||
<li>
|
||||
Header "boost/static_visitor.hpp": <a href="reference.html#StaticVisitor"><code>static_visitor</code></a></li>
|
||||
<li>
|
||||
Header "boost/extract.hpp": <a href="reference.html#ValueExtraction"><code>extract</code></a></li>
|
||||
<li>
|
||||
Header "boost/incomplete.hpp": <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 "as is" without express or implied
|
||||
warranty.</p>
|
||||
</body>
|
||||
</html>
|
||||
102
doc/misc.html
Normal file
102
doc/misc.html
Normal 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>© 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 "as is" without express or implied warranty.</p>
|
||||
118
doc/overview.html
Normal file
118
doc/overview.html
Normal 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 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>." 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, C++ features 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, 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>] 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 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>© 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 "as is" without express or implied
|
||||
warranty.</p>
|
||||
478
doc/reference.html
Normal file
478
doc/reference.html
Normal 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 "boost/variant.hpp"<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 "boost/apply_visitor.hpp": <a href="#Visitation"><code>apply_visitor</code></a></li>
|
||||
<li>
|
||||
Header "boost/static_visitor.hpp": <a href="#StaticVisitor"><code>static_visitor</code></a></li>
|
||||
<li>
|
||||
Header "boost/extract.hpp": <a href="#ValueExtraction"><code>extract</code></a></li>
|
||||
<li>
|
||||
Header "boost/incomplete.hpp": <a href="#incomplete"><code>incomplete</code></a></li>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2>Header <code>"boost/variant.hpp"</code></h2>
|
||||
<h3><a name="Synopsis">Synopsis</a></h3>
|
||||
<p>Dependencies and library features defined in <code><a href="../../../../../../../boost/variant.hpp">
|
||||
"</a></code><a href="../../../../../../../boost/variant.hpp"><code>boost/variant.hpp"</code></a>:
|
||||
</p>
|
||||
<pre>#include <typeinfo>
|
||||
|
||||
#define <a href="#BOOST_VARIANT_LIMIT_TYPES">BOOST_VARIANT_LIMIT_TYPES</a> <i>implementation-defined</i>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template
|
||||
<
|
||||
typename T1,
|
||||
typename T2,
|
||||
...
|
||||
typename T<i>n</i> = <em>implementation-defined</em>
|
||||
>
|
||||
class <a href="#variant">variant</a>;
|
||||
|
||||
template <typename T1, typename T2, ... , typename T<i>n</i>>
|
||||
void swap(
|
||||
variant<T1, T2, ... , T<i>n</i>> &
|
||||
, variant<T1, T2, ... , T<i>n</i>> &
|
||||
);
|
||||
}
|
||||
</pre>
|
||||
<p>Test harnesses provided in <code>"libs/variant/test"</code> directory.</p>
|
||||
<p></p>
|
||||
<hr>
|
||||
<h2><a name="BoundedType"><i>BoundedType</i> Concept</a></h2>
|
||||
<p>Given <a href="#variant"><code>variant</code></a><code><T1, T2, ... , T<i>n</i>></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<T></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 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><T1, T2, ... , T<i>n</i>></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<int, std::string></code>, or implicitly: <code>
|
||||
variant<short, std::string></code>, etc.):</p>
|
||||
<pre>class my_visitor
|
||||
{
|
||||
typedef int result_type;
|
||||
|
||||
int operator()(int i)
|
||||
{
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
int operator()(std::string& 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 <typename T>
|
||||
void operator()(const T& t)
|
||||
{
|
||||
std::cout << t << '\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 >= 10</code>
|
||||
must evaluate true.</p>
|
||||
<hr>
|
||||
<h2><a name="variant"><code>variant</code></a></h2>
|
||||
<pre>template
|
||||
<
|
||||
typename T1,
|
||||
typename T2,
|
||||
...
|
||||
typename T<i>n</i> = <em>implementation-defined</em>
|
||||
>
|
||||
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 &);
|
||||
template <typename OperandType>
|
||||
<a href="#variant-template-ctor">variant</a>(const OperandType &);
|
||||
<a href="#dtor">~variant</a>();
|
||||
|
||||
public: // <i><a href="#variant-modifiers">modifiers</a></i>
|
||||
|
||||
variant & <a href="#variant-swap">swap</a>(variant &);
|
||||
variant & <a href="#variant-copy-assign">operator=</a>(const variant &);
|
||||
template <typename OperandType>
|
||||
variant & <a href="#variant-template-assign">operator=</a>(const OperandType &);
|
||||
|
||||
public: // <i><a href="#variant-queries">queries</a></i>
|
||||
|
||||
int <a href="#variant-which">which</a>() const;
|
||||
const std::type_info & <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 <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& 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 <typename OperandType>
|
||||
<a name="variant-template-ctor">variant</a>(const OperandType & 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& 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->type()
|
||||
== other.type()</code>.<br>
|
||||
</p>
|
||||
<pre>variant& <a name="variant-copy-assign">operator=</a>(const variant& 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<class OperandType>
|
||||
variant& operator=(const OperandType &);
|
||||
</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 & 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<typename VisitorType, typename VariantType>
|
||||
typename VisitorType::result_type apply_visitor(VisitorType& visitor,
|
||||
VariantType& var_inst);
|
||||
|
||||
// Unary form
|
||||
template<class VisitorType>
|
||||
boost::apply_visitor_t<VisitorType> apply_visitor(VisitorType& visitor);
|
||||
|
||||
template <typename VisitorType>
|
||||
class apply_visitor_t
|
||||
{
|
||||
public:
|
||||
typedef typename VisitorType::result_type result_type;
|
||||
|
||||
template <typename VariantType>
|
||||
result_type operator()(VariantType& 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<typename R = void>
|
||||
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 <typename ToType>
|
||||
struct extract
|
||||
{
|
||||
public: // typedefs
|
||||
|
||||
typedef ToType& result_type;
|
||||
|
||||
public: // structors
|
||||
|
||||
template <typename VariantType>
|
||||
extract(VariantType &);
|
||||
template <typename VariantType>
|
||||
extract(const VariantType &);
|
||||
|
||||
public: // queries
|
||||
|
||||
bool check() const;
|
||||
ToType& operator()() const;
|
||||
operator ToType&() 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<RR>(var_inst)();</code> Initializes a temporary <code>extract</code>object
|
||||
and converts it to <code>RR&</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<RR> 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<VariantType>
|
||||
extract(const VariantType& from);
|
||||
|
||||
template<VariantType>
|
||||
extract(VariantType& 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&</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<T></code> is a template class, which allows a <code>variant</code>
|
||||
type to be instantiated with incomplete types.<br>
|
||||
By specifying <code>incomplete<T></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<></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<></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
|
||||
<
|
||||
int,
|
||||
incomplete<non_leaf_node> // non_leaf_node is incomplete at
|
||||
// this point so it must be wrapperd
|
||||
// by incomplete<>
|
||||
> tree_node;
|
||||
|
||||
struct non_leaf_node
|
||||
{
|
||||
non_leaf_node(const non_leaf_node& 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 "as is" without express or implied
|
||||
warranty.</p>
|
||||
</body>
|
||||
</html>
|
||||
335
doc/sample.html
Normal file
335
doc/sample.html
Normal 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: "<code>boost::apply_visitor(visitor,
|
||||
variant);</code>" 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 "visited"
|
||||
values, and - therefore - at the bottom of <code>main()</code>, its value is: 5
|
||||
+ 16 + 3.11 + 15.3 = 39.41.</p>
|
||||
<pre>#include <iostream>
|
||||
|
||||
#include "boost/variant.hpp"
|
||||
#include "boost/apply_visitor.hpp"
|
||||
#include "boost/static_visitor.hpp"
|
||||
|
||||
struct double_sum : boost::static_visitor<double>
|
||||
{
|
||||
double_sum() : total_(0.0) { }
|
||||
|
||||
template<class X>
|
||||
double operator()(X x)
|
||||
{
|
||||
total_ += x;
|
||||
return total_;
|
||||
}
|
||||
|
||||
double total_;
|
||||
};
|
||||
|
||||
int main(int, char* [] )
|
||||
{
|
||||
double_sum ds;
|
||||
boost::variant<short, int, float, double> 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: "Total = 39.41"
|
||||
std::cout << "Total = " << total << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<hr>
|
||||
<h2><a name="tree">A binary tree implementation</a></h2>
|
||||
<p>This sample program shows how <code>incomplete<T></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 <iostream>
|
||||
|
||||
#include "boost/variant.hpp"
|
||||
#include "boost/apply_visitor.hpp"
|
||||
#include "boost/static_visitor.hpp"
|
||||
#include "boost/incomplete.hpp"
|
||||
|
||||
|
||||
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<int, incomplete<non_leaf_node> > tree_node;
|
||||
|
||||
struct non_leaf_node
|
||||
{
|
||||
non_leaf_node(const tree_node& l, int num, const tree_node& r)
|
||||
: left_(l), right_(r), num_(num) { }
|
||||
non_leaf_node(const non_leaf_node& other)
|
||||
: left_(other.left_), right_(other.right_), num_(other.num_) { }
|
||||
|
||||
int num_;
|
||||
tree_node left_;
|
||||
tree_node right_;
|
||||
};
|
||||
|
||||
|
||||
struct tree_printer : boost::static_visitor<void>
|
||||
{
|
||||
void operator()(int n) const
|
||||
{
|
||||
cout << n << ' ';
|
||||
}
|
||||
|
||||
void operator()(const non_leaf_node& node) const
|
||||
{
|
||||
boost::apply_visitor(*this, node.left_);
|
||||
cout << node.num_ << ' ';
|
||||
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 <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
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<star*>(so_p))
|
||||
total_ += so_p->weight();
|
||||
}
|
||||
|
||||
int total_;
|
||||
};
|
||||
|
||||
int main(int, char* [] )
|
||||
{
|
||||
typedef std::vector<space_object*> 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 << "Total weight of all stars = " << total
|
||||
<< 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<> 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 <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "boost/variant.hpp"
|
||||
#include "boost/apply_visitor.hpp"
|
||||
#include "boost/static_visitor.hpp"
|
||||
|
||||
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<void>
|
||||
{
|
||||
total_weight() : total_(0) { }
|
||||
|
||||
void operator()(const star& a_star)
|
||||
{
|
||||
total_ += a_star.weight();
|
||||
}
|
||||
|
||||
//space_ship objects are ignored:
|
||||
void operator()(const space_ship& ) { }
|
||||
|
||||
int total_;
|
||||
};
|
||||
|
||||
int main(int, char* [] )
|
||||
{
|
||||
typedef boost::variant<star, space_ship> space_var;
|
||||
typedef std::vector<space_var> 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 << "Total weight of all stars = " << tw_job.total_
|
||||
<< 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<></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 "as is" without express or implied warranty.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
4
doc/styles.css
Normal file
4
doc/styles.css
Normal file
@@ -0,0 +1,4 @@
|
||||
PRE
|
||||
{
|
||||
BACKGROUND-COLOR: lightcyan
|
||||
}
|
||||
499
doc/tutorial.html
Normal file
499
doc/tutorial.html
Normal 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 < i -> char*
|
||||
1000 < i <= 2000 -> std::string
|
||||
<i>else </i> -> 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 "adapter" 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< std::string,
|
||||
char*, int ></code> from the factory function, the resultant code is clear and
|
||||
straight-forward: </p>
|
||||
<pre>#include <iostream>
|
||||
#include <string>
|
||||
#include "boost/variant.hpp"
|
||||
#include "boost/apply_visitor.hpp"
|
||||
|
||||
using std::string;
|
||||
using boost::variant;
|
||||
|
||||
typedef variant<string, char*, int> create_result;
|
||||
|
||||
//
|
||||
// <i>create</i>, our factory function
|
||||
//
|
||||
create_result create(int i)
|
||||
{
|
||||
// Return char* if (i > 2000):
|
||||
if (which > 2000) return "JKLM";
|
||||
|
||||
// Return std::string if (1000 < i <= 2000):
|
||||
if (which > 1000) return string("QRST");
|
||||
|
||||
// Otherwise, return int:
|
||||
return 15;
|
||||
}
|
||||
|
||||
//
|
||||
// <i>printer</i>, a visitor that prints to std::cout
|
||||
//
|
||||
struct printer : boost::static_visitor<>
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(const T& t)
|
||||
{
|
||||
std::cout << "operand: " << t << 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: "operand: JKLM"
|
||||
|
||||
// Now, create a std::string and print it:
|
||||
result = create(1500);
|
||||
boost::apply_visitor(a_printer, inst); // Output: "operand: QRST"
|
||||
|
||||
// Finally, create an int and print it:
|
||||
result = create(5);
|
||||
boost::apply_visitor(a_printer, inst); // Output: "15"
|
||||
|
||||
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<T1, T2, ... TN> 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<int, char, double> v1; // OK
|
||||
|
||||
variant<int, char, double, char> v2; // Error: char appears twice
|
||||
variant<float> v3; // Error: At least two types must be specified
|
||||
variant<char, char* const, void*> v4; // Error: top-level const types are illegal
|
||||
|
||||
variant<char, const char*, void*> 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<></code> wrapper, as shown below:<br>
|
||||
</p>
|
||||
<pre> struct jas1; // Forward declaration of jas1 (Just Another Struct)
|
||||
|
||||
variant<jas1, double, std::string> v6; // Error: jas1 is incomplete
|
||||
struct jas1 { ... };
|
||||
|
||||
struct jas2; // Forward declaration of jas2
|
||||
variant<incomplete<jas2>, double, std::string> v7; // OK -
|
||||
// incomplete<> 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<int, char, double> v1;
|
||||
v1 = 5.9; // double -> double (no conversion is needed)
|
||||
v1 = 3; // int -> int - " -
|
||||
v1 = 'x'; // char -> char - " -
|
||||
|
||||
v1 = short(5); // short -> int
|
||||
v1 = 5.9f; // float -> double
|
||||
v1 = static_cast<unsigned char>('x'); // unsigned char -> int
|
||||
|
||||
|
||||
v1 = string("abc"); // Error! no implicit conversion from
|
||||
// string to int/char/double
|
||||
|
||||
v1 = static_cast<long double>(4.0); // Error! (ambiguity):
|
||||
// long double -> double conversion
|
||||
// clashes with long double -> int conversion
|
||||
|
||||
|
||||
variant<std::string, double, int> 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<class1, double> v3;
|
||||
v3 = 5; // int -> double
|
||||
v3 = class1("abc"); // class1 -> class1
|
||||
v3 = "abc"; // const char* -> class1
|
||||
|
||||
variant<class1, class2> v4;
|
||||
v4 = class1("text1"); // class1 -> class1
|
||||
v4 = class2("text2"); // class2 -> class2
|
||||
v4 = "text3"; // 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<int, char, double> 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 -> int, hence: v1 = int(5)
|
||||
v2 = v1; // v2 = int(5)
|
||||
|
||||
v1 = 5.7f; // float -> 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<RR, SS, TT, .. > rhs_type;
|
||||
rhs_type src;
|
||||
|
||||
typedef variant<XX, YY, ZZ, .. > 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<int, std::string> variant_type;
|
||||
variant_type a;
|
||||
|
||||
variant<int, double, std::string> b;
|
||||
variant<variant_type, int, double, std::string> c;
|
||||
|
||||
a = "hello"; // char* converted to std::string
|
||||
|
||||
b = a; // b <- value of a, so b holds an std::string (Case 1)
|
||||
|
||||
c = a; // c <- 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<int, std::string> a;
|
||||
variant<int, const char*> b;
|
||||
|
||||
a = b; // OK: int->int or const char* -> 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<XX, YY, ZZ, ... > 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 "Char
|
||||
value: 'x'" and "Int value: 77" 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 << "Int value: " << x << std::endl;
|
||||
}
|
||||
|
||||
// Handle char values
|
||||
void operator()(float x) const
|
||||
{
|
||||
std::cout << "Float value: " << x << std::endl;
|
||||
}
|
||||
};
|
||||
.
|
||||
.
|
||||
variant<int, float> var = 53.22f;
|
||||
|
||||
//Apply print_int_char_visitor to var.
|
||||
apply_visitor(print_int_float_visitor(), var); // Output: "Float value: 53.22"
|
||||
|
||||
var = 77;
|
||||
apply_visitor(print_int_float_visitor(), var); // Output: "Int value: 77"
|
||||
</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<T></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<int> // Return type is int,
|
||||
// so derive from static_visitor<int>
|
||||
{
|
||||
template<typename T>
|
||||
int operator()(T t) const
|
||||
{
|
||||
return int(2 * t);
|
||||
}
|
||||
};
|
||||
.
|
||||
.
|
||||
variant<int, short, char> a = 9;
|
||||
int result = apply_visitor(multiply_by_two(), a);
|
||||
std::cout << "Result = " << result << std::endl; //Output: "Result = 18"
|
||||
</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<void>
|
||||
{
|
||||
// Handler *A*
|
||||
void operator()(int f) const
|
||||
{
|
||||
std::cout << "Int value: " << f << std::endl;
|
||||
}
|
||||
|
||||
// Handler *B*
|
||||
void operator()(char c) const
|
||||
{
|
||||
std::cout << "Char value: '" << c << '\''
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
.
|
||||
.
|
||||
variant<short, char> a = static_cast<short>(88);
|
||||
apply_visitor(print_int_char(), a); // Output: "Int value: 88.0"
|
||||
// (int value intercepted by handler *A*)
|
||||
|
||||
a = 'x'; // a = 'x'
|
||||
apply_visitor(print_int_char(), a); // Output: "Char value: 'x'"
|
||||
|
||||
variant<int, char, void*> b = 88; // b = int(88)
|
||||
apply_visitor(print_int_char(), b); // Error! -
|
||||
// void* cannot be handled by neither
|
||||
// handler (*A* or *B*)
|
||||
</pre>
|
||||
<p>"Catch-all" behavior can be achieved by supplying a templated form of <code>
|
||||
operator(): </code></p>
|
||||
<pre> struct ignore_non_ints_visitor : boost::static_visitor<void>
|
||||
{
|
||||
void operator()(int t) const
|
||||
{
|
||||
std::cout << "Current value: " << t << std::endl;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& t) const
|
||||
{
|
||||
// Catch all other types:
|
||||
std::cout << "Ignore me" << std::endl;
|
||||
}
|
||||
};
|
||||
.
|
||||
.
|
||||
variant<int, double, std::string> a = "abcde";
|
||||
apply_visitor(ignore_non_ints_visitor(), a); //Output: "Ignore me"
|
||||
|
||||
a = 22.24;
|
||||
apply_visitor(ignore_non_ints_visitor(), a); //Output: "Ignore me"
|
||||
|
||||
a = 8;
|
||||
apply_visitor(ignore_non_ints_visitor(), a); //Output: "Current value: 8"
|
||||
</pre>
|
||||
<p>A visitor may accept its operand using a "pass-by-reference" parameter
|
||||
passing scheme. This allows a visitor to mutate the variant-held value: </p>
|
||||
<pre> struct first_capital : boost::static_visitor<void>
|
||||
{
|
||||
void operator()(std::string& str) const
|
||||
{
|
||||
str[0] = toupper(str[0]);
|
||||
}
|
||||
|
||||
void operator()(char* str) const
|
||||
{
|
||||
*str = toupper(*str);
|
||||
}
|
||||
};
|
||||
|
||||
struct printer : boost::static_visitor<void>
|
||||
{
|
||||
template<typename T>
|
||||
void operator()(const T& t) const
|
||||
{
|
||||
std::cout << t << std::endl;
|
||||
}
|
||||
};
|
||||
.
|
||||
.
|
||||
variant<std::string, char*> a = std::string("abcde");
|
||||
apply_visitor(printer(), a); //Output: "abcde"
|
||||
|
||||
apply_visitor(first_capital(), a); //Invoke the mutating visitor
|
||||
//(capitalizes the first letter)
|
||||
|
||||
apply_visitor(printer(), a); //Output: "Abcde"
|
||||
</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<void>
|
||||
{
|
||||
int_accumulator() : total_(0) { }
|
||||
|
||||
void operator()(int x)
|
||||
{
|
||||
total_ += x;
|
||||
}
|
||||
|
||||
int total_;
|
||||
} ;
|
||||
.
|
||||
.
|
||||
int_accumulator adder;
|
||||
variant<int, short, char> a = 15;
|
||||
apply_visitor(adder, a); //adder.total_ += 15
|
||||
|
||||
a = short(9);
|
||||
apply_visitor(adder, a); //adder.total_ += 9
|
||||
|
||||
std::cout << "Total = " << adder.total_ << std::endl; //Output: "Total = 24"
|
||||
</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 "as is" without express or implied warranty.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
39
include/boost/empty.hpp
Normal file
39
include/boost/empty.hpp
Normal 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
|
||||
114
include/boost/incomplete.hpp
Normal file
114
include/boost/incomplete.hpp
Normal 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
|
||||
31
include/boost/incomplete_fwd.hpp
Normal file
31
include/boost/incomplete_fwd.hpp
Normal 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
30
include/boost/variant.hpp
Normal 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
|
||||
24
include/boost/variant/apply_visitor.hpp
Normal file
24
include/boost/variant/apply_visitor.hpp
Normal 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
|
||||
43
include/boost/variant/bad_visit.hpp
Normal file
43
include/boost/variant/bad_visit.hpp
Normal 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
|
||||
133
include/boost/variant/detail/apply_visitor_binary.hpp
Normal file
133
include/boost/variant/detail/apply_visitor_binary.hpp
Normal 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
|
||||
110
include/boost/variant/detail/apply_visitor_delayed.hpp
Normal file
110
include/boost/variant/detail/apply_visitor_delayed.hpp
Normal 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
|
||||
57
include/boost/variant/detail/apply_visitor_unary.hpp
Normal file
57
include/boost/variant/detail/apply_visitor_unary.hpp
Normal 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
|
||||
98
include/boost/variant/detail/define_forwarding_func.hpp
Normal file
98
include/boost/variant/detail/define_forwarding_func.hpp
Normal 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
|
||||
106
include/boost/variant/detail/has_nothrow_move.hpp
Normal file
106
include/boost/variant/detail/has_nothrow_move.hpp
Normal 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
|
||||
100
include/boost/variant/detail/has_trivial_move.hpp
Normal file
100
include/boost/variant/detail/has_trivial_move.hpp
Normal 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
|
||||
169
include/boost/variant/detail/move.hpp
Normal file
169
include/boost/variant/detail/move.hpp
Normal 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
*/
|
||||
130
include/boost/variant/get.hpp
Normal file
130
include/boost/variant/get.hpp
Normal 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
|
||||
73
include/boost/variant/static_visitor.hpp
Normal file
73
include/boost/variant/static_visitor.hpp
Normal 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
|
||||
1163
include/boost/variant/variant.hpp
Normal file
1163
include/boost/variant/variant.hpp
Normal file
File diff suppressed because it is too large
Load Diff
143
include/boost/variant/variant_fwd.hpp
Normal file
143
include/boost/variant/variant_fwd.hpp
Normal 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
|
||||
82
include/boost/variant/visitor_ptr.hpp
Normal file
82
include/boost/variant/visitor_ptr.hpp
Normal 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
8
index.html
Normal 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
20
test/Jamfile
Normal 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
55
test/class_a.cpp
Normal 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
30
test/class_a.h
Normal 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
310
test/jobs.h
Normal 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
135
test/test1.cpp
Normal 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
129
test/test2.cpp
Normal 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
144
test/test3.cpp
Normal 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
46
test/test4.cpp
Normal 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
83
test/test5.cpp
Normal 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
66
test/test6.cpp
Normal 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
202
test/test7.cpp
Normal 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
101
test/test8.cpp
Normal 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
36
test/varout.h
Normal 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_
|
||||
|
||||
Reference in New Issue
Block a user