1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-09-12 17:17:57 -05:00

Initial commit

This commit is contained in:
Crimson-Hawk
2024-03-05 16:42:40 +08:00
commit f1e4595ebf
39576 changed files with 7006612 additions and 0 deletions

View File

View File

View File

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

View File

@@ -0,0 +1,171 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
cxxflags: "cxxflags=--coverage -fsanitize=address,leak,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=--coverage -lasan -lubsan"
gcov_tool: "gcov-10"
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
cxxflags: "cxxflags=-fsanitize=address,undefined,integer -fno-sanitize-recover=undefined"
linkflags: "linkflags=-fsanitize=address,undefined,integer"
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
cxxflags: "cxxflags=-fsanitize=address,undefined -fno-sanitize-recover=undefined"
linkflags: "linkflags=-fsanitize=address,undefined"
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init --depth 10 --jobs 2 tools/boostdep tools/inspect libs/filesystem
python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 3" filesystem
rm -rf libs/$LIBRARY/*
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--depth 10 --jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build
- name: Run tests
run: |
cd ../boost-root
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release "${{matrix.cxxflags}}" "${{matrix.linkflags}}" "${{matrix.launcher}}"
dist/bin/inspect libs/$LIBRARY
- name: Prepare coverage data
if: matrix.gcov_tool
run: |
mkdir -p $GITHUB_WORKSPACE/coveralls
echo -e "#!/bin/bash\nexec ${{matrix.gcov_tool}} \"\$@\"" > $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
chmod +x $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh
wget https://github.com/linux-test-project/lcov/archive/v1.15.zip
unzip v1.15.zip
LCOV="`pwd`/lcov-1.15/bin/lcov --gcov-tool $GITHUB_WORKSPACE/coveralls/gcov_wrapper.sh"
echo "$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory `pwd`/libs/$LIBRARY/test --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info"
$LCOV --directory ../boost-root/bin.v2/libs/$LIBRARY/ --base-directory ../boost-root/ --capture --output-file $GITHUB_WORKSPACE/coveralls/coverage.info
$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info "/usr*" "*/$LIBRARY/test/*" ${{matrix.ignore_coverage}} "*/$LIBRARY/tests/*" "*/$LIBRARY/examples/*" "*/$LIBRARY/example/*" -o $GITHUB_WORKSPACE/coveralls/coverage.info
cd ../boost-root
OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/$LIBRARY\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'`
echo $OTHER_LIBS
eval "$LCOV --remove $GITHUB_WORKSPACE/coveralls/coverage.info $OTHER_LIBS -o $GITHUB_WORKSPACE/coveralls/coverage.info"
- name: Coveralls
uses: coverallsapp/github-action@master
if: matrix.gcov_tool
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coveralls/coverage.info
parallel: true
windows:
strategy:
fail-fast: false
matrix:
include:
- toolset: msvc-14.1
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --include benchmark --include example --include examples --include tools --git_args "--jobs 3" %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
- name: Run tests
shell: cmd
run: |
cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
finish:
needs: posix
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true

View File

@@ -0,0 +1,30 @@
# Copyright 2019 Mike Dev
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required( VERSION 3.5...3.20 )
project( boost_variant VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX )
add_library( boost_variant INTERFACE )
add_library( Boost::variant ALIAS boost_variant )
target_include_directories( boost_variant INTERFACE include )
target_link_libraries( boost_variant
INTERFACE
Boost::assert
Boost::bind
Boost::config
Boost::container_hash
Boost::core
Boost::detail
Boost::integer
Boost::move
Boost::mpl
Boost::preprocessor
Boost::static_assert
Boost::throw_exception
Boost::type_index
Boost::type_traits
Boost::utility
)

View File

@@ -0,0 +1,16 @@
# [Boost.Variant](https://boost.org/libs/variant)
Boost.Variant, part of collection of the [Boost C++ Libraries](https://github.com/boostorg). It is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner.
### Test results
@ | Build | Tests coverage | More info
----------------|-------------- | -------------- |-----------
Develop branch: | [![CI](https://github.com/boostorg/variant/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/variant/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/bijfdoy7byfgc6e2/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/variant-ykfti/branch/develop) | [![Coverage Status](https://coveralls.io/repos/boostorg/variant/badge.png?branch=develop)](https://coveralls.io/r/apolukhin/variant?branch=develop) | [details...](http://www.boost.org/development/tests/develop/developer/variant.html)
Master branch: | [![CI](https://github.com/boostorg/variant/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/variant/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/bijfdoy7byfgc6e2/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/variant-ykfti/branch/master) | [![Coverage Status](https://coveralls.io/repos/boostorg/variant/badge.png?branch=master)](https://coveralls.io/r/apolukhin/variant?branch=master) | [details...](http://www.boost.org/development/tests/master/developer/variant.html)
[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/variant.html)
### License
Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt).

View File

@@ -0,0 +1,29 @@
# Boost.Variant Library doc Jamfile
#
# Copyright (C) 2003, Eric Friedman, Itay Maman.
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
project variant/doc ;
import boostbook : boostbook ;
boostbook variant-doc
:
variant.xml
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
###############################################################################
alias boostdoc
: variant.xml
:
:
: ;
explicit boostdoc ;
alias boostrelease ;
explicit boostrelease ;

View File

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

View File

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

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="variant.intro">
<title>Introduction</title>
<using-namespace name="boost"/>
<section id="variant.abstract">
<title>Abstract</title>
<para>The <code>variant</code> class template is a safe, generic, stack-based
discriminated union container, offering a simple solution for manipulating an
object from a heterogeneous set of types in a uniform manner. Whereas
standard containers such as <code>std::vector</code> may be thought of as
"<emphasis role="bold">multi-value, single type</emphasis>,"
<code>variant</code> is "<emphasis role="bold">multi-type,
single value</emphasis>."</para>
<para>Notable features of <code><classname>boost::variant</classname></code>
include:</para>
<itemizedlist>
<listitem>Full value semantics, including adherence to standard
overload resolution rules for conversion operations.</listitem>
<listitem>Compile-time type-safe value visitation via
<code><functionname>boost::apply_visitor</functionname></code>.</listitem>
<listitem>Run-time checked explicit value retrieval via
<code><functionname>boost::get</functionname></code>.</listitem>
<listitem>Support for recursive variant types via both
<code><classname>boost::make_recursive_variant</classname></code> and
<code><classname>boost::recursive_wrapper</classname></code>.</listitem>
<listitem>Efficient implementation -- stack-based when possible (see
<xref linkend="variant.design.never-empty"/> for more details).</listitem>
</itemizedlist>
</section>
<section id="variant.motivation">
<title>Motivation</title>
<section id="variant.motivation.problem">
<title>Problem</title>
<para>Many times, during the development of a C++ program, the
programmer finds himself in need of manipulating several distinct
types in a uniform manner. Indeed, C++ features direct language
support for such types through its <code>union</code>
keyword:</para>
<programlisting>union { int i; double d; } u;
u.d = 3.14;
u.i = 3; // overwrites u.d (OK: u.d is a POD type)</programlisting>
<para>C++'s <code>union</code> construct, however, is nearly
useless in an object-oriented environment. The construct entered
the language primarily as a means for preserving compatibility with
C, which supports only POD (Plain Old Data) types, and so does not
accept types exhibiting non-trivial construction or
destruction:</para>
<programlisting>union {
int i;
std::string s; // illegal: std::string is not a POD type!
} u;</programlisting>
<para>Clearly another approach is required. Typical solutions
feature the dynamic-allocation of objects, which are subsequently
manipulated through a common base type (often a virtual base class
[<link linkend="variant.refs.hen01">Hen01</link>]
or, more dangerously, a <code>void*</code>). Objects of
concrete type may be then retrieved by way of a polymorphic downcast
construct (e.g., <code>dynamic_cast</code>,
<code><functionname>boost::any_cast</functionname></code>, etc.).</para>
<para>However, solutions of this sort are highly error-prone, due
to the following:</para>
<itemizedlist>
<listitem><emphasis>Downcast errors cannot be detected at
compile-time.</emphasis> Thus, incorrect usage of downcast
constructs will lead to bugs detectable only at run-time.</listitem>
<listitem><emphasis>Addition of new concrete types may be
ignored.</emphasis> If a new concrete type is added to the
hierarchy, existing downcast code will continue to work as-is,
wholly ignoring the new type. Consequently, the programmer must
manually locate and modify code at numerous locations, which often
results in run-time errors that are difficult to find.</listitem>
</itemizedlist>
<para>Furthermore, even when properly implemented, these solutions tend
to incur a relatively significant abstraction penalty due to the use of
the heap, virtual function calls, and polymorphic downcasts.</para>
</section>
<section id="variant.motivation.solution">
<title>Solution: A Motivating Example</title>
<para>The <code><classname>boost::variant</classname></code> class template
addresses these issues in a safe, straightforward, and efficient manner. The
following example demonstrates how the class can be used:</para>
<programlisting>#include "boost/variant.hpp"
#include &lt;iostream&gt;
class my_visitor : public <classname>boost::static_visitor</classname>&lt;int&gt;
{
public:
int operator()(int i) const
{
return i;
}
int operator()(const <classname>std::string</classname> &amp; str) const
{
return str.length();
}
};
int main()
{
<classname>boost::variant</classname>&lt; int, std::string &gt; u("hello world");
std::cout &lt;&lt; u; // output: hello world
int result = <functionname>boost::apply_visitor</functionname>( my_visitor(), u );
std::cout &lt;&lt; result; // output: 11 (i.e., length of "hello world")
}
</programlisting>
</section>
</section>
</section>

View File

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

View File

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

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<header name="boost/variant/bad_visit.hpp">
<namespace name="boost">
<class name="bad_visit">
<inherit access="public">
<classname>std::exception</classname>
</inherit>
<purpose>
<simpara>The exception thrown in the event of a visitor
unable to handle the visited value.</simpara>
</purpose>
<method name="what" specifiers="virtual" cv="const">
<type>const char *</type>
</method>
</class>
</namespace>
</header>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library-reference PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<library-reference xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="concepts.xml"/>
<header name="boost/variant.hpp">
<section id="variant.header.include-all">
<para>This header exists simply as a convenience to the user, including
all of the headers in the <code>boost/variant</code> directory except &lt;boost/multivisiors.hpp&gt;.</para>
</section>
</header>
<xi:include href="variant_fwd.xml"/>
<xi:include href="variant.xml"/>
<xi:include href="recursive_variant.xml"/>
<xi:include href="recursive_wrapper.xml"/>
<xi:include href="apply_visitor.xml"/>
<xi:include href="multivisitor.xml"/>
<xi:include href="get.xml"/>
<xi:include href="polymorphic_get.xml"/>
<xi:include href="bad_visit.xml"/>
<xi:include href="static_visitor.xml"/>
<xi:include href="visitor_ptr.xml"/>
</library-reference>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<header name="boost/variant/static_visitor.hpp">
<namespace name="boost">
<class name="static_visitor">
<template>
<template-type-parameter name="ResultType"/>
</template>
<purpose>Convenient base type for static visitors.</purpose>
<description>
<simpara>Denotes the intent of the deriving class as meeting the
requirements of a static visitor of some type. Also exposes the
inner type <code>result_type</code> as required by the
<link linkend="variant.concepts.static-visitor"><emphasis>StaticVisitor</emphasis></link>
concept.</simpara>
<simpara><emphasis role="bold">Notes</emphasis>:
<code>static_visitor</code> is intended for use as a base type only
and is therefore noninstantiable.</simpara>
</description>
<typedef name="result_type">
<type>ResultType</type>
<purpose>Exposes result_type member as required by StaticVisitor concept.</purpose>
</typedef>
</class>
</namespace>
</header>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<!--
Copyright 2003, Eric Friedman, Itay Maman.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<section xmlns:xi="http://www.w3.org/2001/XInclude" id="variant.tutorial">
<title>Tutorial</title>
<xi:include href="basic.xml"/>
<xi:include href="advanced.xml"/>
</section>

View File

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

View File

@@ -0,0 +1,27 @@
//-----------------------------------------------------------------------------
// boost variant.hpp header file
// See http://www.boost.org/libs/variant for documentation.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_HPP
#define BOOST_VARIANT_HPP
// variant "main"
#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>
// common applications
#include <boost/variant/get.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/visitor_ptr.hpp>
#endif // BOOST_VARIANT_HPP

View File

@@ -0,0 +1,20 @@
//-----------------------------------------------------------------------------
// boost variant/apply_visitor.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_APPLY_VISITOR_HPP
#define BOOST_VARIANT_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_VARIANT_APPLY_VISITOR_HPP

View File

@@ -0,0 +1,43 @@
//-----------------------------------------------------------------------------
// boost variant/bad_visit.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_BAD_VISIT_HPP
#define BOOST_VARIANT_BAD_VISIT_HPP
#include <boost/config.hpp>
#include <exception>
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class bad_visit
//
// Exception thrown when a visitation attempt via apply_visitor fails due
// to invalid visited subtype or contents.
//
struct BOOST_SYMBOL_VISIBLE bad_visit
: std::exception
{
public: // std::exception interface
const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{
return "boost::bad_visit: "
"failed visitation using boost::apply_visitor";
}
};
} // namespace boost
#endif // BOOST_VARIANT_BAD_VISIT_HPP

View File

@@ -0,0 +1,358 @@
//-----------------------------------------------------------------------------
// 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
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
#include <boost/config.hpp>
#include <boost/variant/detail/apply_visitor_unary.hpp>
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
# include <boost/variant/detail/has_result_type.hpp>
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# include <boost/core/enable_if.hpp>
# include <boost/type_traits/is_lvalue_reference.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/move/utility_core.hpp> // for boost::move, boost::forward
#endif
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 variant {
template <typename Visitor, typename Value1, bool MoveSemantics>
class apply_visitor_binary_invoke
{
public: // visitor typedefs
typedef typename Visitor::result_type
result_type;
private: // representation
Visitor& visitor_;
Value1& value1_;
public: // structors
apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
: visitor_(visitor)
, value1_(value1)
{
}
public: // visitor interfaces
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Value2>
typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
operator()(Value2&& value2)
{
return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
}
template <typename Value2>
typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, result_type>::type
operator()(Value2&& value2)
{
return visitor_(value1_, ::boost::forward<Value2>(value2));
}
#else
template <typename Value2>
result_type
operator()(Value2& value2)
{
return visitor_(value1_, value2);
}
#endif
private:
apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
};
template <typename Visitor, typename Visitable2, bool MoveSemantics>
class apply_visitor_binary_unwrap
{
public: // visitor typedefs
typedef typename Visitor::result_type
result_type;
private: // representation
Visitor& visitor_;
Visitable2& visitable2_;
public: // structors
apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
: visitor_(visitor)
, visitable2_(visitable2)
{
}
public: // visitor interfaces
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Value1>
typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
operator()(Value1&& value1)
{
apply_visitor_binary_invoke<
Visitor
, Value1
, ! ::boost::is_lvalue_reference<Value1>::value
> invoker(visitor_, value1);
return boost::apply_visitor(invoker, ::boost::move(visitable2_));
}
template <typename Value1>
typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, result_type>::type
operator()(Value1&& value1)
{
apply_visitor_binary_invoke<
Visitor
, Value1
, ! ::boost::is_lvalue_reference<Value1>::value
> invoker(visitor_, value1);
return boost::apply_visitor(invoker, visitable2_);
}
#else
template <typename Value1>
result_type
operator()(Value1& value1)
{
apply_visitor_binary_invoke<
Visitor
, Value1
, false
> invoker(visitor_, value1);
return boost::apply_visitor(invoker, visitable2_);
}
#endif
private:
apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
};
}} // namespace detail::variant
//
// nonconst-visitor version:
//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable1, typename Visitable2>
inline typename Visitor::result_type
apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
}
#else
template <typename Visitor, typename Visitable1, typename Visitable2>
inline typename Visitor::result_type
apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
Visitor, Visitable2, false
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, visitable1);
}
#endif
//
// const-visitor version:
//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable1, typename Visitable2>
inline typename Visitor::result_type
apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
}
#else
template <typename Visitor, typename Visitable1, typename Visitable2>
inline typename Visitor::result_type
apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
const Visitor, Visitable2, false
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, visitable1);
}
#endif
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, visitable1, visitable2)
//
// C++14 part.
//
namespace detail { namespace variant {
template <typename Visitor, typename Value1, bool MoveSemantics>
class apply_visitor_binary_invoke_cpp14
{
Visitor& visitor_;
Value1& value1_;
public: // structors
apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
: visitor_(visitor)
, value1_(value1)
{
}
public: // visitor interfaces
template <typename Value2>
decltype(auto) operator()(Value2&& value2, typename enable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
{
return visitor_(::boost::move(value1_), ::boost::forward<Value2>(value2));
}
template <typename Value2>
decltype(auto) operator()(Value2&& value2, typename disable_if_c<MoveSemantics && is_same<Value2, Value2>::value, bool>::type = true)
{
return visitor_(value1_, ::boost::forward<Value2>(value2));
}
private:
apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
};
template <typename Visitor, typename Visitable2, bool MoveSemantics>
class apply_visitor_binary_unwrap_cpp14
{
Visitor& visitor_;
Visitable2& visitable2_;
public: // structors
apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
: visitor_(visitor)
, visitable2_(visitable2)
{
}
public: // visitor interfaces
template <typename Value1>
decltype(auto) operator()(Value1&& value1, typename enable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
{
apply_visitor_binary_invoke_cpp14<
Visitor
, Value1
, ! ::boost::is_lvalue_reference<Value1>::value
> invoker(visitor_, value1);
return boost::apply_visitor(invoker, ::boost::move(visitable2_));
}
template <typename Value1>
decltype(auto) operator()(Value1&& value1, typename disable_if_c<MoveSemantics && is_same<Value1, Value1>::value, bool>::type = true)
{
apply_visitor_binary_invoke_cpp14<
Visitor
, Value1
, ! ::boost::is_lvalue_reference<Value1>::value
> invoker(visitor_, value1);
return boost::apply_visitor(invoker, visitable2_);
}
private:
apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
};
}} // namespace detail::variant
template <typename Visitor, typename Visitable1, typename Visitable2>
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
bool
>::type = true)
{
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
}
template <typename Visitor, typename Visitable1, typename Visitable2>
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
bool
>::type = true)
{
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
const Visitor, Visitable2, ! ::boost::is_lvalue_reference<Visitable2>::value
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, ::boost::forward<Visitable1>(visitable1));
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP

View File

@@ -0,0 +1,146 @@
//-----------------------------------------------------------------------------
// 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
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP
#include <boost/variant/detail/apply_visitor_unary.hpp>
#include <boost/variant/detail/apply_visitor_binary.hpp>
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#include <boost/variant/detail/has_result_type.hpp>
#include <boost/core/enable_if.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: // visitor typedefs
typedef typename Visitor::result_type
result_type;
private: // representation
Visitor& visitor_;
public: // structors
explicit apply_visitor_delayed_t(Visitor& visitor) BOOST_NOEXCEPT
: visitor_(visitor)
{
}
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
public: // N-ary visitor interface
template <typename... Visitables>
result_type operator()(Visitables&... visitables) const
{
return apply_visitor(visitor_, visitables...);
}
#else // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
public: // unary visitor interface
template <typename Visitable>
result_type operator()(Visitable& visitable) const
{
return apply_visitor(visitor_, visitable);
}
public: // binary visitor interface
template <typename Visitable1, typename Visitable2>
result_type operator()(Visitable1& visitable1, Visitable2& visitable2) const
{
return apply_visitor(visitor_, visitable1, visitable2);
}
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
private:
apply_visitor_delayed_t& operator=(const apply_visitor_delayed_t&);
};
template <typename Visitor>
inline typename boost::enable_if<
boost::detail::variant::has_result_type<Visitor>,
apply_visitor_delayed_t<Visitor>
>::type apply_visitor(Visitor& visitor)
{
return apply_visitor_delayed_t<Visitor>(visitor);
}
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) \
&& !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template <typename Visitor>
class apply_visitor_delayed_cpp14_t
{
private: // representation
Visitor& visitor_;
public: // structors
explicit apply_visitor_delayed_cpp14_t(Visitor& visitor) BOOST_NOEXCEPT
: visitor_(visitor)
{
}
public: // N-ary visitor interface
template <typename... Visitables>
decltype(auto) operator()(Visitables&... visitables) const
{
return apply_visitor(visitor_, visitables...);
}
private:
apply_visitor_delayed_cpp14_t& operator=(const apply_visitor_delayed_cpp14_t&);
};
template <typename Visitor>
inline typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
apply_visitor_delayed_cpp14_t<Visitor>
>::type apply_visitor(Visitor& visitor)
{
return apply_visitor_delayed_cpp14_t<Visitor>(visitor);
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
// && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP

View File

@@ -0,0 +1,145 @@
//-----------------------------------------------------------------------------
// 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
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
#include <boost/config.hpp>
#include <boost/move/utility.hpp>
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
# include <boost/mpl/distance.hpp>
# include <boost/mpl/advance.hpp>
# include <boost/mpl/deref.hpp>
# include <boost/mpl/size.hpp>
# include <boost/utility/declval.hpp>
# include <boost/core/enable_if.hpp>
# include <boost/type_traits/copy_cv_ref.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/variant/detail/has_result_type.hpp>
#endif
namespace boost {
//////////////////////////////////////////////////////////////////////////
// function template apply_visitor(visitor, visitable)
//
// Visits visitable with visitor.
//
//
// nonconst-visitor version:
//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(Visitor& visitor, Visitable&& visitable)
{
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(Visitor& visitor, Visitable& visitable)
{
return visitable.apply_visitor(visitor);
}
#endif
//
// const-visitor version:
//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(const Visitor& visitor, Visitable&& visitable)
{
return ::boost::forward<Visitable>(visitable).apply_visitor(visitor);
}
#else
template <typename Visitor, typename Visitable>
inline typename Visitor::result_type
apply_visitor(const Visitor& visitor, Visitable& visitable)
{
return visitable.apply_visitor(visitor);
}
#endif
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
#define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE
// C++14
namespace detail { namespace variant {
// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
template <class Visitor, class Variant>
struct result_multideduce1 {
typedef typename remove_reference<Variant>::type::types types;
typedef typename boost::mpl::begin<types>::type begin_it;
typedef typename boost::mpl::advance<
begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
>::type last_it;
template <class It, class Dummy = void> // avoid explicit specialization in class scope
struct deduce_impl {
typedef typename boost::mpl::next<It>::type next_t;
typedef typename boost::mpl::deref<It>::type value_t;
typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )
: boost::declval< typename deduce_impl<next_t>::type >()) type;
};
template <class Dummy>
struct deduce_impl<last_it, Dummy> {
typedef typename boost::mpl::deref<last_it>::type value_t;
typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type;
};
typedef typename deduce_impl<begin_it>::type type;
};
template <class Visitor, class Variant>
struct result_wrapper1
{
typedef typename result_multideduce1<Visitor, Variant>::type result_type;
Visitor&& visitor_;
explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
: visitor_(::boost::forward<Visitor>(visitor))
{}
template <class T>
result_type operator()(T&& val) const {
return visitor_(::boost::forward<T>(val));
}
};
}} // namespace detail::variant
template <typename Visitor, typename Visitable>
inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
bool
>::type = true)
{
boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(::boost::forward<Visitor>(visitor));
return ::boost::forward<Visitable>(visitable).apply_visitor(cpp14_vis);
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP

View File

@@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// boost variant/detail/backup_holder.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
#define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
#include <boost/config.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace detail { namespace variant {
template <typename T>
class backup_holder
{
private: // representation
T* backup_;
public: // structors
~backup_holder() BOOST_NOEXCEPT
{
delete backup_;
}
explicit backup_holder(T* backup) BOOST_NOEXCEPT
: backup_(backup)
{
}
backup_holder(const backup_holder&);
public: // modifiers
backup_holder& operator=(const backup_holder& rhs)
{
*backup_ = rhs.get();
return *this;
}
backup_holder& operator=(const T& rhs)
{
*backup_ = rhs;
return *this;
}
void swap(backup_holder& rhs) BOOST_NOEXCEPT
{
T* tmp = rhs.backup_;
rhs.backup_ = this->backup_;
this->backup_ = tmp;
}
public: // queries
T& get() BOOST_NOEXCEPT
{
return *backup_;
}
const T& get() const BOOST_NOEXCEPT
{
return *backup_;
}
};
template <typename T>
backup_holder<T>::backup_holder(const backup_holder&)
: backup_(0)
{
// not intended for copy, but do not want to prohibit syntactically
BOOST_ASSERT(false);
}
template <typename T>
void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT
{
lhs.swap(rhs);
}
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP

View File

@@ -0,0 +1,42 @@
//-----------------------------------------------------------------------------
// boost variant/detail/cast_storage.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP
#define BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP
#include <boost/config.hpp>
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) function template cast_storage
//
// Casts the given storage to the specified type, but with qualification.
//
template <typename T>
inline T& cast_storage(void* storage)
{
return *static_cast<T*>(storage);
}
template <typename T>
inline const T& cast_storage(const void* storage)
{
return *static_cast<const T*>(storage);
}
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP

View File

@@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// boost variant/detail/config.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman
// Copyright (c) 2016-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_CONFIG_HPP
#define BOOST_VARIANT_DETAIL_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#endif // BOOST_VARIANT_DETAIL_CONFIG_HPP

View File

@@ -0,0 +1,63 @@
//-----------------------------------------------------------------------------
// boost variant/detail/element_index.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP
#define BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP
#include <boost/config.hpp>
#include <boost/variant/recursive_wrapper_fwd.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/mpl/find_if.hpp>
namespace boost { namespace detail { namespace variant {
template <class VariantElement, class T>
struct variant_element_functor :
boost::mpl::or_<
boost::is_same<VariantElement, T>,
boost::is_same<VariantElement, boost::recursive_wrapper<T> >,
boost::is_same<VariantElement, T& >
>
{};
template <class Types, class T>
struct element_iterator_impl :
boost::mpl::find_if<
Types,
boost::mpl::or_<
variant_element_functor<boost::mpl::_1, T>,
variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >
>
>
{};
template <class Variant, class T>
struct element_iterator :
element_iterator_impl< typename Variant::types, typename boost::remove_reference<T>::type >
{};
template <class Variant, class T>
struct holds_element :
boost::mpl::not_<
boost::is_same<
typename boost::mpl::end<typename Variant::types>::type,
typename element_iterator<Variant, T>::type
>
>
{};
}}} // namespace boost::detail::variant
#endif // BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP

View File

@@ -0,0 +1,133 @@
//-----------------------------------------------------------------------------
// boost variant/detail/enable_recursive.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP
#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP
#include <boost/variant/detail/enable_recursive_fwd.hpp>
#include <boost/variant/variant_fwd.hpp>
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# include <boost/mpl/apply.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/lambda.hpp>
#endif
#include <boost/variant/detail/substitute.hpp>
#include <boost/mpl/aux_/config/ctps.hpp>
#include <boost/mpl/bool_fwd.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/variant/recursive_wrapper.hpp>
namespace boost {
namespace detail { namespace variant {
#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
# define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(T,Dest,Source) \
substitute< T , Dest , Source > \
/**/
#else // defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
///////////////////////////////////////////////////////////////////////////////
// (detail) class template rebind1
//
// Limited workaround in case 'substitute' metafunction unavailable.
//
template <typename T, typename U1>
struct rebind1
{
private:
typedef typename mpl::lambda<
mpl::identity<T>
>::type le_;
public:
typedef typename mpl::eval_if<
is_same< le_, mpl::identity<T> >
, le_ // identity<T>
, mpl::apply1<le_, U1>
>::type type;
};
# define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(T,Dest,Source) \
rebind1< T , Dest > \
/**/
#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction enable_recursive
//
// See boost/variant/detail/enable_recursive_fwd.hpp for more information.
//
template <typename T, typename RecursiveVariant, typename NoWrapper>
struct enable_recursive
: BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(
T, RecursiveVariant, ::boost::recursive_variant_
)
{
};
template <typename T, typename RecursiveVariant>
struct enable_recursive< T,RecursiveVariant,mpl::false_ >
{
private: // helpers, for metafunction result (below)
typedef typename BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(
T, RecursiveVariant, ::boost::recursive_variant_
)::type t_;
public: // metafunction result
// [Wrap with recursive_wrapper only if rebind really changed something:]
typedef typename mpl::if_<
mpl::or_<
is_same< t_,T >
, is_reference<t_>
, is_pointer<t_>
>
, t_
, boost::recursive_wrapper<t_>
>::type type;
};
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction class quoted_enable_recursive
//
// Same behavior as enable_recursive metafunction (see above).
//
template <typename RecursiveVariant, typename NoWrapper>
struct quoted_enable_recursive
{
template <typename T>
struct apply
: enable_recursive<T, RecursiveVariant, NoWrapper>
{
};
};
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP

View File

@@ -0,0 +1,87 @@
//-----------------------------------------------------------------------------
// boost variant/detail/enable_recursive_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
#include <boost/mpl/aux_/config/ctps.hpp>
#include <boost/mpl/bool_fwd.hpp>
# include <boost/mpl/bool.hpp>
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) tag recursive_flag
//
// Signifies that the variant should perform recursive substituion.
//
template <typename T>
struct recursive_flag
{
typedef T type;
};
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction is_recursive_flag
//
// Signifies that the variant should perform recursive substituion.
//
template <typename T>
struct is_recursive_flag
: mpl::false_
{
};
template <typename T>
struct is_recursive_flag< recursive_flag<T> >
: mpl::true_
{
};
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction enable_recursive
//
// Attempts recursive_variant_ tag substitution, wrapping with
// boost::recursive_wrapper if substituion occurs w/ non-indirect result
// (i.e., not a reference or pointer) *and* NoWrapper is false_.
//
template <
typename T
, typename RecursiveVariant
, typename NoWrapper = mpl::false_
>
struct enable_recursive;
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction class quoted_enable_recursive
//
// Same behavior as enable_recursive metafunction (see above).
//
template <
typename RecursiveVariant
, typename NoWrapper = mpl::false_
>
struct quoted_enable_recursive;
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP

View File

@@ -0,0 +1,52 @@
//-----------------------------------------------------------------------------
// boost variant/detail/forced_return.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman
// Copyright (c) 2015-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP
#define BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP
#include <boost/config.hpp>
#include <boost/assert.hpp>
#ifdef BOOST_MSVC
# pragma warning( push )
# pragma warning( disable : 4702 ) // unreachable code
#endif
namespace boost { namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) function template forced_return
//
// Logical error to permit invocation at runtime, but (artificially) satisfies
// compile-time requirement of returning a result value.
//
template <typename T>
BOOST_NORETURN inline T
forced_return()
{
// logical error: should never be here! (see above)
BOOST_ASSERT(false);
T (*dummy)() = 0;
(void)dummy;
BOOST_UNREACHABLE_RETURN(dummy());
}
}}} // namespace boost::detail::variant
#ifdef BOOST_MSVC
# pragma warning( pop )
#endif
#endif // BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP

View File

@@ -0,0 +1,37 @@
//-----------------------------------------------------------------------------
// boost variant/detail/has_result_type.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
#define BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>
namespace boost { namespace detail { namespace variant {
template <typename T >
struct has_result_type {
private:
typedef char yes;
typedef struct { char array[2]; } no;
template<typename C> static yes test(typename boost::remove_reference<typename C::result_type>::type*);
template<typename C> static no test(...);
public:
BOOST_STATIC_CONSTANT(bool, value = sizeof(test<T>(0)) == sizeof(yes));
};
}}} // namespace boost::detail::variant
#endif // BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP

View File

@@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// boost variant/detail/hash_variant.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2011-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_HASH_VARIANT_FUNCTION_HPP
#define BOOST_HASH_VARIANT_FUNCTION_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/functional/hash_fwd.hpp>
namespace boost {
namespace detail { namespace variant {
struct variant_hasher: public boost::static_visitor<std::size_t> {
template <class T>
std::size_t operator()(T const& val) const {
boost::hash<T> hasher;
return hasher(val);
}
};
}}
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
std::size_t hash_value(variant< BOOST_VARIANT_ENUM_PARAMS(T) > const& val) {
std::size_t seed = boost::apply_visitor(detail::variant::variant_hasher(), val);
hash_combine(seed, val.which());
return seed;
}
}
#endif

View File

@@ -0,0 +1,249 @@
//-----------------------------------------------------------------------------
// boost variant/detail/initializer.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP
#define BOOST_VARIANT_DETAIL_INITIALIZER_HPP
#include <new> // for placement new
#include <boost/config.hpp>
#include <boost/call_traits.hpp>
#include <boost/detail/reference_content.hpp>
#include <boost/variant/recursive_wrapper_fwd.hpp>
#include <boost/variant/detail/move.hpp>
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# include <boost/mpl/aux_/value_wknd.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/iter_fold.hpp>
# include <boost/mpl/next.hpp>
# include <boost/mpl/deref.hpp>
# include <boost/mpl/pair.hpp>
# include <boost/mpl/protect.hpp>
#else
# include <boost/variant/variant_fwd.hpp>
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/enum.hpp>
# include <boost/preprocessor/repeat.hpp>
#endif
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) support to simulate standard overload resolution rules
//
// The below initializers allows variant to follow standard overload
// resolution rules over the specified set of bounded types.
//
// On compilers where using declarations in class templates can correctly
// avoid name hiding, use an optimal solution based on the variant's typelist.
//
// Otherwise, use a preprocessor workaround based on knowledge of the fixed
// size of the variant's psuedo-variadic template parameter list.
//
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// (detail) quoted metafunction make_initializer_node
//
// Exposes a pair whose first type is a node in the initializer hierarchy.
//
struct make_initializer_node
{
template <typename BaseIndexPair, typename Iterator>
struct apply
{
private: // helpers, for metafunction result (below)
typedef typename BaseIndexPair::first
base;
typedef typename BaseIndexPair::second
index;
class initializer_node
: public base
{
private: // helpers, for static functions (below)
typedef typename mpl::deref<Iterator>::type
recursive_enabled_T;
typedef typename unwrap_recursive<recursive_enabled_T>::type
public_T;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef boost::is_reference<public_T>
is_reference_content_t;
typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
param_T;
template <class T> struct disable_overload{};
typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
param2_T;
#else
typedef typename call_traits<public_T>::param_type
param_T;
#endif
public: // static functions
using base::initialize;
static int initialize(void* dest, param_T operand)
{
typedef typename boost::detail::make_reference_content<
recursive_enabled_T
>::type internal_T;
new(dest) internal_T(operand);
return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
static int initialize(void* dest, param2_T operand)
{
// This assert must newer trigger, because all the reference contents are
// handled by the initilize(void* dest, param_T operand) function above
BOOST_ASSERT(!is_reference_content_t::value);
typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T;
new(dest) value_T( boost::detail::variant::move(operand) );
return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
}
#endif
};
friend class initializer_node;
public: // metafunction result
typedef mpl::pair<
initializer_node
, typename mpl::next< index >::type
> type;
};
};
// (detail) class initializer_root
//
// Every level of the initializer hierarchy must expose the name
// "initialize," so initializer_root provides a dummy function:
//
class initializer_root
{
public: // static functions
static void initialize();
};
#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// Obsolete. Remove.
#define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
/**/
// Obsolete. Remove.
#define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
typedef typename unwrap_recursive< \
BOOST_PP_CAT(recursive_enabled_T,N) \
>::type BOOST_PP_CAT(public_T,N); \
typedef typename call_traits< \
BOOST_PP_CAT(public_T,N) \
>::param_type BOOST_PP_CAT(param_T,N); \
/**/
template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) >
struct preprocessor_list_initializer
{
public: // static functions
#define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \
typedef typename unwrap_recursive< \
BOOST_PP_CAT(recursive_enabled_T,N) \
>::type BOOST_PP_CAT(public_T,N); \
typedef typename call_traits< \
BOOST_PP_CAT(public_T,N) \
>::param_type BOOST_PP_CAT(param_T,N); \
static int initialize( \
void* dest \
, BOOST_PP_CAT(param_T,N) operand \
) \
{ \
typedef typename boost::detail::make_reference_content< \
BOOST_PP_CAT(recursive_enabled_T,N) \
>::type internal_T; \
\
new(dest) internal_T(operand); \
return (N); /*which*/ \
} \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
, _
)
#undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
};
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
}} // namespace detail::variant
} // namespace boost
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_AUX_INITIALIZER_T
//
// Given both the variant's typelist and a basename for forming the list of
// bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
// most appropriate to the current compiler.
//
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
::boost::mpl::iter_fold< \
mpl_seq \
, ::boost::mpl::pair< \
::boost::detail::variant::initializer_root \
, ::boost::mpl::int_<0> \
> \
, ::boost::mpl::protect< \
::boost::detail::variant::make_initializer_node \
> \
>::type::first \
/**/
#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
// Obsolete. Remove.
#define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
BOOST_VARIANT_ENUM_PARAMS(typename_base) \
/**/
#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
::boost::detail::variant::preprocessor_list_initializer< \
BOOST_VARIANT_ENUM_PARAMS(typename_base) \
> \
/**/
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
#endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP

View File

@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
// boost variant/detail/make_variant_list.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003 Eric Friedman, Itay Maman
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
#define BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
#include <boost/variant/variant_fwd.hpp>
#include <boost/mpl/list.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/enum.hpp>
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction make_variant_list
//
// Provides a MPL-compatible sequence with the specified non-void types
// as arguments.
//
// Rationale: see class template convert_void (variant_fwd.hpp) and using-
// declaration workaround (below).
//
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template < typename... T >
struct make_variant_list
{
typedef typename mpl::list< T... >::type type;
};
#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct make_variant_list
{
public: // metafunction result
// [Define a macro to convert any void(NN) tags to mpl::void...]
# define BOOST_VARIANT_AUX_CONVERT_VOID(z, N,_) \
typename convert_void< BOOST_PP_CAT(T,N) >::type
// [...so that the specified types can be passed to mpl::list...]
typedef typename mpl::list<
BOOST_PP_ENUM(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_CONVERT_VOID
, _
)
>::type type;
// [...and, finally, the conversion macro can be undefined:]
# undef BOOST_VARIANT_AUX_CONVERT_VOID
};
#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP

View File

@@ -0,0 +1,50 @@
//-----------------------------------------------------------------------------
// boost variant/detail/move.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003 Eric Friedman
// Copyright (c) 2002 by Andrei Alexandrescu
// Copyright (c) 2013-2022 Antony Polukhin
//
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// 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.
// Re-issued here under the Boost Software License, with permission of the original
// author (Andrei Alexandrescu).
#ifndef BOOST_VARIANT_DETAIL_MOVE_HPP
#define BOOST_VARIANT_DETAIL_MOVE_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/move/utility_core.hpp> // for boost::move
#include <boost/move/adl_move_swap.hpp>
namespace boost { namespace detail { namespace variant {
using boost::move;
//////////////////////////////////////////////////////////////////////////
// function template move_swap
//
// Swaps using Koenig lookup but falls back to move-swap for primitive
// types and on non-conforming compilers.
//
template <typename T>
inline void move_swap(T& lhs, T& rhs)
{
::boost::adl_move_swap(lhs, rhs);
}
}}} // namespace boost::detail::variant
#endif // BOOST_VARIANT_DETAIL_MOVE_HPP

View File

@@ -0,0 +1,217 @@
// Boost.Varaint
// Contains multivisitors that are implemented via variadic templates and std::tuple
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2013-2014.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
#define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/variant/detail/apply_visitor_unary.hpp>
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#include <boost/move/utility.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/core/enable_if.hpp>
#if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE)
# error "This file requires <tuple> and variadic templates support"
#endif
#include <tuple>
namespace boost {
namespace detail { namespace variant {
// Implementing some of the C++14 features in C++11
template <std::size_t... I> class index_sequence {};
template <std::size_t N, std::size_t... I>
struct make_index_sequence
: make_index_sequence<N-1, N-1, I...>
{};
template <std::size_t... I>
struct make_index_sequence<0, I...>
: index_sequence<I...>
{};
template <typename T_, bool MoveSemantics_>
struct MoveableWrapper //Just a reference with some metadata
{
typedef T_ T;
static constexpr bool MoveSemantics = MoveSemantics_;
T& v;
};
template <typename Tp, bool MoveSemantics>
MoveableWrapper<Tp, MoveSemantics>
wrap(Tp& t)
{
return MoveableWrapper<Tp, MoveSemantics>{t};
}
template <typename Wrapper>
typename enable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type
unwrap(Wrapper& w)
{
return ::boost::move(w.v);
}
template <typename Wrapper>
typename disable_if_c<Wrapper::MoveSemantics, typename Wrapper::T>::type &
unwrap(Wrapper& w)
{
return w.v;
}
// Implementing some of the helper tuple methods
template <std::size_t... I, typename Tuple>
std::tuple<typename std::tuple_element<I + 1, Tuple>::type...>
tuple_tail_impl(const Tuple& tpl, index_sequence<I...>)
{
return std::tuple<
typename std::tuple_element<I + 1, Tuple>::type...
> (std::get<I + 1>(tpl)...);
}
template <typename Head, typename... Tail>
std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl)
{
return tuple_tail_impl(tpl, make_index_sequence<sizeof...(Tail)>());
}
// Forward declaration
template <typename Visitor, typename Visitables, typename... Values>
class one_by_one_visitor_and_value_referer;
template <typename Visitor, typename Visitables, typename... Values>
inline one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... >
make_one_by_one_visitor_and_value_referer(
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
)
{
return one_by_one_visitor_and_value_referer<Visitor, Visitables, Values... > (
visitor, visitables, values
);
}
template <typename Visitor, typename Visitables, typename... Values>
class one_by_one_visitor_and_value_referer
{
Visitor& visitor_;
std::tuple<Values...> values_;
Visitables visitables_;
public: // structors
one_by_one_visitor_and_value_referer(
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
) BOOST_NOEXCEPT
: visitor_(visitor)
, values_(values)
, visitables_(visitables)
{}
public: // visitor interfaces
typedef typename Visitor::result_type result_type;
template <typename Value>
result_type operator()(Value&& value) const
{
return ::boost::apply_visitor(
make_one_by_one_visitor_and_value_referer(
visitor_,
tuple_tail(visitables_),
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
)
, unwrap(std::get<0>(visitables_)) // getting Head element
);
}
private:
one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&);
};
template <typename Visitor, typename... Values>
class one_by_one_visitor_and_value_referer<Visitor, std::tuple<>, Values...>
{
Visitor& visitor_;
std::tuple<Values...> values_;
public:
one_by_one_visitor_and_value_referer(
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
) BOOST_NOEXCEPT
: visitor_(visitor)
, values_(values)
{}
typedef typename Visitor::result_type result_type;
template <class Tuple, std::size_t... I>
result_type do_call(Tuple t, index_sequence<I...>) const {
return visitor_(unwrap(std::get<I>(t))...);
}
template <typename Value>
result_type operator()(Value&& value) const
{
return do_call(
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
make_index_sequence<sizeof...(Values) + 1>()
);
}
};
}} // namespace detail::variant
template <class Visitor, class T1, class T2, class T3, class... TN>
inline typename Visitor::result_type
apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
{
return ::boost::apply_visitor(
::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
visitor,
std::make_tuple(
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
),
std::tuple<>()
),
::boost::forward<T1>(v1)
);
}
template <class Visitor, class T1, class T2, class T3, class... TN>
inline typename Visitor::result_type
apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn)
{
return ::boost::apply_visitor(
::boost::detail::variant::make_one_by_one_visitor_and_value_referer(
visitor,
std::make_tuple(
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
),
std::tuple<>()
),
::boost::forward<T1>(v1)
);
}
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP

View File

@@ -0,0 +1,153 @@
// Boost.Varaint
// Contains multivisitors that are implemented via variadic templates, std::tuple
// and decltype(auto)
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2013-2014.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
#define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/variant/detail/multivisitors_cpp14_based.hpp>
#include <tuple>
namespace boost {
namespace detail { namespace variant {
// Forward declaration
template <typename Visitor, typename Visitables, typename... Values>
class one_by_one_visitor_and_value_referer_cpp14;
template <typename Visitor, typename Visitables, typename... Values>
inline one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... >
make_one_by_one_visitor_and_value_referer_cpp14(
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
)
{
return one_by_one_visitor_and_value_referer_cpp14<Visitor, Visitables, Values... > (
visitor, visitables, values
);
}
template <typename Visitor, typename Visitables, typename... Values>
class one_by_one_visitor_and_value_referer_cpp14
{
Visitor& visitor_;
std::tuple<Values...> values_;
Visitables visitables_;
public: // structors
one_by_one_visitor_and_value_referer_cpp14(
Visitor& visitor, Visitables visitables, std::tuple<Values...> values
) BOOST_NOEXCEPT
: visitor_(visitor)
, values_(values)
, visitables_(visitables)
{}
public: // visitor interfaces
template <typename Value>
decltype(auto) operator()(Value&& value) const
{
return ::boost::apply_visitor(
make_one_by_one_visitor_and_value_referer_cpp14(
visitor_,
tuple_tail(visitables_),
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value)))
)
, unwrap(std::get<0>(visitables_)) // getting Head element
);
}
private:
one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&);
};
template <typename Visitor, typename... Values>
class one_by_one_visitor_and_value_referer_cpp14<Visitor, std::tuple<>, Values...>
{
Visitor& visitor_;
std::tuple<Values...> values_;
public:
one_by_one_visitor_and_value_referer_cpp14(
Visitor& visitor, std::tuple<> /*visitables*/, std::tuple<Values...> values
) BOOST_NOEXCEPT
: visitor_(visitor)
, values_(values)
{}
template <class Tuple, std::size_t... I>
decltype(auto) do_call(Tuple t, index_sequence<I...>) const {
return visitor_(unwrap(std::get<I>(t))...);
}
template <typename Value>
decltype(auto) operator()(Value&& value) const
{
return do_call(
std::tuple_cat(values_, std::make_tuple(wrap<Value, ! ::boost::is_lvalue_reference<Value>::value>(value))),
make_index_sequence<sizeof...(Values) + 1>()
);
}
};
}} // namespace detail::variant
template <class Visitor, class T1, class T2, class T3, class... TN>
inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
bool
>::type = true)
{
return boost::apply_visitor(
::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
visitor,
std::make_tuple(
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
),
std::tuple<>()
),
::boost::forward<T1>(v1)
);
}
template <class Visitor, class T1, class T2, class T3, class... TN>
inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>,
bool
>::type = true)
{
return ::boost::apply_visitor(
::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14(
visitor,
std::make_tuple(
::boost::detail::variant::wrap<T2, ! ::boost::is_lvalue_reference<T2>::value>(v2),
::boost::detail::variant::wrap<T3, ! ::boost::is_lvalue_reference<T3>::value>(v3),
::boost::detail::variant::wrap<TN, ! ::boost::is_lvalue_reference<TN>::value>(vn)...
),
std::tuple<>()
),
::boost::forward<T1>(v1)
);
}
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP

View File

@@ -0,0 +1,143 @@
// Boost.Varaint
// Contains multivisitors that are implemented via preprocessor magic
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2013-2014.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP
#define BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/variant.hpp>
#include <boost/bind.hpp>
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#ifndef BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS
# define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 4
#endif
namespace boost {
namespace detail { namespace variant {
template <class VisitorT, class Visitable1T, class Visitable2T>
struct two_variables_holder {
private:
VisitorT& visitor_;
Visitable1T& visitable1_;
Visitable2T& visitable2_;
// required to suppress warnings and ensure that we do not copy
// this visitor
two_variables_holder& operator=(const two_variables_holder&);
public:
typedef BOOST_DEDUCED_TYPENAME VisitorT::result_type result_type;
explicit two_variables_holder(VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2) BOOST_NOEXCEPT
: visitor_(visitor)
, visitable1_(visitable1)
, visitable2_(visitable2)
{}
#define BOOST_VARIANT_OPERATOR_BEG() \
return ::boost::apply_visitor( \
::boost::bind<result_type>(boost::ref(visitor_), _1, _2 \
/**/
#define BOOST_VARIANT_OPERATOR_END() \
), visitable1_, visitable2_); \
/**/
#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
BOOST_PP_COMMA() boost::ref( BOOST_PP_CAT(vis, n) ) \
/**/
#define BOOST_VARIANT_VISIT(z, n, data) \
template <BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 1), class VisitableUnwrapped)> \
result_type operator()( \
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 1), VisitableUnwrapped, & vis) \
) const \
{ \
BOOST_VARIANT_OPERATOR_BEG() \
BOOST_PP_REPEAT(BOOST_PP_ADD(n, 1), BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
BOOST_VARIANT_OPERATOR_END() \
} \
/**/
BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, ~)
#undef BOOST_VARIANT_OPERATOR_BEG
#undef BOOST_VARIANT_OPERATOR_END
#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
#undef BOOST_VARIANT_VISIT
};
template <class VisitorT, class Visitable1T, class Visitable2T>
inline two_variables_holder<VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
) BOOST_NOEXCEPT
{
return two_variables_holder<VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
}
template <class VisitorT, class Visitable1T, class Visitable2T>
inline two_variables_holder<const VisitorT, Visitable1T, Visitable2T> make_two_variables_holder(
const VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2
) BOOST_NOEXCEPT
{
return two_variables_holder<const VisitorT, Visitable1T, Visitable2T>(visitor, visitable1, visitable2);
}
}} // namespace detail::variant
#define BOOST_VARIANT_APPLY_VISITOR_BEG() \
return ::boost::apply_visitor( \
boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \
var2 \
/**/
#define BOOST_VARIANT_APPLY_VISITOR_END() \
); \
/**/
#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \
BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \
/**/
#define BOOST_VARIANT_VISIT(z, n, data) \
template <class Visitor BOOST_PP_COMMA() BOOST_PP_ENUM_PARAMS(BOOST_PP_ADD(n, 3), class T)> \
inline BOOST_DEDUCED_TYPENAME Visitor::result_type apply_visitor( \
data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \
) \
{ \
BOOST_VARIANT_APPLY_VISITOR_BEG() \
BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \
BOOST_VARIANT_APPLY_VISITOR_END() \
} \
/**/
BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor)
BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor)
#undef BOOST_VARIANT_APPLY_VISITOR_BEG
#undef BOOST_VARIANT_APPLY_VISITOR_END
#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER
#undef BOOST_VARIANT_VISIT
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP

View File

@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// boost variant/detail/over_sequence.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Portions Copyright (C) 2002 David Abrahams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP
#define BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP
#include <boost/mpl/aux_/config/ctps.hpp>
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) class over_sequence
//
// Wrapper used to indicate bounded types for variant are from type sequence.
//
template <typename Types>
struct over_sequence
{
typedef Types type;
};
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction is_over_sequence (modeled on code by David Abrahams)
//
// Indicates whether the specified type is of form over_sequence<...> or not.
//
template <typename T>
struct is_over_sequence
: mpl::false_
{
};
template <typename Types>
struct is_over_sequence< over_sequence<Types> >
: mpl::true_
{
};
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP

View File

@@ -0,0 +1,46 @@
//-----------------------------------------------------------------------------
// boost variant/detail/std_hash.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2018-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_STD_HASH_HPP
#define BOOST_VARIANT_DETAIL_STD_HASH_HPP
#include <boost/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/detail/hash_variant.hpp>
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH
//
// Define this macro if you do not wish to have a std::hash specialization for
// boost::variant.
#if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
#include <functional> // for std::hash
namespace std {
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct hash<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) > > {
std::size_t operator()(const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& val) const {
return ::boost::hash_value(val);
}
};
}
#endif // #if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
#endif // BOOST_VARIANT_DETAIL_STD_HASH_HPP

View File

@@ -0,0 +1,279 @@
#if !defined(BOOST_PP_IS_ITERATING)
///// header body
//-----------------------------------------------------------------------------
// boost variant/detail/substitute.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP
#define BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP
#include <boost/mpl/aux_/config/ctps.hpp>
#include <boost/variant/detail/substitute_fwd.hpp>
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#include <boost/mpl/aux_/lambda_arity_param.hpp>
#include <boost/mpl/aux_/preprocessor/params.hpp>
#include <boost/mpl/aux_/preprocessor/repeat.hpp>
#include <boost/mpl/int_fwd.hpp>
#include <boost/mpl/limits/arity.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/empty.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/iterate.hpp>
namespace boost {
namespace detail { namespace variant {
#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction substitute
//
// Substitutes one type for another in the given type expression.
//
//
// primary template
//
template <
typename T, typename Dest, typename Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
typename Arity /* = ... (see substitute_fwd.hpp) */
)
>
struct substitute
{
typedef T type;
};
//
// tag substitution specializations
//
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(CV_) \
template <typename Dest, typename Source> \
struct substitute< \
CV_ Source \
, Dest \
, Source \
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) \
> \
{ \
typedef CV_ Dest type; \
}; \
/**/
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG( BOOST_PP_EMPTY() )
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(const)
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(volatile)
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(const volatile)
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG
//
// pointer specializations
//
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(CV_) \
template <typename T, typename Dest, typename Source> \
struct substitute< \
T * CV_ \
, Dest \
, Source \
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) \
> \
{ \
typedef typename substitute< \
T, Dest, Source \
>::type * CV_ type; \
}; \
/**/
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER( BOOST_PP_EMPTY() )
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(const)
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(volatile)
BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(const volatile)
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER
//
// reference specializations
//
template <typename T, typename Dest, typename Source>
struct substitute<
T&
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>)
>
{
typedef typename substitute<
T, Dest, Source
>::type & type;
};
//
// template expression (i.e., F<...>) specializations
//
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template <
template <typename...> class F
, typename... Ts
, typename Dest
, typename Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct substitute<
F<Ts...>
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
typedef F<typename substitute<
Ts, Dest, Source
>::type...> type;
};
//
// function specializations
//
template <
typename R
, typename... A
, typename Dest
, typename Source
>
struct substitute<
R (*)(A...)
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>)
>
{
private:
typedef typename substitute< R, Dest, Source >::type r;
public:
typedef r (*type)(typename substitute<
A, Dest, Source
>::type...);
};
#else
#define BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL(N) \
typedef typename substitute< \
BOOST_PP_CAT(U,N), Dest, Source \
>::type BOOST_PP_CAT(u,N); \
/**/
#define BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF(z, N, _) \
BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL( BOOST_PP_INC(N) ) \
/**/
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
#define BOOST_PP_FILENAME_1 <boost/variant/detail/substitute.hpp>
#include BOOST_PP_ITERATE()
#undef BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL
#undef BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP
///// iteration, depth == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
#define i BOOST_PP_FRAME_ITERATION(1)
#if i > 0
//
// template specializations
//
template <
template < BOOST_MPL_PP_PARAMS(i,typename P) > class T
, BOOST_MPL_PP_PARAMS(i,typename U)
, typename Dest
, typename Source
>
struct substitute<
T< BOOST_MPL_PP_PARAMS(i,U) >
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<( i )>)
>
{
private:
BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF, _)
public:
typedef T< BOOST_MPL_PP_PARAMS(i,u) > type;
};
//
// function specializations
//
template <
typename R
, BOOST_MPL_PP_PARAMS(i,typename U)
, typename Dest
, typename Source
>
struct substitute<
R (*)( BOOST_MPL_PP_PARAMS(i,U) )
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>)
>
{
private:
typedef typename substitute< R, Dest, Source >::type r;
BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF, _)
public:
typedef r (*type)( BOOST_MPL_PP_PARAMS(i,u) );
};
#elif i == 0
//
// zero-arg function specialization
//
template <
typename R, typename Dest, typename Source
>
struct substitute<
R (*)( void )
, Dest
, Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>)
>
{
private:
typedef typename substitute< R, Dest, Source >::type r;
public:
typedef r (*type)( void );
};
#endif // i
#undef i
#endif // BOOST_PP_IS_ITERATING

View File

@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// boost variant/detail/substitute_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP
#define BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP
#include <boost/mpl/aux_/lambda_arity_param.hpp>
#include <boost/mpl/aux_/template_arity.hpp>
#include <boost/mpl/int_fwd.hpp>
///////////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_DETAIL_NO_SUBSTITUTE
//
// Defined if 'substitute' is not implementable on the current compiler.
//
#include <boost/mpl/aux_/config/ctps.hpp>
#include <boost/mpl/aux_/config/ttp.hpp>
#if defined(BOOST_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
&& !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
# define BOOST_VARIANT_DETAIL_NO_SUBSTITUTE
#endif
namespace boost {
namespace detail { namespace variant {
#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
///////////////////////////////////////////////////////////////////////////////
// metafunction substitute
//
// Substitutes one type for another in the given type expression.
//
template <
typename T, typename Dest, typename Source
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
typename Arity = mpl::int_< mpl::aux::template_arity<T>::value >
)
>
struct substitute;
#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
}} // namespace detail::variant
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP

View File

@@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// boost variant/detail/variant_io.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_VARIANT_IO_HPP
#define BOOST_VARIANT_DETAIL_VARIANT_IO_HPP
#include <iosfwd> // for std::basic_ostream forward declare
#include <boost/variant/variant_fwd.hpp>
#include <boost/detail/templated_streams.hpp>
#include <boost/variant/static_visitor.hpp>
namespace boost {
///////////////////////////////////////////////////////////////////////////////
// function template operator<<
//
// Outputs the content of the given variant to the given ostream.
//
// forward declare (allows output of embedded variant< variant< ... >, ... >)
template <
BOOST_TEMPLATED_STREAM_ARGS(E,T)
BOOST_TEMPLATED_STREAM_COMMA
BOOST_VARIANT_ENUM_PARAMS(typename U)
>
inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<(
BOOST_TEMPLATED_STREAM(ostream, E,T)& out
, const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs
);
namespace detail { namespace variant {
template <typename OStream>
class printer
: public boost::static_visitor<>
{
private: // representation
OStream& out_;
public: // structors
explicit printer(OStream& out)
: out_( out )
{
}
public: // visitor interface
template <typename T>
void operator()(const T& operand) const
{
out_ << operand;
}
private:
printer& operator=(const printer&);
};
}} // namespace detail::variant
template <
BOOST_TEMPLATED_STREAM_ARGS(E,T)
BOOST_TEMPLATED_STREAM_COMMA
BOOST_VARIANT_ENUM_PARAMS(typename U)
>
inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<(
BOOST_TEMPLATED_STREAM(ostream, E,T)& out
, const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs
)
{
detail::variant::printer<
BOOST_TEMPLATED_STREAM(ostream, E,T)
> visitor(out);
rhs.apply_visitor(visitor);
return out;
}
} // namespace boost
#endif // BOOST_VARIANT_DETAIL_VARIANT_IO_HPP

View File

@@ -0,0 +1,277 @@
//-----------------------------------------------------------------------------
// boost variant/detail/visitation_impl.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
#define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
#include <boost/config.hpp>
#include <boost/variant/detail/backup_holder.hpp>
#include <boost/variant/detail/cast_storage.hpp>
#include <boost/variant/detail/forced_return.hpp>
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/or.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning (push)
# pragma warning (disable : 4702) //unreachable code
#endif
///////////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
//
// Unrolls variant's visitation mechanism to reduce template instantiation
// and potentially increase runtime performance. (TODO: Investigate further.)
//
#if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
# include <boost/mpl/limits/list.hpp>
# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
BOOST_MPL_LIMIT_LIST_SIZE
#else
# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
BOOST_VARIANT_LIMIT_TYPES
#endif
#endif
// Define a compiler generic null pointer value
#if defined(BOOST_NO_CXX11_NULLPTR)
#define BOOST_VARIANT_NULL 0
#else
#define BOOST_VARIANT_NULL nullptr
#endif
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) class apply_visitor_unrolled
//
// Tag type indicates when visitation_impl is unrolled.
//
struct apply_visitor_unrolled {};
///////////////////////////////////////////////////////////////////////////////
// (detail) class template visitation_impl_step
//
// "Never ending" iterator range facilitates visitation_impl unrolling.
//
template <typename Iter, typename LastIter>
struct visitation_impl_step
{
typedef typename mpl::deref<Iter>::type type;
typedef typename mpl::next<Iter>::type next_iter;
typedef visitation_impl_step<
next_iter, LastIter
> next;
};
template <typename LastIter>
struct visitation_impl_step< LastIter,LastIter >
{
typedef apply_visitor_unrolled type;
typedef visitation_impl_step next;
};
///////////////////////////////////////////////////////////////////////////////
// (detail) function template visitation_impl_invoke
//
// Invokes the given visitor on the specified type in the given storage.
//
template <typename Visitor, typename VoidPtrCV, typename T>
inline typename Visitor::result_type
visitation_impl_invoke_impl(
int, Visitor& visitor, VoidPtrCV storage, T*
, mpl::true_// never_uses_backup
)
{
return visitor.internal_visit(
cast_storage<T>(storage), 1L
);
}
template <typename Visitor, typename VoidPtrCV, typename T>
inline typename Visitor::result_type
visitation_impl_invoke_impl(
int internal_which, Visitor& visitor, VoidPtrCV storage, T*
, mpl::false_// never_uses_backup
)
{
if (internal_which >= 0)
{
return visitor.internal_visit(
cast_storage<T>(storage), 1L
);
}
else
{
return visitor.internal_visit(
cast_storage< backup_holder<T> >(storage), 1L
);
}
}
template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
inline typename Visitor::result_type
visitation_impl_invoke(
int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
, NoBackupFlag
, int
)
{
typedef typename mpl::or_<
NoBackupFlag
, is_nothrow_move_constructible<T>
, has_nothrow_copy<T>
>::type never_uses_backup;
return (visitation_impl_invoke_impl)(
internal_which, visitor, storage, t
, never_uses_backup()
);
}
template <typename Visitor, typename VoidPtrCV, typename NBF>
inline typename Visitor::result_type
visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
{
// should never be here at runtime!
typedef typename Visitor::result_type result_type;
return ::boost::detail::variant::forced_return< result_type >();
}
///////////////////////////////////////////////////////////////////////////////
// (detail) function template visitation_impl
//
// Invokes the given visitor on the type in the given variant storage.
//
template <
typename W, typename S
, typename Visitor, typename VPCV
, typename NBF
>
inline typename Visitor::result_type
visitation_impl(
int, int, Visitor&, VPCV
, mpl::true_ // is_apply_visitor_unrolled
, NBF, W* = BOOST_VARIANT_NULL, S* = BOOST_VARIANT_NULL
)
{
// should never be here at runtime!
typedef typename Visitor::result_type result_type;
return ::boost::detail::variant::forced_return< result_type >();
}
template <
typename Which, typename step0
, typename Visitor, typename VoidPtrCV
, typename NoBackupFlag
>
BOOST_FORCEINLINE typename Visitor::result_type
visitation_impl(
const int internal_which, const int logical_which
, Visitor& visitor, VoidPtrCV storage
, mpl::false_ // is_apply_visitor_unrolled
, NoBackupFlag no_backup_flag
, Which* = BOOST_VARIANT_NULL, step0* = BOOST_VARIANT_NULL
)
{
// Typedef apply_visitor_unrolled steps and associated types...
# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
typedef typename BOOST_PP_CAT(step,N)::next \
BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
, BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
, _
)
# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
// ...switch on the target which-index value...
switch (logical_which)
{
// ...applying the appropriate case:
# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
case (Which::value + (N)): \
return (visitation_impl_invoke)( \
internal_which, visitor, storage \
, static_cast<BOOST_PP_CAT(T,N)*>(0) \
, no_backup_flag, 1L \
); \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
, BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
, _
)
# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
default: break;
}
// If not handled in this iteration, continue unrolling:
typedef mpl::int_<
Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
> next_which;
typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
next_step;
typedef typename next_step::type next_type;
typedef typename is_same< next_type,apply_visitor_unrolled >::type
is_apply_visitor_unrolled;
return detail::variant::visitation_impl(
internal_which, logical_which
, visitor, storage
, is_apply_visitor_unrolled()
, no_backup_flag
, static_cast<next_which*>(0), static_cast<next_step*>(0)
);
}
}} // namespace detail::variant
} // namespace boost
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(pop)
#endif
#endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP

View File

@@ -0,0 +1,388 @@
//-----------------------------------------------------------------------------
// boost variant/get.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman, Itay Maman
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_GET_HPP
#define BOOST_VARIANT_GET_HPP
#include <exception>
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/detail/element_index.hpp>
#include <boost/variant/detail/move.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
namespace boost {
#if defined(BOOST_CLANG)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
#endif
//////////////////////////////////////////////////////////////////////////
// class bad_get
//
// The exception thrown in the event of a failed get of a value.
//
class BOOST_SYMBOL_VISIBLE bad_get
: public std::exception
{
public: // std::exception implementation
const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
{
return "boost::bad_get: "
"failed value get using boost::get";
}
};
#if defined(BOOST_CLANG)
# pragma clang diagnostic pop
#endif
//////////////////////////////////////////////////////////////////////////
// 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
{
private: // private typedefs
typedef typename add_pointer<T>::type pointer;
typedef typename add_reference<T>::type reference;
public: // visitor typedefs
typedef pointer result_type;
public: // visitor interfaces
pointer operator()(reference operand) const BOOST_NOEXCEPT
{
return boost::addressof(operand);
}
template <typename U>
pointer operator()(const U&) const BOOST_NOEXCEPT
{
return static_cast<pointer>(0);
}
};
}} // namespace detail::variant
#ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
# else
# if defined(BOOST_NO_CXX11_NULLPTR)
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
, t* = 0
# else
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
, t* = nullptr
# endif
# endif
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// relaxed_get<U>(variant) methods
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
typedef typename add_pointer<U>::type U_ptr;
if (!operand) return static_cast<U_ptr>(0);
detail::variant::get_visitor<U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
typedef typename add_pointer<const U>::type U_ptr;
if (!operand) return static_cast<U_ptr>(0);
detail::variant::get_visitor<const U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<U>::type U_ptr;
U_ptr result = relaxed_get<U>(boost::addressof(operand));
if (!result)
boost::throw_exception(bad_get());
return *result;
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<const U>::type U_ptr;
U_ptr result = relaxed_get<const U>(boost::addressof(operand));
if (!result)
boost::throw_exception(bad_get());
return *result;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined(BOOST_MSVC) && (_MSC_VER < 1900) // MSVC-2014 has fixed the incorrect diagnostics.
# pragma warning(push)
# pragma warning(disable: 4172) // returning address of local variable or temporary
#endif
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
U&&
relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<U>::type U_ptr;
U_ptr result = relaxed_get<U>(boost::addressof(operand));
if (!result)
boost::throw_exception(bad_get());
return static_cast<U&&>(*result);
}
#if defined(BOOST_MSVC) && (_MSC_VER < 1900)
# pragma warning(pop)
#endif
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// strict_get<U>(variant) methods
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
strict_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::get<U>(boost::variant<T...>*) will always return NULL"
);
return relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
strict_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
"boost::variant does not contain specified type U, "
"call to boost::get<U>(const boost::variant<T...>*) will always return NULL"
);
return relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
strict_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::get<U>(boost::variant<T...>&) will always throw boost::bad_get exception"
);
return relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
strict_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, const U >::value),
"boost::variant does not contain specified type U, "
"call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
);
return relaxed_get<U>(operand);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
U&&
strict_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
BOOST_STATIC_ASSERT_MSG(
(!boost::is_lvalue_reference<U>::value),
"remove ampersand '&' from template type U in boost::get<U>(boost::variant<T...>&&) "
);
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::get<U>(const boost::variant<T...>&) will always throw boost::bad_get exception"
);
return relaxed_get<U>(detail::variant::move(operand));
}
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get<U>(variant) methods
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return relaxed_get<U>(operand);
#else
return strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return relaxed_get<U>(operand);
#else
return strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return relaxed_get<U>(operand);
#else
return strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return relaxed_get<U>(operand);
#else
return strict_get<U>(operand);
#endif
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
U&&
get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return relaxed_get<U>(detail::variant::move(operand));
#else
return strict_get<U>(detail::variant::move(operand));
#endif
}
#endif
} // namespace boost
#endif // BOOST_VARIANT_GET_HPP

View File

@@ -0,0 +1,32 @@
// Boost.Varaint
// Multivisitors defined here
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright (c) 2013-2022 Antony Polukhin.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#ifndef BOOST_VARIANT_MULTIVISITORS_HPP
#define BOOST_VARIANT_MULTIVISITORS_HPP
#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/variant/variant_fwd.hpp> // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
# include <boost/variant/detail/multivisitors_cpp11_based.hpp>
# if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
# include <boost/variant/detail/multivisitors_cpp14_based.hpp>
# endif
#else
# include <boost/variant/detail/multivisitors_preprocessor_based.hpp>
#endif
#endif // BOOST_VARIANT_MULTIVISITORS_HPP

View File

@@ -0,0 +1,352 @@
//-----------------------------------------------------------------------------
// boost variant/polymorphic_get.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP
#define BOOST_VARIANT_POLYMORPHIC_GET_HPP
#include <exception>
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/get.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_const.hpp>
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class bad_polymorphic_get
//
// The exception thrown in the event of a failed get of a value.
//
class BOOST_SYMBOL_VISIBLE bad_polymorphic_get
: public bad_get
{
public: // std::exception implementation
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
{
return "boost::bad_polymorphic_get: "
"failed value get using boost::polymorphic_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 {
///////////////////////////////////////////////////////////////////////////////////////////////////
// polymorphic metafunctions to detect index of a value
//
template <class Types, class T>
struct element_polymorphic_iterator_impl :
boost::mpl::find_if<
Types,
boost::mpl::or_<
variant_element_functor<boost::mpl::_1, T>,
variant_element_functor<boost::mpl::_1, typename boost::remove_cv<T>::type >,
boost::is_base_of<T, boost::mpl::_1>
>
>
{};
template <class Variant, class T>
struct holds_element_polymorphic :
boost::mpl::not_<
boost::is_same<
typename boost::mpl::end<typename Variant::types>::type,
typename element_polymorphic_iterator_impl<typename Variant::types, typename boost::remove_reference<T>::type >::type
>
>
{};
// (detail) class template get_polymorphic_visitor
//
// Generic static visitor that: if the value is of the specified
// type or of a type derived from specified, returns a pointer
// to the value it visits; else a null pointer.
//
template <typename Base>
struct get_polymorphic_visitor
{
private: // private typedefs
typedef get_polymorphic_visitor<Base> this_type;
typedef typename add_pointer<Base>::type pointer;
typedef typename add_reference<Base>::type reference;
pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT
{
return boost::addressof(operand);
}
template <class T>
pointer get(T&, boost::false_type) const BOOST_NOEXCEPT
{
return static_cast<pointer>(0);
}
public: // visitor interfaces
typedef pointer result_type;
template <typename U>
pointer operator()(U& operand) const BOOST_NOEXCEPT
{
typedef typename boost::remove_reference<Base>::type base_t;
typedef boost::integral_constant<
bool,
(
boost::is_base_of<base_t, U>::value &&
(boost::is_const<base_t>::value || !boost::is_const<U>::value)
)
|| boost::is_same<base_t, U>::value
|| boost::is_same<typename boost::remove_cv<base_t>::type, U >::value
> tag_t;
return this_type::get(operand, tag_t());
}
};
}} // namespace detail::variant
#ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE
# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)
# else
# if defined(BOOST_NO_CXX11_NULLPTR)
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
, t* = 0
# else
# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \
, t* = nullptr
# endif
# endif
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// polymorphic_relaxed_get
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
polymorphic_relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
typedef typename add_pointer<U>::type U_ptr;
if (!operand) return static_cast<U_ptr>(0);
detail::variant::get_polymorphic_visitor<U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
polymorphic_relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
typedef typename add_pointer<const U>::type U_ptr;
if (!operand) return static_cast<U_ptr>(0);
detail::variant::get_polymorphic_visitor<const U> v;
return operand->apply_visitor(v);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
polymorphic_relaxed_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<U>::type U_ptr;
U_ptr result = polymorphic_relaxed_get<U>(&operand);
if (!result)
boost::throw_exception(bad_polymorphic_get());
return *result;
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
polymorphic_relaxed_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
typedef typename add_pointer<const U>::type U_ptr;
U_ptr result = polymorphic_relaxed_get<const U>(&operand);
if (!result)
boost::throw_exception(bad_polymorphic_get());
return *result;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// polymorphic_strict_get
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
polymorphic_strict_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::polymorphic_get<U>(boost::variant<T...>*) will always return NULL"
);
return polymorphic_relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
polymorphic_strict_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::polymorphic_get<U>(const boost::variant<T...>*) will always return NULL"
);
return polymorphic_relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
polymorphic_strict_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::polymorphic_get<U>(boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
);
return polymorphic_relaxed_get<U>(operand);
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
polymorphic_strict_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
BOOST_STATIC_ASSERT_MSG(
(boost::detail::variant::holds_element_polymorphic<boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >, U >::value),
"boost::variant does not contain specified type U, "
"call to boost::polymorphic_get<U>(const boost::variant<T...>&) will always throw boost::bad_polymorphic_get exception"
);
return polymorphic_relaxed_get<U>(operand);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// polymorphic_get<U>(variant) methods
//
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<U>::type
polymorphic_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return polymorphic_relaxed_get<U>(operand);
#else
return polymorphic_strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_pointer<const U>::type
polymorphic_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
) BOOST_NOEXCEPT
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return polymorphic_relaxed_get<U>(operand);
#else
return polymorphic_strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<U>::type
polymorphic_get(
boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return polymorphic_relaxed_get<U>(operand);
#else
return polymorphic_strict_get<U>(operand);
#endif
}
template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
inline
typename add_reference<const U>::type
polymorphic_get(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
)
{
#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
return polymorphic_relaxed_get<U>(operand);
#else
return polymorphic_strict_get<U>(operand);
#endif
}
} // namespace boost
#endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP

View File

@@ -0,0 +1,209 @@
//-----------------------------------------------------------------------------
// boost variant/recursive_variant.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_RECURSIVE_VARIANT_HPP
#define BOOST_VARIANT_RECURSIVE_VARIANT_HPP
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/detail/enable_recursive.hpp>
#include <boost/variant/detail/substitute_fwd.hpp>
#include <boost/variant/detail/make_variant_list.hpp>
#include <boost/variant/detail/over_sequence.hpp>
#include <boost/mpl/aux_/lambda_arity_param.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/protect.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/variant/variant.hpp>
namespace boost {
namespace detail { namespace variant {
///////////////////////////////////////////////////////////////////////////////
// (detail) metafunction specialization substitute
//
// Handles embedded variant types when substituting for recursive_variant_.
//
#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
template <
BOOST_VARIANT_ENUM_PARAMS(typename T)
, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct substitute<
::boost::variant<
recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
>
, RecursiveVariant
, ::boost::recursive_variant_
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
typedef ::boost::variant<
recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
> type;
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T)
, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct substitute<
::boost::variant<
::boost::detail::variant::over_sequence< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
>
, RecursiveVariant
, ::boost::recursive_variant_
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
private:
typedef T0 initial_types;
typedef typename mpl::transform<
initial_types
, mpl::protect< quoted_enable_recursive<RecursiveVariant,mpl::true_> >
>::type types;
public:
typedef typename mpl::if_<
mpl::equal<initial_types, types, ::boost::is_same<mpl::_1, mpl::_2> >
, ::boost::variant<
::boost::detail::variant::over_sequence< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
>
, ::boost::variant< over_sequence<types> >
>::type type;
};
template <
BOOST_VARIANT_ENUM_PARAMS(typename T)
, typename RecursiveVariant
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity)
>
struct substitute<
::boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >
, RecursiveVariant
, ::boost::recursive_variant_
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity)
>
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
typedef ::boost::variant<
typename enable_recursive<
T0
, RecursiveVariant
, mpl::true_
>::type,
typename enable_recursive<
TN
, RecursiveVariant
, mpl::true_
>::type...
> type;
#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
private: // helpers, for metafunction result (below)
#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
typedef typename enable_recursive< \
BOOST_PP_CAT(T,N) \
, RecursiveVariant \
, mpl::true_ \
>::type BOOST_PP_CAT(wknd_T,N); \
/**/
BOOST_PP_REPEAT(
BOOST_VARIANT_LIMIT_TYPES
, BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
, _
)
#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
public: // metafunction result
typedef ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(wknd_T) > type;
#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
};
#else // defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
//
// no specializations: embedded variants unsupported on these compilers!
//
#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
}} // namespace detail::variant
///////////////////////////////////////////////////////////////////////////////
// metafunction make_recursive_variant
//
// See docs and boost/variant/variant_fwd.hpp for more information.
//
template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
struct make_recursive_variant
{
public: // metafunction result
typedef boost::variant<
detail::variant::recursive_flag< T0 >
, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
> type;
};
///////////////////////////////////////////////////////////////////////////////
// metafunction make_recursive_variant_over
//
// See docs and boost/variant/variant_fwd.hpp for more information.
//
template <typename Types>
struct make_recursive_variant_over
{
private: // precondition assertions
BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
public: // metafunction result
typedef typename make_recursive_variant<
detail::variant::over_sequence< Types >
>::type type;
};
} // namespace boost
#endif // BOOST_VARIANT_RECURSIVE_VARIANT_HPP

View File

@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
// boost variant/recursive_wrapper.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_HPP
#define BOOST_VARIANT_RECURSIVE_WRAPPER_HPP
#include <boost/variant/recursive_wrapper_fwd.hpp>
#include <boost/variant/detail/move.hpp>
#include <boost/checked_delete.hpp>
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class template recursive_wrapper
//
// See docs and recursive_wrapper_fwd.hpp for more information.
//
template <typename T>
class recursive_wrapper
{
public: // typedefs
typedef T type;
private: // representation
T* p_;
public: // structors
~recursive_wrapper();
recursive_wrapper();
recursive_wrapper(const recursive_wrapper& operand);
recursive_wrapper(const T& operand);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
recursive_wrapper(recursive_wrapper&& operand);
recursive_wrapper(T&& operand);
#endif
private: // helpers, for modifiers (below)
void assign(const T& rhs);
public: // modifiers
recursive_wrapper& operator=(const recursive_wrapper& rhs)
{
assign( rhs.get() );
return *this;
}
recursive_wrapper& operator=(const T& rhs)
{
assign( rhs );
return *this;
}
void swap(recursive_wrapper& operand) BOOST_NOEXCEPT
{
T* temp = operand.p_;
operand.p_ = p_;
p_ = temp;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
recursive_wrapper& operator=(recursive_wrapper&& rhs) BOOST_NOEXCEPT
{
swap(rhs);
return *this;
}
recursive_wrapper& operator=(T&& rhs)
{
get() = detail::variant::move(rhs);
return *this;
}
#endif
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>
recursive_wrapper<T>::~recursive_wrapper()
{
boost::checked_delete(p_);
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper()
: p_(new T)
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(const recursive_wrapper& operand)
: p_(new T( operand.get() ))
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(const T& operand)
: p_(new T(operand))
{
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename T>
recursive_wrapper<T>::recursive_wrapper(recursive_wrapper&& operand)
: p_(new T( detail::variant::move(operand.get()) ))
{
}
template <typename T>
recursive_wrapper<T>::recursive_wrapper(T&& operand)
: p_(new T( detail::variant::move(operand) ))
{
}
#endif
template <typename T>
void recursive_wrapper<T>::assign(const T& rhs)
{
this->get() = rhs;
}
// function template swap
//
// Swaps two recursive_wrapper<T> objects of the same type T.
//
template <typename T>
inline void swap(recursive_wrapper<T>& lhs, recursive_wrapper<T>& rhs) BOOST_NOEXCEPT
{
lhs.swap(rhs);
}
} // namespace boost
#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_HPP

View File

@@ -0,0 +1,130 @@
//-----------------------------------------------------------------------------
// boost variant/recursive_wrapper_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002 Eric Friedman, Itay Maman
// Copyright (c) 2016-2022 Antony Polukhin
//
// Portions Copyright (C) 2002 David Abrahams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
#define BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
#include <boost/mpl/bool.hpp>
#include <boost/mpl/aux_/config/ctps.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
namespace boost {
//////////////////////////////////////////////////////////////////////////
// class template recursive_wrapper
//
// Enables recursive types in templates by breaking cyclic dependencies.
//
// For example:
//
// class my;
//
// typedef variant< int, recursive_wrapper<my> > var;
//
// class my {
// var var_;
// ...
// };
//
template <typename T> class recursive_wrapper;
///////////////////////////////////////////////////////////////////////////////
// metafunction is_constructible partial specializations.
//
// recursive_wrapper<T> is constructible only from T and recursive_wrapper<T>.
//
template <class T> struct is_constructible<recursive_wrapper<T>, T> : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, const T> : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, T&> : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, const T&> : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, recursive_wrapper<T> > : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, const recursive_wrapper<T> > : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, recursive_wrapper<T>& > : boost::true_type{};
template <class T> struct is_constructible<recursive_wrapper<T>, const recursive_wrapper<T>& > : boost::true_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, U > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, const U > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, U& > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, const U& > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, recursive_wrapper<U> > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, const recursive_wrapper<U> > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, recursive_wrapper<U>& > : boost::false_type{};
template <class T, class U> struct is_constructible<recursive_wrapper<T>, const recursive_wrapper<U>& > : boost::false_type{};
// recursive_wrapper is not nothrow move constructible, because it's constructor does dynamic memory allocation.
// This specialisation is required to workaround GCC6 issue: https://svn.boost.org/trac/boost/ticket/12680
template <class T> struct is_nothrow_move_constructible<recursive_wrapper<T> > : boost::false_type{};
///////////////////////////////////////////////////////////////////////////////
// metafunction is_recursive_wrapper (modeled on code by David Abrahams)
//
// True if specified type matches recursive_wrapper<T>.
//
namespace detail {
template <typename T>
struct is_recursive_wrapper_impl
: mpl::false_
{
};
template <typename T>
struct is_recursive_wrapper_impl< recursive_wrapper<T> >
: mpl::true_
{
};
} // namespace detail
template< typename T > struct is_recursive_wrapper
: public ::boost::integral_constant<bool,(::boost::detail::is_recursive_wrapper_impl<T>::value)>
{
public:
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_recursive_wrapper,(T))
};
///////////////////////////////////////////////////////////////////////////////
// metafunction unwrap_recursive
//
// If specified type T matches recursive_wrapper<U>, then U; else T.
//
template <typename T>
struct unwrap_recursive
{
typedef T type;
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,unwrap_recursive,(T))
};
template <typename T>
struct unwrap_recursive< recursive_wrapper<T> >
{
typedef T type;
BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(1,unwrap_recursive,(T))
};
} // namespace boost
#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP

View File

@@ -0,0 +1,93 @@
//-----------------------------------------------------------------------------
// boost variant/static_visitor.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_STATIC_VISITOR_HPP
#define BOOST_VARIANT_STATIC_VISITOR_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/mpl/aux_/lambda_support.hpp>
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 { };
typedef void static_visitor_default_return;
} // namespace detail
template <typename R = ::boost::detail::static_visitor_default_return>
class static_visitor
: public detail::is_static_visitor_tag
{
public: // typedefs
typedef R result_type;
protected: // for use as base class only
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
static_visitor() = default;
#else
static_visitor() BOOST_NOEXCEPT { }
#endif
};
//////////////////////////////////////////////////////////////////////////
// metafunction is_static_visitor
//
// Value metafunction indicates whether the specified type derives from
// static_visitor<...>.
//
// NOTE #1: This metafunction does NOT check whether the specified type
// fulfills the requirements of the StaticVisitor concept.
//
// NOTE #2: This template never needs to be specialized!
//
namespace detail {
template <typename T>
struct is_static_visitor_impl
{
BOOST_STATIC_CONSTANT(bool, value =
(::boost::is_base_and_derived<
detail::is_static_visitor_tag,
T
>::value));
};
} // namespace detail
template< typename T > struct is_static_visitor
: public ::boost::integral_constant<bool,(::boost::detail::is_static_visitor_impl<T>::value)>
{
public:
BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_static_visitor,(T))
};
} // namespace boost
#endif // BOOST_VARIANT_STATIC_VISITOR_HPP

View File

@@ -0,0 +1,322 @@
//-----------------------------------------------------------------------------
// 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
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_VARIANT_VARIANT_FWD_HPP
#define BOOST_VARIANT_VARIANT_FWD_HPP
#include <boost/variant/detail/config.hpp>
#include <boost/blank_fwd.hpp>
#include <boost/mpl/arg.hpp>
#include <boost/mpl/limits/arity.hpp>
#include <boost/mpl/aux_/na.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/enum.hpp>
#include <boost/preprocessor/enum_params.hpp>
#include <boost/preprocessor/enum_shifted_params.hpp>
#include <boost/preprocessor/repeat.hpp>
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
//
// Defined if variant does not support make_variant_over (see below).
//
#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
#endif
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
//
// Defined if make_recursive_variant cannot be supported as documented.
//
// Note: Currently, MPL lambda facility is used as workaround if defined, and
// so only types declared w/ MPL lambda workarounds will work.
//
#include <boost/variant/detail/substitute_fwd.hpp>
#if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \
&& !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
# define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
#endif
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
//
/*
GCC before 4.0 had no variadic tempaltes;
GCC 4.6 has incomplete implementation of variadic templates.
MSVC2015 Update 1 has variadic templates, but they have issues.
NOTE: Clang compiler defines __GNUC__
*/
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
|| (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) \
|| (defined(_MSC_VER) && (_MSC_VER <= 1900)) \
|| defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) \
|| defined (BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
# define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
#endif
#endif
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
#include <boost/preprocessor/seq/size.hpp>
#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_class class)(
#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_typename typename)(
#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_class class...
#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_typename typename...
#define ARGS_VARIADER_1(x) x ## N...
#define ARGS_VARIADER_2(x) BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_ ## x ## N
#define BOOST_VARIANT_MAKE_VARIADIC(sequence, x) BOOST_VARIANT_MAKE_VARIADIC_I(BOOST_PP_SEQ_SIZE(sequence), x)
#define BOOST_VARIANT_MAKE_VARIADIC_I(argscount, x) BOOST_VARIANT_MAKE_VARIADIC_II(argscount, x)
#define BOOST_VARIANT_MAKE_VARIADIC_II(argscount, orig) ARGS_VARIADER_ ## argscount(orig)
///////////////////////////////////////////////////////////////////////////////
// BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS
//
// Convenience macro for enumeration of variant params.
// When variadic templates are available expands:
// BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN
// BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN
// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN
// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN
// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
//
// Rationale: Cleaner, simpler code for clients of variant library. Minimal
// code modifications to move from C++03 to C++11.
//
// With BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES defined
// will be used BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS from below `#else`
//
#define BOOST_VARIANT_ENUM_PARAMS(x) \
x ## 0, \
BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \
/**/
#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS(x) \
BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \
/**/
#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_LIMIT_TYPES
//
// Implementation-defined preprocessor symbol describing the actual
// length of variant's pseudo-variadic template parameter list.
//
#include <boost/mpl/limits/list.hpp>
#define BOOST_VARIANT_LIMIT_TYPES \
BOOST_MPL_LIMIT_LIST_SIZE
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY
//
// Exposes maximum allowed arity of class templates with recursive_variant
// arguments. That is,
// make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >.
//
#include <boost/mpl/limits/arity.hpp>
#define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \
BOOST_MPL_LIMIT_METAFUNCTION_ARITY
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_ENUM_PARAMS
//
// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params.
//
// Rationale: Cleaner, simpler code for clients of variant library.
//
#define BOOST_VARIANT_ENUM_PARAMS( param ) \
BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
///////////////////////////////////////////////////////////////////////////////
// macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS
//
// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params.
//
#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \
BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
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::na 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::na 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::na 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
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
# define BOOST_VARIANT_AUX_DECLARE_PARAMS BOOST_VARIANT_ENUM_PARAMS(typename T)
#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
///////////////////////////////////////////////////////////////////////////////
// (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM
//
// Template parameter list for variant and recursive_variant declarations.
//
#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
typename BOOST_PP_CAT(T,N) = detail::variant::void_ \
/**/
#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \
/**/
#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
#define BOOST_VARIANT_AUX_DECLARE_PARAMS \
BOOST_PP_ENUM( \
BOOST_VARIANT_LIMIT_TYPES \
, BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \
, T \
) \
/**/
#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
///////////////////////////////////////////////////////////////////////////////
// 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)
//
template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant;
///////////////////////////////////////////////////////////////////////////////
// metafunction make_recursive_variant
//
// Exposes a boost::variant with recursive_variant_ tags (below) substituted
// with the variant itself (wrapped as needed with boost::recursive_wrapper).
//
template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant;
#undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL
#undef BOOST_VARIANT_AUX_DECLARE_PARAMS
///////////////////////////////////////////////////////////////////////////////
// type recursive_variant_
//
// Tag type indicates where recursive variant substitution should occur.
//
#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
struct recursive_variant_ {};
#else
typedef mpl::arg<1> recursive_variant_;
#endif
///////////////////////////////////////////////////////////////////////////////
// metafunction make_variant_over
//
// Result is a variant w/ types of the specified type sequence.
//
template <typename Types> struct make_variant_over;
///////////////////////////////////////////////////////////////////////////////
// metafunction make_recursive_variant_over
//
// Result is a recursive variant w/ types of the specified type sequence.
//
template <typename Types> struct make_recursive_variant_over;
} // namespace boost
#endif // BOOST_VARIANT_VARIANT_FWD_HPP

View File

@@ -0,0 +1,88 @@
//-----------------------------------------------------------------------------
// boost variant/visitor_ptr.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002-2003
// Eric Friedman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#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/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_void.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 mpl::eval_if<
is_reference<T>
, mpl::identity<T>
, add_reference<const T>
>::type argument_fwd_type;
public: // structors
explicit visitor_ptr_t(visitor_t visitor) BOOST_NOEXCEPT
: visitor_(visitor)
{
}
public: // static visitor interfaces
template <typename U>
result_type operator()(const U&) const
{
boost::throw_exception(bad_visit());
}
public: // static visitor interfaces, cont.
result_type operator()(argument_fwd_type operand) const
{
return visitor_(operand);
}
};
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

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<!--
Copyright 2014-2022 Antony Polukhin
antoshkka at gmail dot com
Distributed under the Boost Software License,
Version 1.0. (See accompanying file LICENSE_1_0.txt
or copy at http://boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; URL=../../doc/html/variant.html">
<title>Boost.Variant</title>
<style>
body {
background: #fff;
color: #000;
}
a {
color: #00f;
text-decoration: none;
}
</style>
</head>
<body>
<p>
Automatic redirection failed, please go to
<a href="../../doc/html/variant.html">../../doc/html/variant.html</a>
</p>
<p>
&copy; 2014-2022 Antony Polukhin
</p>
</body>
</html>

View File

@@ -0,0 +1,18 @@
{
"key": "variant",
"name": "Variant",
"authors": [
"Eric Friedman",
"Itay Maman"
],
"description": "Safe, generic, stack-based discriminated union container.",
"category": [
"Containers",
"Data"
],
"maintainers": [
"Antony Polukhin <antoshkka -at- gmail.com>",
"Eric Friedman <ericbrandon -at- gmail.com>"
],
"cxxstd": "03"
}

View File

@@ -0,0 +1,29 @@
#==============================================================================
# Copyright (c) 2012-2022 Antony Polukhin
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#==============================================================================
# performance tests
import testing ;
import path ;
path-constant TEST_DIR : . ;
project performance/test
: source-location ./
: requirements
# <library>/boost/chrono//boost_chrono
# <library>/boost/system//boost_system
<link>static
<target-os>freebsd:<linkflags>"-lrt"
<target-os>linux:<linkflags>"-lrt"
<toolset>gcc:<cxxflags>-fvisibility=hidden
<toolset>intel-linux:<cxxflags>-fvisibility=hidden
<toolset>sun:<cxxflags>-xldscope=hidden
: default-build release
;
run move_perf.cpp : $(TEST_DIR) ;

View File

@@ -0,0 +1,236 @@
// (C) Copyright Antony Polukhin 2012-2021.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/config for most recent version.
//
// Testing variant performance rvalue copy/assign performance
//
#define BOOST_ERROR_CODE_HEADER_ONLY
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono.hpp>
#include <boost/variant.hpp>
#include <string>
#include <vector>
struct scope {
typedef boost::chrono::steady_clock test_clock;
typedef boost::chrono::milliseconds duration_t;
test_clock::time_point start_;
const char* const message_;
explicit scope(const char* const message)
: start_(test_clock::now())
, message_(message)
{}
~scope() {
std::cout << message_ << " " << boost::chrono::duration_cast<duration_t>(test_clock::now() - start_) << std::endl;
}
};
static void do_test(bool do_count_cleanup_time = false) {
BOOST_STATIC_CONSTANT(std::size_t, c_run_count = 5000000);
typedef std::vector<char> str_t;
typedef boost::variant<int, str_t, float> var_t;
const char hello1_c[] = "hello long word";
const str_t hello1(hello1_c, hello1_c + sizeof(hello1_c));
const char hello2_c[] = "Helllloooooooooooooooooooooooooooooooo!!!!!!!!!!!!!";
const str_t hello2(hello2_c, hello2_c + sizeof(hello2_c));
if (do_count_cleanup_time) {
std::cout << "#############################################\n";
std::cout << "#############################################\n";
std::cout << "NOW TIMES WITH DATA DESTRUCTION\n";
std::cout << "#############################################\n";
}
std::vector<var_t> data_from, data_to;
data_from.resize(c_run_count, hello1);
data_to.reserve(c_run_count);
{
scope sc("boost::variant(const variant&) copying speed");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to.push_back(data_from[i]);
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
data_from.resize(c_run_count, hello1);
data_to.clear();
data_to.reserve(c_run_count);
{
scope sc("boost::variant(variant&&) moving speed");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to.push_back(boost::move(data_from[i]));
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
std::cout << "#############################################\n";
data_from.clear();
data_from.resize(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, hello2);
{
scope sc("boost::variant=(const variant&) copying speed on same types");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = data_from[i];
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
data_from.resize(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, hello2);
{
scope sc("boost::variant=(variant&&) moving speed on same types");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = boost::move(data_from[i]);
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
std::cout << "#############################################\n";
data_from.clear();
data_from.resize(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, var_t(0));
{
scope sc("boost::variant=(const variant&) copying speed on different types");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = data_from[i];
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
data_from.resize(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, var_t(0));
{
scope sc("boost::variant=(variant&&) moving speed on different types");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = boost::move(data_from[i]);
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
std::cout << "#############################################\n";
data_from.clear();
data_from.resize(c_run_count, var_t(0));
data_to.clear();
data_to.resize(c_run_count, hello2);
{
scope sc("boost::variant=(const variant&) copying speed on different types II");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = data_from[i];
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
data_from.resize(c_run_count, var_t(0));
data_to.clear();
data_to.resize(c_run_count, hello2);
{
scope sc("boost::variant=(variant&&) moving speed on different types II");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = boost::move(data_from[i]);
}
if (do_count_cleanup_time) {
data_to.clear();
data_from.clear();
}
}
std::cout << "#############################################\n";
std::vector<str_t> s1(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, var_t(0));
{
scope sc("boost::variant=(const T&) copying speed");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = s1[i];
}
if (do_count_cleanup_time) {
data_to.clear();
s1.clear();
}
}
std::vector<str_t> s2(c_run_count, hello2);
data_to.clear();
data_to.resize(c_run_count, var_t(0));
{
scope sc("boost::variant=(T&&) moving speed");
for (std::size_t i = 0; i < c_run_count; ++i) {
data_to[i] = boost::move(s2[i]);
}
if (do_count_cleanup_time) {
data_to.clear();
s2.clear();
}
}
}
int main () {
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
std::cout << "# Running tests in C++11 mode (with rvalues).\n";
#else
std::cout << "# Running tests in C++03 mode (without rvalues).\n";
#endif
do_test(false);
do_test(true);
}

View File

@@ -0,0 +1,69 @@
# Boost.Variant Library test Jamfile
#
# Copyright (C) 2003, Eric Friedman, Itay Maman.
# Copyright (C) 2013-2022 Antony Polukhin.
#
# Use, modification and distribution is subject to the Boost Software License,
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
import testing ;
local below_cpp11 = 98 03 ;
local below_cpp14 = 98 03 0x 11 ;
local since_cpp20 = 2a 20 latest ;
project
: requirements
<toolset>msvc:<asynch-exceptions>on
;
test-suite variant
:
[ run test1.cpp class_a.cpp : : : : variant_test1 ]
[ run test2.cpp : : : : variant_test2 ]
[ run test3.cpp : : : : variant_test3 ]
[ run test3.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : variant_test3_no_rtti ]
[ run test4.cpp class_a.cpp : : : : variant_test4 ]
[ run test5.cpp : : : : variant_test5 ]
[ run test6.cpp : : : : variant_test6 ]
[ run test7.cpp : : : : variant_test7 ]
[ run test8.cpp : : : : variant_test8 ]
[ run test9.cpp : : : : variant_test9 ]
[ run recursive_variant_test.cpp ]
[ run variant_reference_test.cpp ]
[ run variant_comparison_test.cpp ]
[ run variant_visit_internal_linkage.cpp : : : "<cxxstd>$(below_cpp14)"\:<build>no ]
[ run variant_visit_test.cpp ]
[ run variant_get_test.cpp ]
[ compile-fail variant_rvalue_get_with_ampersand_test.cpp ]
[ compile-fail no_rvalue_to_nonconst_visitation.cpp ]
[ compile fusion_interop.cpp : "<cxxstd>$(below_cpp11)"\:<build>no ]
[ run variant_polymorphic_get_test.cpp ]
[ run variant_multivisit_test.cpp ]
[ run hash_variant_test.cpp ]
[ run rvalue_test.cpp ]
[ run variant_nonempty_check.cpp ]
[ run recursive_variant_test.cpp : : : <define>BOOST_NO_EXCEPTIONS
<toolset>gcc-4.3:<cxxflags>-fno-exceptions
<toolset>gcc-4.4:<cxxflags>-fno-exceptions
<toolset>gcc-4.5:<cxxflags>-fno-exceptions
<toolset>gcc-4.6:<cxxflags>-fno-exceptions
<toolset>gcc-4.7:<cxxflags>-fno-exceptions
<toolset>gcc-4.8:<cxxflags>-fno-exceptions
<toolset>clang:<cxxflags>-fno-exceptions
: variant_noexcept_test
]
[ run recursive_variant_test.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : variant_no_rtti_test ]
[ run hash_recursive_variant_test.cpp ]
[ run variant_swap_test.cpp ]
[ run auto_visitors.cpp ]
[ run issue42.cpp ]
[ run issue53.cpp ]
[ run overload_selection.cpp : : : "<cxxstd>$(since_cpp20)"\:<build>no ]
[ run recursive_wrapper_move_test.cpp ]
[ run variant_over_joint_view_test.cpp ]
[ run const_ref_apply_visitor.cpp ]
;

View File

@@ -0,0 +1,94 @@
# Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Copyright Antony Polukhin 2016-2021.
#
# See https://svn.boost.org/trac/boost/wiki/TravisCoverals for description of this file
# and how it can be used with Boost libraries.
#
# File revision #7
init:
# boost-local/libs/ folder to put this library into. This may be useful, if you're for example running Travis
# from `Boost.DLL` repo while Boost already has `dll` and with to replace `dll` with content of`Boost.DLL`.
#
# Otherwise just leave the default value - set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
- set BOOST_LIBS_FOLDER=%APPVEYOR_PROJECT_NAME%
###############################################################################################################
# From this point and below code is same for all the Boost libs
###############################################################################################################
version: 1.71.{build}-{branch}
# branches to build
branches:
except:
- gh-pages
skip_tags: true
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
ADDRMD: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1,clang-win
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
VARIANT: release # "variant_get_test.o: File too big" errors in debug
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
VARIANT: release # "variant_get_test.o: File too big" errors in debug
before_build:
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- echo "Testing %APPVEYOR_PROJECT_NAME%"
# Cloning Boost libraries (fast nondeep cloning)
- set BOOST=C:/boost-local
- git clone -b %BOOST_BRANCH% --depth 10 https://github.com/boostorg/boost.git %BOOST%
- cd %BOOST%
- git submodule update --init --depth 10 tools/build tools/boostdep
- rm -rf %BOOST%/libs/%BOOST_LIBS_FOLDER%
- mv -f %APPVEYOR_BUILD_FOLDER% %BOOST%/libs/%BOOST_LIBS_FOLDER%
- python tools/boostdep/depinst/depinst.py --git_args "--depth 10 --jobs 2" %BOOST_LIBS_FOLDER%
build_script:
- cmd /c bootstrap
- b2.exe headers
- cd %BOOST%/libs/%BOOST_LIBS_FOLDER%/test
after_build:
before_test:
test_script:
- PATH=%ADDPATH%%PATH%
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- if "%VARIANT%"== "" set VARIANT=debug,release
- set VARIANT=variant=%VARIANT%
- echo "Running command ..\..\..\b2 -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release"
- ..\..\..\b2.exe -j3 toolset=%TOOLSET% %CXXSTD% %ADDRMD% %VARIANT% cxxflags="-DBOOST_TRAVISCI_BUILD"
after_test:
on_success:
on_failure:
on_finish:

View File

@@ -0,0 +1,380 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/auto_visitors.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "boost/variant/multivisitors.hpp"
#include "boost/lexical_cast.hpp"
#include <boost/noncopyable.hpp>
#include <boost/core/ignore_unused.hpp>
namespace has_result_type_tests {
template <class T>
struct wrap {
typedef T result_type;
};
struct s1 : wrap<int> {};
struct s2 : wrap<int&> {};
struct s3 : wrap<const int&> {};
struct s4 {};
struct s5 : wrap<int*> {};
struct s6 : wrap<int**> {};
struct s7 : wrap<const int*> {};
struct s8 : wrap<boost::noncopyable> {};
struct s9 : wrap<boost::noncopyable&> {};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
struct s10 : wrap<boost::noncopyable&&> {};
#endif
struct s11 : wrap<const boost::noncopyable&> {};
struct s12 : wrap<const boost::noncopyable*> {};
struct s13 : wrap<boost::noncopyable*> {};
struct s14 { typedef int result_type; };
struct s15 { typedef int& result_type; };
struct s16 { typedef const int& result_type; };
}
void test_has_result_type_triat() {
using namespace has_result_type_tests;
using boost::detail::variant::has_result_type;
BOOST_TEST(has_result_type<s1>::value);
BOOST_TEST(has_result_type<s2>::value);
BOOST_TEST(has_result_type<s3>::value);
BOOST_TEST(!has_result_type<s4>::value);
BOOST_TEST(has_result_type<s5>::value);
BOOST_TEST(has_result_type<s6>::value);
BOOST_TEST(has_result_type<s7>::value);
BOOST_TEST(has_result_type<s8>::value);
BOOST_TEST(has_result_type<s9>::value);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_TEST(has_result_type<s10>::value);
#endif
BOOST_TEST(has_result_type<s11>::value);
BOOST_TEST(has_result_type<s12>::value);
BOOST_TEST(has_result_type<s13>::value);
BOOST_TEST(has_result_type<s14>::value);
BOOST_TEST(has_result_type<s15>::value);
BOOST_TEST(has_result_type<s16>::value);
}
struct lex_streamer_explicit: boost::static_visitor<std::string> {
template <class T>
const char* operator()(const T& ) {
return "10";
}
template <class T1, class T2>
const char* operator()(const T1& , const T2& ) {
return "100";
}
};
void run_explicit()
{
typedef boost::variant<int, std::string, double> variant_type;
variant_type v2("10"), v1("100");
lex_streamer_explicit visitor_ref;
// Must return instance of std::string
BOOST_TEST(boost::apply_visitor(visitor_ref, v2).c_str() == std::string("10"));
BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1).c_str() == std::string("100"));
}
// Most part of tests from this file require decltype(auto)
#ifdef BOOST_NO_CXX14_DECLTYPE_AUTO
void run()
{
BOOST_TEST(true);
}
void run2()
{
BOOST_TEST(true);
}
void run3()
{
BOOST_TEST(true);
}
#else
#include <iostream>
struct lex_streamer {
template <class T>
std::string operator()(const T& val) const {
return boost::lexical_cast<std::string>(val);
}
};
struct lex_streamer_void {
template <class T>
void operator()(const T& val) const {
std::cout << val << std::endl;
}
template <class T1, class T2>
void operator()(const T1& val, const T2& val2) const {
std::cout << val << '+' << val2 << std::endl;
}
template <class T1, class T2, class T3>
void operator()(const T1& val, const T2& val2, const T3& val3) const {
std::cout << val << '+' << val2 << '+' << val3 << std::endl;
}
};
struct lex_streamer2 {
std::string res;
template <class T>
const char* operator()(const T& /*val*/) const {
return "fail";
}
template <class T1, class T2>
const char* operator()(const T1& /*v1*/, const T2& /*v2*/) const {
return "fail2";
}
template <class T1, class T2, class T3>
const char* operator()(const T1& /*v1*/, const T2& /*v2*/, const T3& /*v3*/) const {
return "fail3";
}
template <class T>
std::string& operator()(const T& val) {
res = boost::lexical_cast<std::string>(val);
return res;
}
template <class T1, class T2>
std::string& operator()(const T1& v1, const T2& v2) {
res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2);
return res;
}
template <class T1, class T2, class T3>
std::string& operator()(const T1& v1, const T2& v2, const T3& v3) {
res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2)
+ "+" + boost::lexical_cast<std::string>(v3);
return res;
}
};
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
# define BOOST_TEST_IF_HAS_VARIADIC(x) BOOST_TEST(x)
#else
# define BOOST_TEST_IF_HAS_VARIADIC(x) /**/
#endif
void run()
{
typedef boost::variant<int, std::string, double> variant_type;
variant_type v1(1), v2("10"), v3(100.0);
lex_streamer lex_streamer_visitor;
BOOST_TEST(boost::apply_visitor(lex_streamer(), v1) == "1");
BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v1) == "1");
BOOST_TEST(boost::apply_visitor(lex_streamer(), v2) == "10");
BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v2) == "10");
#ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v1) == "1");
BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v2) == "10");
// Retun type must be the same in all instances, so this code does not compile
//boost::variant<int, short, unsigned> v_diff_types(1);
//BOOST_TEST(boost::apply_visitor([](auto v) { return v; }, v_diff_types) == 1);
boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v1);
boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v2);
#endif
lex_streamer2 visitor_ref;
BOOST_TEST(boost::apply_visitor(visitor_ref, v1) == "1");
BOOST_TEST(boost::apply_visitor(visitor_ref, v2) == "10");
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1);
BOOST_TEST(ref_to_string == "1");
#endif
lex_streamer_void lex_streamer_void_visitor;
boost::apply_visitor(lex_streamer_void(), v1);
boost::apply_visitor(lex_streamer_void(), v2);
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
boost::apply_visitor(lex_streamer_void_visitor)(v2);
#endif
boost::ignore_unused(lex_streamer_visitor, visitor_ref, lex_streamer_void_visitor);
}
struct lex_combine {
template <class T1, class T2>
std::string operator()(const T1& v1, const T2& v2) const {
return boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2);
}
template <class T1, class T2, class T3>
std::string operator()(const T1& v1, const T2& v2, const T3& v3) const {
return boost::lexical_cast<std::string>(v1) + "+"
+ boost::lexical_cast<std::string>(v2) + '+'
+ boost::lexical_cast<std::string>(v3);
}
};
void run2()
{
typedef boost::variant<int, std::string, double> variant_type;
variant_type v1(1), v2("10"), v3(100.0);
lex_combine lex_combine_visitor;
BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2) == "1+10");
BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1) == "10+1");
BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_combine_visitor)(v2, v1) == "10+1");
#ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
BOOST_TEST(
boost::apply_visitor(
[](auto v1, auto v2) {
return boost::lexical_cast<std::string>(v1) + "+"
+ boost::lexical_cast<std::string>(v2);
}
, v1
, v2
) == "1+10"
);
BOOST_TEST(
boost::apply_visitor(
[](auto v1, auto v2) {
return boost::lexical_cast<std::string>(v1) + "+"
+ boost::lexical_cast<std::string>(v2);
}
, v2
, v1
) == "10+1"
);
boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v1, v2);
boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v2, v1);
#endif
lex_streamer2 visitor_ref;
BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10");
BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1) == "10+1");
#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
std::string& ref_to_string = boost::apply_visitor(visitor_ref)(v1, v2);
BOOST_TEST(ref_to_string == "1+10");
#endif
boost::apply_visitor(lex_streamer_void(), v1, v2);
boost::apply_visitor(lex_streamer_void(), v2, v1);
boost::ignore_unused(lex_combine_visitor, visitor_ref);
}
#undef BOOST_TEST_IF_HAS_VARIADIC
void run3()
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
typedef boost::variant<int, std::string, double> variant_type;
variant_type v1(1), v2("10"), v3(100);
lex_combine lex_combine_visitor;
BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2, v3) == "1+10+100");
BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1, v3) == "10+1+100");
BOOST_TEST(boost::apply_visitor(lex_combine_visitor)(v2, v1, v3) == "10+1+100");
#ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
BOOST_TEST(
boost::apply_visitor(
[](auto v1, auto v2, auto v3) {
return boost::lexical_cast<std::string>(v1) + "+"
+ boost::lexical_cast<std::string>(v2) + "+"
+ boost::lexical_cast<std::string>(v3);
}
, v1
, v2
, v3
) == "1+10+100"
);
BOOST_TEST(
boost::apply_visitor(
[](auto v1, auto v2, auto v3) {
return boost::lexical_cast<std::string>(v1) + "+"
+ boost::lexical_cast<std::string>(v2) + "+"
+ boost::lexical_cast<std::string>(v3);
}
, v3
, v1
, v3
) == "100+1+100"
);
boost::apply_visitor(
[](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; },
v1, v2, v3
);
boost::apply_visitor(
[](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; },
v2, v1, v3
);
#endif
lex_streamer2 visitor_ref;
BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10");
BOOST_TEST(boost::apply_visitor(visitor_ref)(v2, v1) == "10+1");
std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1, v2);
BOOST_TEST(ref_to_string == "1+10");
lex_streamer_void lex_streamer_void_visitor;
boost::apply_visitor(lex_streamer_void(), v1, v2, v1);
boost::apply_visitor(lex_streamer_void(), v2, v1, v1);
boost::apply_visitor(lex_streamer_void_visitor)(v2, v1, v1);
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
}
#endif
int main()
{
run_explicit();
run();
run2();
run3();
test_has_result_type_triat();
return boost::report_errors();
}

View File

@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/class_a.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <algorithm> // for std::swap
#include <sstream>
#include <iostream>
#include <boost/assert.hpp>
#include "class_a.h"
using namespace std;
class_a::~class_a()
{
BOOST_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() << ")";
}

View File

@@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// boost-libs variant/libs/test/class_a.h header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#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_

View File

@@ -0,0 +1,417 @@
// Copyright (c) 2017 Levon Tarakchyan
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "boost/variant/apply_visitor.hpp"
#include "boost/variant/multivisitors.hpp"
#include "boost/lexical_cast.hpp"
#define lcs(val) boost::lexical_cast<std::string>(val)
struct construction_logger
{
int val_;
construction_logger(int val) : val_(val)
{
std::cout << val_ << " constructed\n";
}
construction_logger(const construction_logger& cl) :
val_(cl.val_)
{
std::cout << val_ << " copy constructed\n";
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
construction_logger(construction_logger&& cl) :
val_(cl.val_)
{
std::cout << val_ << " move constructed\n";
}
#endif
friend std::ostream& operator << (std::ostream& os, const construction_logger& cl)
{
return os << cl.val_;
}
friend std::istream& operator << (std::istream& is, construction_logger& cl)
{
return is >> cl.val_;
}
};
struct lex_streamer_explicit : boost::static_visitor<std::string>
{
template <class T>
std::string operator()(const T& val) const
{
return lcs(val);
}
template <class T, class V>
std::string operator()(const T& val, const V& val2) const
{
return lcs(val) + '+' + lcs(val2);
}
template <class T, class V, class P, class S>
std::string operator()(const T& val, const V& val2, const P& val3, const S& val4) const
{
return lcs(val) + '+' + lcs(val2) + '+' + lcs(val3) + '+' + lcs(val4);
}
};
struct lvalue_rvalue_detector : boost::static_visitor<std::string>
{
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <class T>
std::string operator()(T&&) const
{
return std::is_lvalue_reference<T>::value ? "lvalue reference"
: "rvalue reference";
}
template <class T, class V>
std::string operator()(T&& t, V&& v) const
{
return operator()(std::forward<T>(t)) + ", " + operator()(std::forward<V>(v));
}
template <class T, class V, class P>
std::string operator()(T&& t, V&& v, P&& p) const
{
return operator()(std::forward<T>(t), std::forward<V>(v)) + ", " + operator()(std::forward<P>(p));
}
template <class T, class V, class P, class S>
std::string operator()(T&& t, V&& v, P&& p, S&& s) const
{
return operator()(std::forward<T>(t), std::forward<V>(v), std::forward<P>(p)) + ", " + operator()(std::forward<S>(s));
}
#else
template <class T>
std::string operator()(T&) const
{
return "lvalue reference";
}
template <class T, class V>
std::string operator()(T&, V&) const
{
return "lvalue reference, lvalue reference";
}
template <class T, class V, class P>
std::string operator()(T&, V&, P&) const
{
return "lvalue reference, lvalue reference, lvalue reference";
}
template <class T, class V, class P, class S>
std::string operator()(T&, V&, P&, S&) const
{
return "lvalue reference, lvalue reference, lvalue reference, lvalue reference";
}
#endif
};
typedef boost::variant<construction_logger, std::string> variant_type;
void test_const_ref_parameter(const variant_type& test_var)
{
std::cout << "Testing const lvalue reference visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var) == "lvalue reference");
}
void test_const_ref_parameter2(const variant_type& test_var, const variant_type& test_var2)
{
std::cout << "Testing const lvalue reference visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2) == "lvalue reference, lvalue reference");
}
void test_const_ref_parameter4(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3, const variant_type& test_var4)
{
std::cout << "Testing const lvalue reference visitable with multivisitor\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2, test_var3, test_var4)
== "lvalue reference, lvalue reference, lvalue reference, lvalue reference");
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
void test_rvalue_parameter(variant_type&& test_var)
{
std::cout << "Testing rvalue visitable\n";
const auto expected_val = lcs(test_var);
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var)) == "rvalue reference");
}
void test_rvalue_parameter2(variant_type&& test_var, variant_type&& test_var2)
{
std::cout << "Testing rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2)) == "rvalue reference, rvalue reference");
}
void test_rvalue_parameter4(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3, variant_type&& test_var4)
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing rvalue visitable with multivisitor\n";
auto result = boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2), std::move(test_var3), std::move(test_var4));
std::cout << "result: " << result << std::endl;
BOOST_TEST(result == "rvalue reference, rvalue reference, rvalue reference, rvalue reference");
#else
(void)test_var;
(void)test_var2;
(void)test_var3;
(void)test_var4;
#endif
}
#endif
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
#define FORWARD(x) std::forward<decltype(x)>(x)
void test_cpp14_visitor(const variant_type& test_var)
{
std::cout << "Testing const lvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, test_var) == "lvalue reference");
}
void test_cpp14_mutable_visitor(const variant_type& test_var)
{
std::cout << "Testing const lvalue visitable for c++14 with inline mutable lambda\n";
BOOST_TEST(boost::apply_visitor([](auto&& v) mutable -> auto { return lvalue_rvalue_detector()(FORWARD(v)); }, test_var) == "lvalue reference");
}
void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2)
{
std::cout << "Testing const lvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, test_var, test_var2)
== "lvalue reference, lvalue reference");
}
void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3)
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing const lvalue visitable for c++14\n";
auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
test_var, test_var2, test_var3);
std::cout << "result: " << result << std::endl;
BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference");
#else
(void)test_var;
(void)test_var2;
(void)test_var3;
#endif
}
void test_cpp14_visitor(variant_type& test_var)
{
std::cout << "Testing lvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto& v) { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
}
void test_cpp14_mutable_visitor(variant_type& test_var)
{
std::cout << "Testing lvalue visitable for c++14 with inline mutable lambda\n";
BOOST_TEST(boost::apply_visitor([](auto& v) mutable -> auto { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference");
}
void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2)
{
std::cout << "Testing lvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto& v, auto& vv) { return lvalue_rvalue_detector()(v, vv); }, test_var, test_var2)
== "lvalue reference, lvalue reference");
}
void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2, variant_type& test_var3)
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing lvalue visitable for c++14\n";
auto result = boost::apply_visitor([](auto& v, auto& t, auto& p) { return lvalue_rvalue_detector()(v, t, p); },
test_var, test_var2, test_var3);
std::cout << "result: " << result << std::endl;
BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference");
#else
(void)test_var;
(void)test_var2;
(void)test_var3;
#endif
}
void test_cpp14_visitor(variant_type&& test_var)
{
std::cout << "Testing rvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, std::move(test_var)) == "rvalue reference");
}
void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2)
{
std::cout << "Testing rvalue visitable for c++14\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, std::move(test_var), std::move(test_var2))
== "rvalue reference, rvalue reference");
}
void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3)
{
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing rvalue visitable for c++14\n";
auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
std::move(test_var), std::move(test_var2), std::move(test_var3));
std::cout << "result: " << result << std::endl;
BOOST_TEST(result == "rvalue reference, rvalue reference, rvalue reference");
#else
(void)test_var;
(void)test_var2;
(void)test_var3;
#endif
}
#endif
void run_const_lvalue_ref_tests()
{
const variant_type v1(1), v2(2), v3(3), v4(4);
test_const_ref_parameter(v1);
test_const_ref_parameter2(v1, v2);
test_const_ref_parameter4(v1, v2, v3, v4);
}
void run_rvalue_ref_tests()
{
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
variant_type v1(10), v2(20), v3(30);
test_rvalue_parameter(boost::move(v1));
test_rvalue_parameter2(boost::move(v2), boost::move(v3));
variant_type vv1(100), vv2(200), vv3(300), vv4(400);
test_rvalue_parameter4(boost::move(vv1), boost::move(vv2), boost::move(vv3), boost::move(vv4));
#endif
}
void run_mixed_tests()
{
variant_type v1(1), v2(2);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
std::cout << "Testing lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10)) == "lvalue reference, rvalue reference");
std::cout << "Testing rvalue + lvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1) == "rvalue reference, lvalue reference");
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing rvalue + lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1, variant_type(20)) == "rvalue reference, lvalue reference, rvalue reference");
std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10), v2, variant_type(20)) == "lvalue reference, rvalue reference, lvalue reference, rvalue reference");
#endif
#endif // #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
std::cout << "Testing lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, v1) == "lvalue reference, lvalue reference");
std::cout << "Testing rvalue + lvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1) == "lvalue reference, lvalue reference");
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing rvalue + lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference");
std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, static_cast<const variant_type&>(variant_type(10)), v2, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference, lvalue reference");
#endif
#endif
}
void run_cpp14_mixed_tests()
{
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
variant_type v1(1), v2(2);
std::cout << "Testing lvalue + rvalue visitable\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); },
v1, variant_type(10)) == "lvalue reference, rvalue reference");
std::cout << "Testing rvalue + lvalue visitable\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); },
variant_type(10), v1) == "rvalue reference, lvalue reference");
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
std::cout << "Testing rvalue + lvalue + lvalue visitable\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
variant_type(10), v1, v2) == "rvalue reference, lvalue reference, lvalue reference");
std::cout << "Testing lvalue + rvalue + lvalue visitable\n";
BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); },
v1, variant_type(10), v2) == "lvalue reference, rvalue reference, lvalue reference");
#endif
#endif
}
void run_cpp14_tests()
{
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
variant_type const c1(10), c2(20), c3(30);
variant_type v1(10), v2(20), v3(30);
test_cpp14_visitor(c1);
test_cpp14_mutable_visitor(c1);
test_cpp14_visitor(c2, c3);
test_cpp14_visitor(c1, c2, c3);
test_cpp14_visitor(v1);
test_cpp14_mutable_visitor(v1);
test_cpp14_visitor(v2, v3);
test_cpp14_visitor(v1, v2, v3);
test_cpp14_visitor(boost::move(v1));
test_cpp14_visitor(boost::move(v2), boost::move(v3));
variant_type vv1(100), vv2(200), vv3(300);
test_cpp14_visitor(boost::move(vv1), boost::move(vv2), boost::move(vv3));
#endif
}
int main()
{
run_const_lvalue_ref_tests();
run_rvalue_ref_tests();
run_mixed_tests();
run_cpp14_mixed_tests();
run_cpp14_tests();
return boost::report_errors();
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) 2021 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Test case from https://svn.boost.org/trac10/ticket/8721
#include <boost/variant.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
#include <boost/fusion/include/vector.hpp>
struct emptyList {};
typedef boost::make_recursive_variant
< emptyList
, boost::fusion::vector
< int
, boost::recursive_variant_
>
>::type IntList;
const emptyList el = emptyList();
const IntList nil( el );
IntList cons( int head, IntList tail )
{
return IntList( boost::fusion::vector<int, IntList>( head, tail ) );
}
#endif // #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)

View File

@@ -0,0 +1,73 @@
// Copyright (c) 2016
// Mikhail Maximov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
// Test is based on reported issues:
// https://svn.boost.org/trac/boost/ticket/12508
// https://svn.boost.org/trac/boost/ticket/12645
// Following hash function was not found at compile time,
// because boost::variant construction from boost::recursive_variant_
// was forbidden.
#include <unordered_set>
#include "boost/variant.hpp"
struct hash;
using int_t = int;
template <typename T>
using basic_set_t = std::unordered_set<T, hash>;
using value_t = boost::make_recursive_variant<
int_t,
basic_set_t<boost::recursive_variant_>
>::type;
using set_t = basic_set_t<value_t>;
struct hash
{
size_t operator()(const value_t&) const
{
return 0;
}
};
void run()
{
set_t s;
int_t i = 3;
value_t v = i;
auto emplace_result = s.emplace(v); // raises error above
BOOST_TEST(emplace_result.second);
v = s;
const set_t& check_set = boost::get<set_t>(v);
BOOST_TEST(!check_set.empty());
for (const auto& check_v : check_set) {
BOOST_TEST(s.find(check_v) != s.end());
}
for (const auto& check_v : s) {
BOOST_TEST(check_set.find(check_v) != check_set.end());
}
}
#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
// if no unordered_set and template aliases - does nothing
void run() {}
#endif
int main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2011-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/core/lightweight_test.hpp"
#include "boost/config.hpp"
#include "boost/variant.hpp"
#include "boost/functional/hash/hash.hpp"
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH)
#include <unordered_set>
void test_std_hash() {
std::unordered_set<boost::variant<int, bool> > us;
us.insert(1);
us.insert(true);
BOOST_TEST(us.size() == 2);
}
#else
void test_std_hash() {}
#endif
void run() {
typedef boost::variant<bool, int, unsigned int, char> variant_type;
boost::hash<variant_type> hasher;
variant_type bool_variant1 = true;
variant_type bool_variant2 = false;
variant_type int_variant = 1;
variant_type char_variant1 = '\1';
variant_type char_variant2 = '\2';
variant_type uint_variant = static_cast<unsigned int>(1);
BOOST_TEST(hasher(bool_variant1) != hasher(bool_variant2));
BOOST_TEST(hasher(bool_variant1) == hasher(bool_variant1));
BOOST_TEST(hasher(int_variant) != hasher(uint_variant));
BOOST_TEST(hasher(char_variant1) != hasher(uint_variant));
BOOST_TEST(hasher(char_variant1) != hasher(char_variant2));
BOOST_TEST(hasher(char_variant1) == hasher(char_variant1));
BOOST_TEST(hasher(char_variant2) == hasher(char_variant2));
}
int main() {
run();
test_std_hash();
return boost::report_errors();
}

View File

@@ -0,0 +1,61 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/issue42.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2018-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Test case from https://github.com/boostorg/variant/issues/42
#include <boost/variant.hpp>
#include <map>
#include <memory>
#include <vector>
#ifdef BOOST_NO_CXX11_SMART_PTR
template <class T> struct shared_ptr_like {};
typedef shared_ptr_like<boost::recursive_variant_> ptr_t;
#else
typedef std::shared_ptr<boost::recursive_variant_> ptr_t;
#endif
template <class F>
class func{};
int main() {
typedef boost::make_recursive_variant<
int,
ptr_t
>::type node;
node x = 1;
(void)x;
typedef boost::make_recursive_variant<
std::string, int, double, bool,
ptr_t,
std::map<const std::string, boost::recursive_variant_>,
std::vector<boost::recursive_variant_>
>::type node2;
node2 x2 = 1;
(void)x2;
typedef boost::make_recursive_variant<
int,
func<boost::recursive_variant_(*)(boost::recursive_variant_&, const boost::recursive_variant_&)>,
boost::recursive_variant_&(*)(boost::recursive_variant_, boost::recursive_variant_*),
ptr_t
>::type node3;
node3 x3 = func<node3(*)(node3&, const node3&)>();
(void)x3;
}

View File

@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/issue53.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2019-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Test case from https://github.com/boostorg/variant/issues/53
#include <boost/variant.hpp>
#include <boost/thread/lock_guard.hpp> // this line was causing problems on MSVC
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
struct spanac {};
struct ceapa{
double a,b;
};
typedef boost::variant<spanac, ceapa> var_t;
struct visitor_t : public boost::static_visitor<bool> {
bool operator() (const spanac&) const {
return true;
}
bool operator() (const ceapa&) const {
return false;
}
private:
double a, b;
};
var_t get(int k) {
if (k)
return spanac();
else
return ceapa();
}
int main(int argc, const char** argv) {
visitor_t v;
bool result = boost::apply_visitor(v, get(argc - 1));
(void)result;
}
#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
int main() {}
#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES

View File

@@ -0,0 +1,335 @@
//-----------------------------------------------------------------------------
// boost-libs variant/libs/test/jobs.h header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef _JOBSH_INC_
#define _JOBSH_INC_
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
#include <vector>
#include "boost/variant/variant_fwd.hpp"
#include "boost/variant/get.hpp"
#include "boost/variant/apply_visitor.hpp"
#include "boost/variant/static_visitor.hpp"
#include "boost/type_index.hpp"
#include "boost/detail/workaround.hpp"
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
# pragma warn -lvc
#endif
struct to_text : boost::static_visitor<std::string>
{
private: // NO_FUNCTION_TEMPLATE_ORDERING workaround
template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
std::string to_text_impl(
const boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) >& operand, long
) const
{
std::ostringstream ost;
ost << "[V] " << boost::apply_visitor(to_text(), operand);
return ost.str();
}
template <typename Value>
std::string to_text_impl(const Value& operand, int) const
{
std::ostringstream ost;
ost << "[V] " << operand;
return ost.str();
}
public:
template <typename T>
std::string operator()(const T& operand) const
{
return to_text_impl(operand, 1L);
}
};
struct total_sizeof : boost::static_visitor<int>
{
total_sizeof() : total_(0) { }
template<class Value>
int operator()(const 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<>
{
int_adder(int rhs) : rhs_(rhs) { }
result_type operator()(int& lhs) const
{
lhs += rhs_;
}
template<typename T>
result_type operator()(const T& ) const
{
//Do nothing
}
int rhs_;
}; //int_adder
template<typename T>
struct spec
{
typedef T result;
};
template<typename VariantType, typename S>
inline void verify(VariantType& var, spec<S>, std::string str = "")
{
const VariantType& cvar = var;
BOOST_TEST(boost::apply_visitor(total_sizeof(), cvar) == sizeof(S));
BOOST_TEST(cvar.type() == boost::typeindex::type_id<S>());
//
// Check get<>()
//
BOOST_TEST(boost::get<S>(&var));
BOOST_TEST(boost::get<S>(&cvar));
const S* ptr1 = 0;
const S* ptr2 = 0;
try
{
S& r = boost::get<S>(var);
ptr1 = &r;
}
catch(const boost::bad_get& )
{
BOOST_ERROR( "get<S> failed unexpectedly" );
}
try
{
const S& cr = boost::get<S>(cvar);
ptr2 = &cr;
}
catch(const boost::bad_get& )
{
BOOST_ERROR( "get<S> const failed unexpectedly" );
}
BOOST_TEST(ptr1 != 0 && ptr2 == ptr1);
//
// Check string content
//
if(str.length() > 0)
{
std::string temp = boost::apply_visitor(to_text(), cvar);
std::cout << "temp = " << temp << ", str = " << str << std::endl;
BOOST_TEST(temp == str);
}
}
template<typename VariantType, typename S>
inline void verify_not(VariantType& var, spec<S>)
{
const VariantType& cvar = var;
BOOST_TEST(cvar.type() != boost::typeindex::type_id<S>());
//
// Check get<>()
//
BOOST_TEST(!boost::get<S>(&var));
BOOST_TEST(!boost::get<S>(&cvar));
const S* ptr1 = 0;
const S* ptr2 = 0;
try
{
S& r = boost::get<S>(var); // should throw
BOOST_ERROR( "get<S> passed unexpectedly" );
ptr1 = &r;
}
catch(const boost::bad_get& )
{
// do nothing except pass-through
}
try
{
const S& cr = boost::get<S>(var); // should throw
BOOST_ERROR( "get<S> const passed unexpectedly" );
ptr2 = &cr;
}
catch(const boost::bad_get& )
{
// do nothing except pass-through
}
BOOST_TEST(ptr1 == 0 && ptr2 == 0);
}
#endif //_JOBSH_INC_

View File

@@ -0,0 +1,32 @@
// Copyright (c) 2017-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/variant.hpp"
struct foo {};
struct some_user_provided_visitor_for_lvalues: boost::static_visitor<void> {
void operator()(foo& ) const {}
void operator()(int ) const {}
};
int main() {
boost::apply_visitor(
some_user_provided_visitor_for_lvalues(),
boost::variant<int, foo>(foo())
);
#ifdef __GNUC__
# if __GNUC__ < 5 && __GNUC_MINOR__ < 8
# error This test does not pass on GCC < 4.8 because of the incomplete C++11 support
# endif
#endif
#ifdef BOOST_MSVC
# error Temporaries/rvalues could bind to non-const lvalues on MSVC compilers
#endif
}

View File

@@ -0,0 +1,215 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_get_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2016-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This test suite was created to cover issues reported in:
// https://svn.boost.org/trac/boost/ticket/5871
// https://svn.boost.org/trac/boost/ticket/11602
#include "boost/variant/variant.hpp"
#include "boost/variant/recursive_variant.hpp"
#include "boost/core/lightweight_test.hpp"
#include <string>
#include <list>
struct A{};
struct B{};
struct C{};
struct D{};
bool foo(const boost::variant<A, B>& ) {
return false;
}
bool foo(const boost::variant<C, D>& ) {
return true;
}
void test_overload_selection_variant_constructor() {
D d;
BOOST_TEST(foo(d));
boost::variant<B, A> v;
BOOST_TEST(!foo(v));
}
// Pre msvc-14.0 could not dustinguish between multiple assignment operators:
// warning C4522: 'assignment_tester' : multiple assignment operators specified
// error C2666: variant::operator =' : 3 overloads have similar conversions
// Old versions of GCC have same issue:
// error: variant::operator=(const T&) cannot be overloaded
#if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_MSC_VER) && _MSC_VER < 1900)
void test_overload_selection_variant_assignment() {
BOOST_TEST(true);
}
#else
struct assignment_tester: boost::variant<C, D>, boost::variant<B, A> {
using boost::variant<B, A>::operator=;
using boost::variant<C, D>::operator=;
};
void test_overload_selection_variant_assignment() {
A a;
assignment_tester tester;
tester = a;
const int which0 = static_cast< boost::variant<B, A>& >(tester).which();
BOOST_TEST(which0 == 1);
boost::variant<A, B> b;
b = B();
tester = b;
const int which1 = static_cast< boost::variant<B, A>& >(tester).which();
BOOST_TEST(which1 == 0);
}
#endif
typedef boost::variant<int> my_variant;
struct convertible {
operator my_variant() const {
return my_variant();
}
};
void test_implicit_conversion_operator() {
// https://svn.boost.org/trac/boost/ticket/8555
my_variant y = convertible();
BOOST_TEST(y.which() == 0);
}
struct X: boost::variant< int > {};
class V1: public boost::variant<float,double> {};
struct AB: boost::variant<A, B> {};
void test_derived_from_variant_construction() {
// https://svn.boost.org/trac/boost/ticket/7120
X x;
boost::variant<X> y(x);
BOOST_TEST(y.which() == 0);
// https://svn.boost.org/trac/boost/ticket/10278
boost::variant<V1, std::string> v2 = V1();
BOOST_TEST(v2.which() == 0);
// https://svn.boost.org/trac/boost/ticket/12155
AB ab;
boost::variant<AB, C> ab_c(ab);
BOOST_TEST(ab_c.which() == 0);
boost::variant<A, B> a_b(ab);
BOOST_TEST(a_b.which() == 0);
boost::variant<B, C, A> b_c_a1(static_cast<boost::variant<A, B>& >(ab));
BOOST_TEST(b_c_a1.which() == 2);
// Following conversion seems harmful as it may lead to slicing:
// boost::variant<B, C, A> b_c_a(ab);
// BOOST_TEST(b_c_a.which() == 2);
}
void test_derived_from_variant_assignment() {
// https://svn.boost.org/trac/boost/ticket/7120
X x;
boost::variant<X> y;
y = x;
BOOST_TEST(y.which() == 0);
// https://svn.boost.org/trac/boost/ticket/10278
boost::variant<V1, std::string> v2;
v2 = V1();
BOOST_TEST(v2.which() == 0);
// https://svn.boost.org/trac/boost/ticket/12155
AB ab;
boost::variant<AB, C> ab_c;
ab_c = ab;
BOOST_TEST(ab_c.which() == 0);
boost::variant<A, B> a_b;
a_b = ab;
BOOST_TEST(a_b.which() == 0);
boost::variant<B, C, A> b_c_a1;
b_c_a1 = static_cast<boost::variant<A, B>& >(ab);
BOOST_TEST(b_c_a1.which() == 2);
// Following conversion seems harmful as it may lead to slicing:
// boost::variant<B, C, A> b_c_a;
// b_c_a = ab;
// BOOST_TEST(b_c_a.which() == 2);
}
// http://thread.gmane.org/gmane.comp.lib.boost.devel/267757
struct info {
struct nil_ {};
typedef
boost::variant<
nil_
, std::string
, boost::recursive_wrapper<info>
, boost::recursive_wrapper<std::pair<info, info> >
, boost::recursive_wrapper<std::list<info> >
>
value_type;
value_type v;
inline void test_on_incomplete_types() {
info i0;
i0.v = "Hello";
BOOST_TEST(i0.v.which() == 1);
info::value_type v0 = "Hello";
BOOST_TEST(v0.which() == 1);
info::value_type v1("Hello");
BOOST_TEST(v1.which() == 1);
info::value_type v2 = i0;
BOOST_TEST(v2.which() == 2);
info::value_type v3(i0);
BOOST_TEST(v3.which() == 2);
v0 = v3;
BOOST_TEST(v0.which() == 2);
v3 = v1;
BOOST_TEST(v3.which() == 1);
v3 = nil_();
BOOST_TEST(v3.which() == 0);
}
};
int main()
{
test_overload_selection_variant_constructor();
test_overload_selection_variant_assignment();
test_implicit_conversion_operator();
test_derived_from_variant_construction();
test_derived_from_variant_assignment();
info().test_on_incomplete_types();
return boost::report_errors();
}

View File

@@ -0,0 +1,364 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/recursive_variant_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman, Itay Maman
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is used in two test cases:
//
// 1) recursive_variant_test.cpp that tests recursive usage of variant
//
// 2) variant_noexcept_test that tests Boost.Variant ability to compile
// and work with disabled exceptions
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "boost/mpl/vector.hpp"
#include "boost/mpl/copy.hpp"
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
#include <tuple>
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
struct printer
: boost::static_visitor<std::string>
{
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
std::string operator()(
const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &var) const
{
return boost::apply_visitor( printer(), var );
}
template <typename T>
std::string operator()(const std::vector<T>& vec) const
{
std::ostringstream ost;
ost << "( ";
typename std::vector<T>::const_iterator it = vec.begin();
for (; it != vec.end(); ++it)
ost << printer()( *it );
ost << ") ";
return ost.str();
}
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
template <int...> struct indices {};
template <typename... Ts, int... Is>
std::string operator()(const std::tuple<Ts...>& tup, indices<Is...>) const
{
std::ostringstream ost;
ost << "( ";
int a[] = {0, (ost << printer()( std::get<Is>(tup) ), 0)... };
(void)a;
ost << ") ";
return ost.str();
}
template <int N, int... Is>
struct make_indices : make_indices<N-1, N-1, Is...> {};
template <int... Is>
struct make_indices<0, Is...> : indices<Is...> {};
template <typename... Ts>
std::string operator()(const std::tuple<Ts...>& tup) const
{
return printer()(tup, make_indices<sizeof...(Ts)>());
}
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
template <typename T>
std::string operator()(const T& operand) const
{
std::ostringstream ost;
ost << operand << ' ';
return ost.str();
}
};
void test_recursive_variant()
{
typedef boost::make_recursive_variant<
int
, std::vector<boost::recursive_variant_>
>::type var1_t;
std::vector<var1_t> vec1;
vec1.push_back(3);
vec1.push_back(5);
vec1.push_back(vec1);
vec1.push_back(7);
var1_t var1(vec1);
std::string result1( printer()(var1) );
std::cout << "result1: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) ");
std::vector<var1_t> vec1_copy = vec1;
vec1_copy.erase(vec1_copy.begin() + 2);
vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy);
var1 = vec1_copy;
result1 = printer()(var1);
std::cout << "result1+: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
// Uses move construction on compilers with rvalue references support
result1 = printer()(
var1_t(
std::vector<var1_t>(vec1_copy)
)
);
std::cout << "result1++: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
var1_t vec1_another_copy(vec1_copy);
vec1_copy[2].swap(vec1_another_copy);
result1 = printer()(
var1_t(vec1_copy)
);
std::cout << "result1+++1: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
result1 = printer()(vec1_another_copy);
std::cout << "result1++2: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 7 ) ");
vec1_copy[2].swap(vec1_copy[2]);
result1 = printer()(
var1_t(vec1_copy)
);
std::cout << "result1.2: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
typedef boost::make_recursive_variant<
boost::variant<int, double>
, std::vector<boost::recursive_variant_>
>::type var2_t;
std::vector<var2_t> vec2;
vec2.push_back(boost::variant<int, double>(3));
vec2.push_back(boost::variant<int, double>(3.5));
vec2.push_back(vec2);
vec2.push_back(boost::variant<int, double>(7));
var2_t var2(vec2);
std::string result2( printer()(var2) );
std::cout << "result2: " << result2 << '\n';
BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) ");
typedef boost::make_recursive_variant<
int
, std::vector<
boost::variant<
double
, std::vector<boost::recursive_variant_>
>
>
>::type var3_t;
typedef boost::variant<double, std::vector<var3_t> > var4_t;
std::vector<var3_t> vec3;
vec3.push_back(3);
vec3.push_back(5);
std::vector<var4_t> vec4;
vec4.push_back(3.5);
vec4.push_back(vec3);
vec3.push_back(vec4);
vec3.push_back(7);
var4_t var4(vec3);
std::string result3( printer()(var4) );
std::cout << "result2: " << result3 << '\n';
BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) ");
typedef boost::make_recursive_variant<
double,
std::vector<var1_t>
>::type var5_t;
std::vector<var5_t> vec5;
vec5.push_back(3.5);
vec5.push_back(vec1);
vec5.push_back(17.25);
std::string result5( printer()(vec5) );
std::cout << "result5: " << result5 << '\n';
BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) ");
typedef boost::make_recursive_variant<
int,
std::map<int, boost::recursive_variant_>
>::type var6_t;
var6_t var6;
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
typedef boost::make_recursive_variant<
int,
std::tuple<int, boost::recursive_variant_>
>::type var7_t;
var7_t var7 = 0; // !!! Do not replace with `var7_t var7{0}` or `var7_t var7(0)` !!!
var7 = std::tuple<int, var7_t>(1, var7);
var7 = std::tuple<int, var7_t>(2, var7);
std::string result7( printer()(var7) );
std::cout << "result7: " << result7 << '\n';
BOOST_TEST(result7 == "( 2 ( 1 0 ) ) ");
#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
}
void test_recursive_variant_over()
{
typedef boost::make_recursive_variant_over<
boost::mpl::vector<
int
, std::vector<boost::recursive_variant_>
>
>::type var1_t;
std::vector<var1_t> vec1;
vec1.push_back(3);
vec1.push_back(5);
vec1.push_back(vec1);
vec1.push_back(7);
var1_t var1(vec1);
std::string result1( printer()(var1) );
std::cout << "result1: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) ");
std::vector<var1_t> vec1_copy = vec1;
vec1_copy.erase(vec1_copy.begin() + 2);
vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy);
var1 = vec1_copy;
result1 = printer()(var1);
std::cout << "result1+: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
// Uses move construction on compilers with rvalue references support
result1 = printer()(
var1_t(
std::vector<var1_t>(vec1_copy)
)
);
std::cout << "result1++: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) ");
var1_t vec1_another_copy(vec1_copy);
vec1_copy[2].swap(vec1_another_copy);
result1 = printer()(
var1_t(vec1_copy)
);
std::cout << "result1+++1: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) ");
result1 = printer()(vec1_another_copy);
std::cout << "result1++2: " << result1 << '\n';
BOOST_TEST(result1 == "( 3 5 7 ) ");
typedef boost::make_recursive_variant_over<
boost::mpl::vector<
boost::make_variant_over<boost::mpl::vector<int, double> >::type
, std::vector<boost::recursive_variant_>
>
>::type var2_t;
std::vector<var2_t> vec2;
vec2.push_back(boost::variant<int, double>(3));
vec2.push_back(boost::variant<int, double>(3.5));
vec2.push_back(vec2);
vec2.push_back(boost::variant<int, double>(7));
var2_t var2(vec2);
std::string result2( printer()(var2) );
std::cout << "result2: " << result2 << '\n';
BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) ");
typedef boost::make_recursive_variant_over<
boost::mpl::vector<
int
, std::vector<
boost::make_variant_over<
boost::mpl::vector<
double
, std::vector<boost::recursive_variant_>
>
>::type
>
>
>::type var3_t;
typedef boost::make_variant_over<
boost::mpl::copy<
boost::mpl::vector<
double
, std::vector<var3_t>
>
>::type
>::type var4_t;
std::vector<var3_t> vec3;
vec3.push_back(3);
vec3.push_back(5);
std::vector<var4_t> vec4;
vec4.push_back(3.5);
vec4.push_back(vec3);
vec3.push_back(vec4);
vec3.push_back(7);
var4_t var3(vec3);
std::string result3( printer()(var3) );
std::cout << "result2: " << result3 << '\n';
BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) ");
typedef boost::make_recursive_variant_over<
boost::mpl::vector<
double
, std::vector<var1_t>
>
>::type var5_t;
std::vector<var5_t> vec5;
vec5.push_back(3.5);
vec5.push_back(vec1);
vec5.push_back(17.25);
std::string result5( printer()(vec5) );
std::cout << "result5: " << result5 << '\n';
BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) ");
}
int main()
{
test_recursive_variant();
test_recursive_variant_over();
return boost::report_errors();
}

View File

@@ -0,0 +1,77 @@
// Copyright (c) 2017
// Mikhail Maximov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#ifdef __cpp_inheriting_constructors
// Test is based on reported issue:
// https://svn.boost.org/trac/boost/ticket/12680
// GCC 6 crashed, trying to determine is boost::recursive_wrapper<Node>
// is_noexcept_move_constructible
#include <string>
#include <boost/variant.hpp>
#include <boost/array.hpp>
struct Leaf { };
struct Node;
typedef boost::variant<Leaf, boost::recursive_wrapper<Node>> TreeBase;
struct Tree : TreeBase {
using TreeBase::TreeBase;
template <typename Iter>
static Tree Create(Iter /*first*/, Iter /*last*/) { return Leaf{}; }
};
struct Node {
Tree left, right;
};
// Test from https://svn.boost.org/trac/boost/ticket/7120
template<class Node>
struct node1_type;
struct var_type;
using var_base = boost::variant<int,
boost::recursive_wrapper<node1_type<var_type>>
>;
template<class Node>
struct node1_type {
boost::array<Node, 1> children;
};
struct var_type : var_base {
using var_base::var_base;
};
void run() {
std::string input{"abracadabra"};
const Tree root = Tree::Create(input.begin(), input.end());
(void)root; // prevents unused variable warning
var_type v1 = 1;
(void)v1;
}
#else // #!ifdef __cpp_inheriting_constructors
// if compiler does not support inheriting constructors - does nothing
void run() {}
#endif
int main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,332 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/rvalue_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2012-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "boost/type_traits/is_nothrow_move_assignable.hpp"
#include "boost/mpl/bool.hpp"
#include <boost/blank.hpp>
#include <boost/swap.hpp>
namespace swap_ambiguouty_test_ns {
struct A {};
struct B {};
void swap_ambiguouty_test() {
// If boost::blank is not used, then it compiles.
typedef boost::variant<boost::blank, A, B> Variant;
Variant v1, v2;
swap(v1, v2);
}
} // namespace swap_ambiguouty_test_ns
// Most part of tests from this file require rvalue references support
class move_copy_conting_class {
public:
static unsigned int moves_count;
static unsigned int copy_count;
move_copy_conting_class(){}
move_copy_conting_class(BOOST_RV_REF(move_copy_conting_class) ) {
++ moves_count;
}
move_copy_conting_class& operator=(BOOST_RV_REF(move_copy_conting_class) ) {
++ moves_count;
return *this;
}
move_copy_conting_class(const move_copy_conting_class&) {
++ copy_count;
}
move_copy_conting_class& operator=(BOOST_COPY_ASSIGN_REF(move_copy_conting_class) ) {
++ copy_count;
return *this;
}
};
unsigned int move_copy_conting_class::moves_count = 0;
unsigned int move_copy_conting_class::copy_count = 0;
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
void run()
{
// Making sure that internals of Boost.Move do not interfere with
// internals of Boost.Variant and in case of C++03 or C++98 compilation
// is still possible.
typedef boost::variant<int, move_copy_conting_class> variant_I_type;
variant_I_type v1, v2;
v1 = move_copy_conting_class();
v2 = v1;
v2 = boost::move(v1);
v1.swap(v2);
move_copy_conting_class val;
v2 = boost::move(val);
v2 = 10;
variant_I_type v3(boost::move(val));
variant_I_type v4(boost::move(v1));
}
void run1()
{
BOOST_TEST(true);
}
void run_move_only()
{
BOOST_TEST(true);
}
void run_moves_are_noexcept()
{
BOOST_TEST(true);
}
void run_const_rvalues()
{
BOOST_TEST(true);
}
#else
void run()
{
typedef boost::variant<int, move_copy_conting_class> variant_I_type;
variant_I_type v1, v2;
// Assuring that `move_copy_conting_class` was not created
BOOST_TEST(move_copy_conting_class::copy_count == 0);
BOOST_TEST(move_copy_conting_class::moves_count == 0);
v1 = move_copy_conting_class();
// Assuring that `move_copy_conting_class` was moved at least once
BOOST_TEST(move_copy_conting_class::moves_count != 0);
unsigned int total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
move_copy_conting_class var;
v1 = 0;
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v1 = var;
// Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v2 = boost::move(v1);
// Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
BOOST_TEST(move_copy_conting_class::moves_count != 0);
BOOST_TEST(move_copy_conting_class::copy_count == 0);
v1 = move_copy_conting_class();
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v2 = boost::move(v1);
// Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
BOOST_TEST(move_copy_conting_class::moves_count != 0);
BOOST_TEST(move_copy_conting_class::copy_count == 0);
total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v1 = v2;
// Assuring that move assignment operator moves/copyes value not more times than copy assignment operator
BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
typedef boost::variant<move_copy_conting_class, int> variant_II_type;
variant_II_type v3;
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v1 = boost::move(v3);
// Assuring that `move_copy_conting_class` in v3 was moved at least once (v1 and v3 have different types)
BOOST_TEST(move_copy_conting_class::moves_count != 0);
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
v2 = boost::move(v1);
// Assuring that `move_copy_conting_class` in v1 was moved at least once (v1 and v3 have different types)
BOOST_TEST(move_copy_conting_class::moves_count != 0);
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
variant_I_type v5(boost::move(v1));
// Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied
BOOST_TEST(move_copy_conting_class::moves_count != 0);
BOOST_TEST(move_copy_conting_class::copy_count == 0);
total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count;
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
variant_I_type v6(v1);
// Assuring that move constructor moves/copyes value not more times than copy constructor
BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count);
}
void run1()
{
move_copy_conting_class::moves_count = 0;
move_copy_conting_class::copy_count = 0;
move_copy_conting_class c1;
typedef boost::variant<int, move_copy_conting_class> variant_I_type;
variant_I_type v1(boost::move(c1));
// Assuring that `move_copy_conting_class` was not copyied
BOOST_TEST(move_copy_conting_class::copy_count == 0);
BOOST_TEST(move_copy_conting_class::moves_count > 0);
}
struct move_only_structure {
move_only_structure(){}
move_only_structure(move_only_structure&&){}
move_only_structure& operator=(move_only_structure&&) { return *this; }
private:
move_only_structure(const move_only_structure&);
move_only_structure& operator=(const move_only_structure&);
};
struct visitor_returning_move_only_type: boost::static_visitor<move_only_structure> {
template <class T>
move_only_structure operator()(const T&) const {
return move_only_structure();
}
};
void run_move_only()
{
move_only_structure mo;
boost::variant<int, move_only_structure > vi, vi2(static_cast<move_only_structure&&>(mo));
BOOST_TEST(vi.which() == 0);
BOOST_TEST(vi2.which() == 1);
vi = 10;
vi2 = 10;
BOOST_TEST(vi.which() == 0);
BOOST_TEST(vi2.which() == 0);
vi = static_cast<move_only_structure&&>(mo);
vi2 = static_cast<move_only_structure&&>(mo);
BOOST_TEST(vi.which() == 1);
boost::variant<move_only_structure, int > rvi (1);
BOOST_TEST(rvi.which() == 1);
rvi = static_cast<move_only_structure&&>(mo);
BOOST_TEST(rvi.which() == 0);
rvi = 1;
BOOST_TEST(rvi.which() == 1);
rvi = static_cast<boost::variant<int, move_only_structure >&&>(vi2);
BOOST_TEST(rvi.which() == 0);
move_only_structure from_visitor = boost::apply_visitor(visitor_returning_move_only_type(), vi);
(void)from_visitor;
}
void run_moves_are_noexcept() {
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || __GNUC_MINOR__ >= 8)
typedef boost::variant<int, short, double> variant_noexcept_t;
BOOST_TEST(boost::is_nothrow_move_assignable<variant_noexcept_t>::value);
BOOST_TEST(boost::is_nothrow_move_constructible<variant_noexcept_t>::value);
typedef boost::variant<int, short, double, move_only_structure> variant_except_t;
BOOST_TEST(!boost::is_nothrow_move_assignable<variant_except_t>::value);
BOOST_TEST(!boost::is_nothrow_move_constructible<variant_except_t>::value);
#endif
}
inline const std::string get_string() { return "test"; }
inline const boost::variant<int, std::string> get_variant() { return std::string("test"); }
inline const boost::variant<std::string, int> get_variant2() { return std::string("test"); }
void run_const_rvalues()
{
typedef boost::variant<int, std::string> variant_t;
const variant_t v1(get_string());
const variant_t v2(get_variant());
const variant_t v3(get_variant2());
variant_t v4, v5, v6, v7;
v4 = get_string();
v5 = get_variant();
v6 = get_variant2();
v7 = boost::move(v1);
}
#endif
struct nothrow_copyable_throw_movable {
nothrow_copyable_throw_movable(){}
nothrow_copyable_throw_movable(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT {}
nothrow_copyable_throw_movable& operator=(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT { return *this; }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
nothrow_copyable_throw_movable(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) {}
nothrow_copyable_throw_movable& operator=(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) { return *this; }
#endif
};
// This test is created to cover the following situation:
// https://svn.boost.org/trac/boost/ticket/8772
void run_tricky_compilation_test()
{
boost::variant<int, nothrow_copyable_throw_movable> v;
v = nothrow_copyable_throw_movable();
}
template <typename T>
struct is_container : boost::mpl::false_ {};
template <typename T>
struct is_container<boost::variant<T> > : is_container<T> {};
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_container<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
: boost::mpl::bool_<is_container<T0>::value
|| is_container<boost::variant<BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)> >::value>
{};
void run_is_container_compilation_test()
{
BOOST_TEST((!is_container<boost::variant<double, int> >::value));
BOOST_TEST((!is_container<boost::variant<double, int, char> >::value));
BOOST_TEST((!is_container<boost::variant<double, int, char, float> >::value));
}
int main()
{
swap_ambiguouty_test_ns::swap_ambiguouty_test();
run();
run1();
run_move_only();
run_moves_are_noexcept();
run_tricky_compilation_test();
run_const_rvalues();
run_is_container_compilation_test();
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6)
# ifdef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
BOOST_TEST(false &&
"Something wrong with macro definitions. GCC-4.7+ is known to work with variadic templates"
);
# endif
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,150 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test1.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#ifdef BOOST_MSVC
#pragma warning(disable:4244) // conversion from const int to const short
#endif
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "class_a.h"
#include "jobs.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 main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,149 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test2.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#ifdef BOOST_MSVC
#pragma warning(disable:4244) // conversion from 'const int' to 'const short'
#endif
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include <cassert>
#include <iostream>
#include <algorithm>
#include <cstring>
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)
{
#ifndef BOOST_NO_STDC_NAMESPACE
using std::strlen;
#endif // BOOST_NO_STDC_NAMESPACE
size_t limit = this->e_limit; // avoid warnings on some compilers
size_t src_len = strlen(src);
len_ = (std::min)(src_len, 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 main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,134 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test3.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include <iostream>
#include <sstream>
#include <string>
/////////////////////////////////////////////////////////////////////
using boost::variant;
using boost::recursive_wrapper;
using std::cout;
using std::endl;
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
struct Add;
struct Sub;
typedef variant<int, recursive_wrapper<Add>, recursive_wrapper<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 Sub& 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;
}
//
// 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 main()
{
int n = 13;
Expr e1( Add(n, Sub(Add(40,2),Add(10,4))) ); //n + (40+2)-(10+14) = n+28
std::ostringstream e1_str;
e1_str << e1;
BOOST_TEST(e1.type() == boost::typeindex::type_id<Add>());
BOOST_TEST(e1_str.str() == "(13+((40+2)-(10+4)))");
//Evaluate expression
int res = boost::apply_visitor(Calculator(), e1);
BOOST_TEST(res == n + 28);
return boost::report_errors();
}

View File

@@ -0,0 +1,57 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test4.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#ifdef BOOST_MSVC
#pragma warning(disable:4244) // conversion from 'const int' to 'const short'
#endif
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include <string>
struct class_a;
using boost::variant;
typedef variant<std::string, class_a, float> var_type_1;
typedef variant<std::string, class_a, short> var_type_2;
#include "class_a.h"
int main()
{
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 boost::report_errors();
}

View File

@@ -0,0 +1,90 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test5.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "jobs.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 main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test6.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include <iostream>
#include "jobs.h"
//Just Another Class
struct jac
{
jac() { }
jac(int ) { }
jac(const char* ) { }
};
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 main()
{
run();
return boost::report_errors();
}

View File

@@ -0,0 +1,255 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test7.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#ifdef BOOST_MSVC
#pragma warning(disable:4244) // conversion from 'const int' to 'const short'
#endif
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "jobs.h"
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include "boost/detail/workaround.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
# include "boost/mpl/bool.hpp"
# include "boost/type_traits/is_same.hpp"
#endif
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_TEST(iter != s_this_to_sn_.end());
BOOST_TEST( ((*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_TEST(sn == j.sn_);
s_this_to_sn_.erase(&j);
cout << "jas( " << j.sn_ << ") Removed" << endl;
}
static void check()
{
BOOST_TEST(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) { }
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
bool operator()(const ValueType& value)
{
return value == expected_;
}
template <typename T>
bool operator()(const T& )
{
return false;
}
#else // MSVC6
private:
bool compare_impl(const ValueType& value, boost::mpl::true_)
{
return value == expected_;
}
template <typename T>
bool compare_impl(const T&, boost::mpl::false_)
{
return false;
}
public:
template <typename T>
bool operator()(const T& value)
{
typedef typename boost::is_same<T, ValueType>::type
T_is_ValueType;
return compare_impl(value, T_is_ValueType());
}
#endif // MSVC6 workaround
ValueType& expected_;
private:
compare_helper& operator=(const compare_helper&);
};
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_TEST(checks);
}
void run()
{
boost::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"));
boost::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));
boost::variant<string, int> v3;
var_compare(v3, string(""));
}
int main()
{
run();
Tracker::check();
return boost::report_errors();
}

View File

@@ -0,0 +1,113 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test8.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003
// Eric Friedman, Itay Maman
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include <iostream>
#include <vector>
#include <string>
using namespace boost;
typedef variant<float, std::string, int, std::vector<std::string> > t_var1;
struct int_sum : static_visitor<>
{
int_sum() : result_(0) { }
void operator()(int t)
{
result_ += t;
}
result_type operator()(float ) { }
result_type operator()(const std::string& ) { }
result_type operator()(const std::vector<std::string>& ) { }
int result_;
};
template <typename T, typename Variant>
T& check_pass(Variant& v, T value)
{
BOOST_TEST(get<T>(&v));
try
{
T& r = get<T>(v);
BOOST_TEST(r == value);
return r;
}
catch(boost::bad_get&)
{
throw; // must never reach
}
}
template <typename T, typename Variant>
void check_fail(Variant& v)
{
BOOST_TEST(!relaxed_get<T>(&v));
try
{
T& r = relaxed_get<T>(v);
(void)r; // suppress warning about r not being used
BOOST_TEST(false && relaxed_get<T>(&v)); // should never reach
}
catch(const boost::bad_get& e)
{
BOOST_TEST(!!e.what()); // make sure that what() is const qualified and returnes something
}
}
int main()
{
int_sum acc;
t_var1 v1 = 800;
// check get on non-const variant
{
int& r1 = check_pass<int>(v1, 800);
const int& cr1 = check_pass<const int>(v1, 800);
check_fail<float>(v1);
check_fail<const float>(v1);
check_fail<short>(v1);
check_fail<const short>(v1);
apply_visitor(acc, v1);
BOOST_TEST(acc.result_ == 800);
r1 = 920; // NOTE: modifies content of v1
apply_visitor(acc, v1);
BOOST_TEST(cr1 == 920);
BOOST_TEST(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::report_errors();
}

View File

@@ -0,0 +1,22 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/test9.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2016-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Test from https://github.com/boostorg/variant/pull/21
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/variant/variant.hpp>
int main() {
boost::make_variant_over<boost::fusion::vector<int, char> >::type t;
(void)t;
}

View File

@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_comparison_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2003 Eric Friedman, Itay Maman
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/variant/variant.hpp"
#include "boost/core/lightweight_test.hpp"
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include "boost/detail/workaround.hpp"
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
# pragma warn -lvc // temporary used for parameter warning
#endif
template <typename T>
void assert_equality_comparable(
const T& x, const T& y, const T& z
)
{
// identity check
BOOST_TEST( !(&x == &y) || (x == y) );
BOOST_TEST( !(&x == &z) || (x == z) );
BOOST_TEST( !(&y == &z) || (y == z) );
BOOST_TEST( !(&x == &y) || !(x != y) );
BOOST_TEST( !(&x == &z) || !(x != z) );
BOOST_TEST( !(&y == &z) || !(y != z) );
// reflexivity check
BOOST_TEST( (x == x) );
BOOST_TEST( (y == y) );
BOOST_TEST( (z == z) );
// symmetry check
BOOST_TEST( !(x == y) || (y == x) );
BOOST_TEST( !(y == x) || (x == y) );
BOOST_TEST( (x != y) || (y == x) );
BOOST_TEST( (y != x) || (x == y) );
BOOST_TEST( !(x == z) || (z == x) );
BOOST_TEST( !(z == x) || (x == z) );
BOOST_TEST( (x != z) || (z == x) );
BOOST_TEST( (z != x) || (x == z) );
BOOST_TEST( !(y == z) || (z == y) );
BOOST_TEST( !(z == y) || (y == z) );
BOOST_TEST( (y != z) || (z == y) );
BOOST_TEST( (z != y) || (y == z) );
// transitivity check
BOOST_TEST( !(x == y && y == z) || (x == z) );
BOOST_TEST( !(x == z && z == y) || (x == y) );
BOOST_TEST( !(y == z && z == x) || (y == x) );
}
template <typename T>
void assert_less_than_comparable(
const T& x, const T& y, const T& z
)
{
// irreflexivity check
BOOST_TEST( !(x < x) );
BOOST_TEST( !(y < y) );
BOOST_TEST( !(z < z) );
BOOST_TEST( !(x > x) );
BOOST_TEST( !(y > y) );
BOOST_TEST( !(z > z) );
BOOST_TEST( (x <= x) );
BOOST_TEST( (y <= y) );
BOOST_TEST( (z <= z) );
BOOST_TEST( (x >= x) );
BOOST_TEST( (y >= y) );
BOOST_TEST( (z >= z) );
// transitivity check
BOOST_TEST( (x < y) );
BOOST_TEST( (y < z) );
BOOST_TEST( (x < z) );
BOOST_TEST( (x <= y) );
BOOST_TEST( (y <= z) );
BOOST_TEST( (x <= z) );
BOOST_TEST( (z > y) );
BOOST_TEST( (y > x) );
BOOST_TEST( (z > x) );
BOOST_TEST( (z >= y) );
BOOST_TEST( (y >= x) );
BOOST_TEST( (z >= x) );
// antisymmetry check
BOOST_TEST( !(y < x) );
BOOST_TEST( !(z < y) );
BOOST_TEST( !(z < x) );
}
template <typename It>
std::string print_range(It first, It last)
{
std::ostringstream result;
while (first != last)
{
result << *first << ' ';
++first;
}
return result.str();
}
int main()
{
typedef boost::variant<int, std::string> var_t;
var_t var1(3);
var_t var2(5);
var_t var3("goodbye");
var_t var4("hello");
assert_equality_comparable(var1, var1, var1);
assert_equality_comparable(var_t(var1), var_t(var1), var_t(var1));
assert_equality_comparable(var1, var2, var3);
assert_less_than_comparable(var1, var2, var3);
assert_less_than_comparable(var2, var3, var4);
std::vector<var_t> vec;
vec.push_back( var3 );
vec.push_back( var2 );
vec.push_back( var4 );
vec.push_back( var1 );
std::sort(vec.begin(), vec.end());
std::string sort_result( print_range(vec.begin(), vec.end()) );
BOOST_TEST( sort_result == "3 5 goodbye hello " );
// https://svn.boost.org/trac/boost/ticket/11751
int a = 0, b = 0;
boost::variant< int& > v (a), u (b);
BOOST_TEST(v == u);
return boost::report_errors();
}

View File

@@ -0,0 +1,417 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_get_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifdef _MSC_VER
#pragma warning(disable: 4127) // conditional expression is constant
#pragma warning(disable: 4181) // qualifier applied to reference type; ignored
#endif
#include "boost/variant/get.hpp"
#include "boost/variant/variant.hpp"
#include "boost/variant/polymorphic_get.hpp"
#include "boost/variant/recursive_wrapper.hpp"
#include "boost/core/lightweight_test.hpp"
struct base {
int trash;
base() : trash(123) {}
base(const base& b) : trash(b.trash) { int i = 100; (void)i; }
const base& operator=(const base& b) {
trash = b.trash;
int i = 100; (void)i;
return *this;
}
virtual ~base(){}
};
struct derived1 : base{};
struct derived2 : base{};
struct vbase { short trash; virtual ~vbase(){} virtual int foo() const { return 0; } };
struct vderived1 : virtual vbase{ virtual int foo() const { return 1; } };
struct vderived2 : virtual vbase{ virtual int foo() const { return 3; } };
struct vderived3 : vderived1, vderived2 { virtual int foo() const { return 3; } };
typedef boost::variant<int, base, derived1, derived2, std::string> var_t;
typedef boost::variant<int, derived1, derived2, std::string> var_t_shortened;
typedef boost::variant<base, derived1, derived2> var_t_no_fallback;
typedef boost::variant<int&, base&, derived1&, derived2&, std::string&> var_ref_t;
typedef boost::variant<const int&, const base&, const derived1&, const derived2&, const std::string&> var_cref_t;
struct recursive_structure;
typedef boost::variant<
int, base, derived1, derived2, std::string, boost::recursive_wrapper<recursive_structure>
> var_req_t;
struct recursive_structure { var_req_t var; };
template <class TypeInVariant, class V, class TestType>
inline void check_polymorphic_get_on_types_impl_single_type(V* v)
{
typedef typename boost::add_reference<TestType>::type ref_test_t;
typedef typename boost::add_reference<const TestType>::type cref_test_t;
const bool exact_same = !!boost::is_same<TypeInVariant, TestType>::value;
const bool ref_same = !!boost::is_same<TypeInVariant, ref_test_t>::value;
if (exact_same || ref_same) {
BOOST_TEST(boost::polymorphic_get<TestType>(v));
BOOST_TEST(boost::polymorphic_get<const TestType>(v));
BOOST_TEST(boost::polymorphic_strict_get<TestType>(v));
BOOST_TEST(boost::polymorphic_strict_get<const TestType>(v));
BOOST_TEST(boost::polymorphic_relaxed_get<TestType>(v));
BOOST_TEST(boost::polymorphic_relaxed_get<const TestType>(v));
BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
if (ref_same) {
BOOST_TEST(boost::polymorphic_get<ref_test_t>(v));
BOOST_TEST(boost::polymorphic_get<cref_test_t>(v));
BOOST_TEST(boost::polymorphic_strict_get<ref_test_t>(v));
BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v));
BOOST_TEST(boost::polymorphic_relaxed_get<ref_test_t>(v));
BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v));
}
} else {
BOOST_TEST(!boost::polymorphic_get<TestType>(v));
BOOST_TEST(!boost::polymorphic_get<const TestType>(v));
BOOST_TEST(!boost::polymorphic_strict_get<TestType>(v));
BOOST_TEST(!boost::polymorphic_strict_get<const TestType>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<TestType>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<const TestType>(v));
}
}
template <class T, class V, class TestType>
inline void check_get_on_types_impl_single_type(V* v)
{
typedef typename boost::add_reference<TestType>::type ref_test_t;
typedef typename boost::add_reference<const TestType>::type cref_test_t;
const bool exact_same = !!boost::is_same<T, TestType>::value;
const bool ref_same = !!boost::is_same<T, ref_test_t>::value;
if (exact_same || ref_same) {
BOOST_TEST(boost::get<TestType>(v));
BOOST_TEST(boost::get<const TestType>(v));
BOOST_TEST(boost::strict_get<TestType>(v));
BOOST_TEST(boost::strict_get<const TestType>(v));
BOOST_TEST(boost::relaxed_get<TestType>(v));
BOOST_TEST(boost::relaxed_get<const TestType>(v));
BOOST_TEST(boost::get<cref_test_t>(v));
BOOST_TEST(boost::strict_get<cref_test_t>(v));
BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
if (ref_same) {
BOOST_TEST(boost::get<ref_test_t>(v));
BOOST_TEST(boost::get<cref_test_t>(v));
BOOST_TEST(boost::strict_get<ref_test_t>(v));
BOOST_TEST(boost::strict_get<cref_test_t>(v));
BOOST_TEST(boost::relaxed_get<ref_test_t>(v));
BOOST_TEST(boost::relaxed_get<cref_test_t>(v));
}
} else {
BOOST_TEST(!boost::get<TestType>(v));
BOOST_TEST(!boost::get<const TestType>(v));
BOOST_TEST(!boost::strict_get<TestType>(v));
BOOST_TEST(!boost::strict_get<const TestType>(v));
BOOST_TEST(!boost::relaxed_get<TestType>(v));
BOOST_TEST(!boost::relaxed_get<const TestType>(v));
}
}
template <class T, class V>
inline void check_get_on_types_impl(V* v)
{
check_get_on_types_impl_single_type<T, V, int>(v);
check_polymorphic_get_on_types_impl_single_type<T, V, int>(v);
check_get_on_types_impl_single_type<T, V, base>(v);
check_get_on_types_impl_single_type<T, V, derived1>(v);
check_polymorphic_get_on_types_impl_single_type<T, V, derived1>(v);
check_get_on_types_impl_single_type<T, V, derived2>(v);
check_polymorphic_get_on_types_impl_single_type<T, V, derived2>(v);
check_get_on_types_impl_single_type<T, V, std::string>(v);
check_polymorphic_get_on_types_impl_single_type<T, V, std::string>(v);
// Never exist in here
BOOST_TEST(!boost::relaxed_get<short>(v));
BOOST_TEST(!boost::relaxed_get<const short>(v));
BOOST_TEST(!boost::relaxed_get<char>(v));
BOOST_TEST(!boost::relaxed_get<char*>(v));
BOOST_TEST(!boost::relaxed_get<bool>(v));
BOOST_TEST(!boost::relaxed_get<const bool>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<short>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<const short>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<char>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<char*>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<bool>(v));
BOOST_TEST(!boost::polymorphic_relaxed_get<const bool>(v));
boost::get<T>(*v); // Must compile
boost::get<const T>(*v); // Must compile
boost::strict_get<T>(*v); // Must compile
boost::strict_get<const T>(*v); // Must compile
bool is_ref = boost::is_lvalue_reference<T>::value;
(void)is_ref;
if (!is_ref) {
boost::polymorphic_get<T>(*v); // Must compile
boost::polymorphic_get<const T>(*v); // Must compile
boost::polymorphic_strict_get<T>(*v); // Must compile
boost::polymorphic_strict_get<const T>(*v); // Must compile
}
}
template <class T, class V>
inline void check_get_on_types(V* v)
{
check_get_on_types_impl<T, V>(v);
check_get_on_types_impl<T, const V>(v);
}
inline void get_test()
{
var_t v;
check_get_on_types<int>(&v);
var_t(base()).swap(v);
check_get_on_types<base>(&v);
var_t(derived1()).swap(v);
check_get_on_types<derived1>(&v);
var_t(derived2()).swap(v);
check_get_on_types<derived2>(&v);
var_t(std::string("Hello")).swap(v);
check_get_on_types<std::string>(&v);
var_t_shortened vs = derived2();
check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
// Checking that Base is really determinated
check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs);
vs = derived1();
check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs);
check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs);
// Checking that Base is really determinated
check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs);
check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs);
}
inline void get_test_no_fallback()
{
var_t_no_fallback v;
var_t_no_fallback(base()).swap(v);
check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
check_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
check_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
var_t_no_fallback(derived1()).swap(v);
check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
check_get_on_types_impl_single_type<derived1, var_t_no_fallback, derived1>(&v);
check_get_on_types_impl_single_type<derived1, const var_t_no_fallback, derived1>(&v);
var_t_no_fallback(derived2()).swap(v);
check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v);
check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v);
check_get_on_types_impl_single_type<derived2, var_t_no_fallback, derived2>(&v);
check_get_on_types_impl_single_type<derived2, const var_t_no_fallback, derived2>(&v);
}
inline void get_ref_test()
{
int i = 0;
var_ref_t v(i);
check_get_on_types<int>(&v);
check_get_on_types<int&>(&v);
base b;
var_ref_t v1(b);
check_get_on_types<base>(&v1);
check_get_on_types<base&>(&v1);
derived1 d1;
var_ref_t v2(d1);
check_get_on_types<derived1>(&v2);
check_get_on_types<derived1&>(&v2);
derived2 d2;
var_ref_t v3(d2);
check_get_on_types<derived2>(&v3);
check_get_on_types<derived2&>(&v3);
std::string s("Hello");
var_ref_t v4(s);
check_get_on_types<std::string>(&v4);
check_get_on_types<std::string&>(&v4);
}
inline void get_cref_test()
{
int i = 0;
var_cref_t v(i);
BOOST_TEST(boost::get<const int>(&v));
BOOST_TEST(boost::get<const int&>(&v));
BOOST_TEST(!boost::get<const base>(&v));
base b;
var_cref_t v1(b);
BOOST_TEST(boost::get<const base>(&v1));
BOOST_TEST(!boost::get<const derived1>(&v1));
BOOST_TEST(!boost::get<const int>(&v1));
std::string s("Hello");
const var_cref_t v4 = s;
BOOST_TEST(boost::get<const std::string>(&v4));
BOOST_TEST(!boost::get<const int>(&v4));
}
inline void get_recursive_test()
{
var_req_t v;
check_get_on_types<int>(&v);
var_req_t(base()).swap(v);
check_get_on_types<base>(&v);
var_req_t(derived1()).swap(v);
check_get_on_types<derived1>(&v);
var_req_t(derived2()).swap(v);
check_get_on_types<derived2>(&v);
var_req_t(std::string("Hello")).swap(v);
check_get_on_types<std::string>(&v);
recursive_structure s = { v }; // copying "v"
v = s;
check_get_on_types<recursive_structure>(&v);
}
template <class T>
inline void check_that_does_not_exist_impl()
{
using namespace boost::detail::variant;
BOOST_TEST((holds_element<T, const int>::value));
BOOST_TEST((!holds_element<T, short>::value));
BOOST_TEST((!holds_element<T, short>::value));
BOOST_TEST((!holds_element<T, const short>::value));
BOOST_TEST((!holds_element<T, char*>::value));
BOOST_TEST((!holds_element<T, const char*>::value));
BOOST_TEST((!holds_element<T, char[5]>::value));
BOOST_TEST((!holds_element<T, const char[5]>::value));
BOOST_TEST((!holds_element<T, bool>::value));
BOOST_TEST((!holds_element<T, const bool>::value));
BOOST_TEST((!holds_element<T, boost::recursive_wrapper<int> >::value));
BOOST_TEST((!holds_element<T, boost::recursive_wrapper<short> >::value));
BOOST_TEST((!holds_element<T, boost::detail::reference_content<short> >::value));
BOOST_TEST((holds_element_polymorphic<T, const int>::value));
BOOST_TEST((!holds_element_polymorphic<T, short>::value));
BOOST_TEST((!holds_element_polymorphic<T, short>::value));
BOOST_TEST((!holds_element_polymorphic<T, const short>::value));
BOOST_TEST((!holds_element_polymorphic<T, char*>::value));
BOOST_TEST((!holds_element_polymorphic<T, const char*>::value));
BOOST_TEST((!holds_element_polymorphic<T, char[5]>::value));
BOOST_TEST((!holds_element_polymorphic<T, const char[5]>::value));
BOOST_TEST((!holds_element_polymorphic<T, bool>::value));
BOOST_TEST((!holds_element_polymorphic<T, const bool>::value));
BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<int> >::value));
BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<short> >::value));
BOOST_TEST((!holds_element_polymorphic<T, boost::detail::reference_content<short> >::value));
}
inline void check_that_does_not_exist()
{
using namespace boost::detail::variant;
BOOST_TEST((holds_element<var_t, int>::value));
BOOST_TEST((holds_element<var_ref_t, int>::value));
BOOST_TEST((!holds_element<var_cref_t, int>::value));
check_that_does_not_exist_impl<var_t>();
check_that_does_not_exist_impl<var_ref_t>();
check_that_does_not_exist_impl<var_cref_t>();
check_that_does_not_exist_impl<var_req_t>();
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
class MoveonlyType {
public:
MoveonlyType() {}
~MoveonlyType() {}
MoveonlyType(MoveonlyType&&) {}
void operator=(MoveonlyType&&) {}
private:
MoveonlyType(const MoveonlyType&);
void operator=(const MoveonlyType&);
};
const boost::variant<int, std::string> foo1() { return ""; }
boost::variant<int, std::string> foo2() { return ""; }
inline void get_rvref_test()
{
boost::get<std::string>(foo1());
boost::get<std::string>(foo2());
boost::variant<MoveonlyType, int> v;
v = MoveonlyType();
boost::get<MoveonlyType>(boost::move(v));
v = 3;
v = MoveonlyType();
boost::get<MoveonlyType>(v);
boost::relaxed_get<MoveonlyType&>(boost::variant<MoveonlyType, int>());
v = MoveonlyType();
MoveonlyType moved_from_variant(boost::get<MoveonlyType>(boost::move(v)));
}
#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
int main()
{
get_test();
get_test_no_fallback();
get_ref_test();
get_cref_test();
get_recursive_test();
check_that_does_not_exist();
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
get_rvref_test();
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_multivisit_test.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2013-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/config.hpp"
#include "boost/noncopyable.hpp"
#define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 5
#include "boost/variant/multivisitors.hpp"
#include "boost/variant.hpp"
#include "boost/core/lightweight_test.hpp"
struct my_noncopyable : boost::noncopyable {
my_noncopyable(){}
~my_noncopyable(){}
};
typedef boost::variant<my_noncopyable, int> variant_noncopy_t;
typedef boost::variant<char, unsigned char, signed char, unsigned short, int> variant5_t;
struct test_visitor: boost::static_visitor<> {
// operators that shall not be called
template <class T1, class T2, class T3>
void operator()(T1&, T2&, T3&) const
{
BOOST_TEST(false);
}
template <class T1, class T2, class T3, class T4>
void operator()(T1&, T2&, T3&, T4&) const
{
BOOST_TEST(false);
}
template <class T1, class T2, class T3, class T4, class T5>
void operator()(T1&, T2&, T3&, T4&, T5&) const
{
BOOST_TEST(false);
}
// operators that are OK to call
void operator()(char v0, unsigned char v1, signed char v2) const
{
BOOST_TEST(v0 == 0);
BOOST_TEST(v1 == 1);
BOOST_TEST(v2 == 2);
}
void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3) const
{
BOOST_TEST(v0 == 0);
BOOST_TEST(v1 == 1);
BOOST_TEST(v2 == 2);
BOOST_TEST(v3 == 3);
}
void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3, int v4) const
{
BOOST_TEST(v0 == 0);
BOOST_TEST(v1 == 1);
BOOST_TEST(v2 == 2);
BOOST_TEST(v3 == 3);
BOOST_TEST(v4 == 4);
}
// Noncopyables
void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
BOOST_TEST(true);
}
void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
BOOST_TEST(true);
}
void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
BOOST_TEST(true);
}
void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const {
BOOST_TEST(true);
}
};
typedef boost::variant<int, double, bool> bool_like_t;
typedef boost::variant<int, double> arithmetics_t;
struct if_visitor: public boost::static_visitor<arithmetics_t> {
template <class T0, class T1, class T2>
arithmetics_t operator()(T0 b, T1 v1, T2 v2) const {
if (!!b) {
return v1;
} else {
return v2;
}
}
};
int main()
{
test_visitor v;
variant5_t v_array5[5];
v_array5[0] = char(0);
v_array5[1] = static_cast<unsigned char>(1);
v_array5[2] = static_cast<signed char>(2);
v_array5[3] = static_cast<unsigned short>(3);
v_array5[4] = static_cast<int>(4);
boost::apply_visitor(v, v_array5[0], v_array5[1], v_array5[2]);
boost::apply_visitor(test_visitor(), v_array5[0], v_array5[1], v_array5[2]);
// Following test also pass, but requires many Gigabytes of RAM for compilation and compile for about 15 minutes
//#define BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
boost::apply_visitor(v, v_array5[0], v_array5[1], v_array5[2], v_array5[3]);
boost::apply_visitor(test_visitor(), v_array5[0], v_array5[1], v_array5[2], v_array5[3]);
boost::apply_visitor(v, v_array5[0], v_array5[1], v_array5[2], v_array5[3], v_array5[4]);
boost::apply_visitor(test_visitor(), v_array5[0], v_array5[1], v_array5[2], v_array5[3], v_array5[4]);
#endif
bool_like_t v0(1), v1(true), v2(1.0);
BOOST_TEST(
boost::apply_visitor(if_visitor(), v0, v1, v2)
==
arithmetics_t(true)
);
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
if_visitor if_vis;
BOOST_TEST(
boost::apply_visitor(if_vis)(v0, v1, v2)
==
arithmetics_t(true)
);
#endif
variant_noncopy_t vnonc[6];
boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2]);
boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3]);
#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME
boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4]);
boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4], vnonc[5]);
#endif
return boost::report_errors();
}

View File

@@ -0,0 +1,474 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_nonempty_check.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2014-2022 Antony Polukhin
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// In this file we are making tests to ensure that variant guarantees nonemptiness.
//
// For that purpose we create a `throwing_class`, that throws exception at a specified
// assignment attempt. If exception was thrown during move/assignemnt operation we make sure
// that data in variant is same as before move/assignemnt operation or that a fallback type is
// stored in variant.
//
// Different nonthrowing_class'es are used to tests different variant internal policies:
// with/without fallback type + throw/nothrow copyable + throw/nothrow movable
#include "boost/variant/variant.hpp"
#include "boost/variant/get.hpp"
#include "boost/core/lightweight_test.hpp"
#include <stdexcept>
struct exception_on_assignment : std::exception {};
struct exception_on_move_assignment : exception_on_assignment {};
void prevent_compiler_noexcept_detection() {
char* p = new char;
*p = '\0';
delete p;
}
struct throwing_class {
int trash;
enum helper_enum {
do_not_throw = 780,
throw_after_5,
throw_after_4,
throw_after_3,
throw_after_2,
throw_after_1
};
bool is_throw() {
if (trash < do_not_throw) {
return true;
}
if (trash > do_not_throw && trash <= throw_after_1) {
++ trash;
return false;
}
return trash != do_not_throw;
}
throwing_class(int value = 123) BOOST_NOEXCEPT_IF(false) : trash(value) {
prevent_compiler_noexcept_detection();
}
throwing_class(const throwing_class& b) BOOST_NOEXCEPT_IF(false) : trash(b.trash) {
if (is_throw()) {
throw exception_on_assignment();
}
}
const throwing_class& operator=(const throwing_class& b) BOOST_NOEXCEPT_IF(false) {
trash = b.trash;
if (is_throw()) {
throw exception_on_assignment();
}
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
throwing_class(throwing_class&& b) BOOST_NOEXCEPT_IF(false) : trash(b.trash) {
if (is_throw()) {
throw exception_on_move_assignment();
}
}
const throwing_class& operator=(throwing_class&& b) BOOST_NOEXCEPT_IF(false) {
trash = b.trash;
if (is_throw()) {
throw exception_on_move_assignment();
}
return *this;
}
#endif
virtual ~throwing_class() {}
};
struct nonthrowing_class {
int trash;
nonthrowing_class() BOOST_NOEXCEPT_IF(false) : trash(123) {
prevent_compiler_noexcept_detection();
}
nonthrowing_class(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class& operator=(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
nonthrowing_class(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class& operator=(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#endif
};
struct nonthrowing_class2 {
int trash;
nonthrowing_class2() BOOST_NOEXCEPT_IF(false) : trash(123) {
prevent_compiler_noexcept_detection();
}
};
struct nonthrowing_class3 {
int trash;
nonthrowing_class3() BOOST_NOEXCEPT_IF(true) : trash(123) {}
nonthrowing_class3(const nonthrowing_class3&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class3& operator=(const nonthrowing_class3&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
nonthrowing_class3(nonthrowing_class3&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class3& operator=(nonthrowing_class3&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#endif
};
struct nonthrowing_class4 {
int trash;
nonthrowing_class4() BOOST_NOEXCEPT_IF(false) : trash(123) {
prevent_compiler_noexcept_detection();
}
nonthrowing_class4(const nonthrowing_class4&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class4& operator=(const nonthrowing_class4&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
nonthrowing_class4(nonthrowing_class4&&) BOOST_NOEXCEPT_IF(true) {
}
const nonthrowing_class4& operator=(nonthrowing_class4&&) BOOST_NOEXCEPT_IF(true) {
return *this;
}
#endif
};
// Tests /////////////////////////////////////////////////////////////////////////////////////
template <class Nonthrowing>
inline void check_1_impl(int helper)
{
boost::variant<throwing_class, Nonthrowing> v;
try {
v = throwing_class(helper);
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<throwing_class>(&v));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<throwing_class>(&v));
}
try {
throwing_class tc(helper);
v = tc;
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<throwing_class>(&v));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<throwing_class>(&v));
}
}
inline void check_1(int helper = 1)
{
check_1_impl<nonthrowing_class>(helper);
check_1_impl<nonthrowing_class2>(helper);
check_1_impl<nonthrowing_class3>(helper);
check_1_impl<nonthrowing_class4>(helper);
check_1_impl<boost::blank>(helper);
}
template <class Nonthrowing>
inline void check_2_impl(int helper)
{
boost::variant<Nonthrowing, throwing_class> v;
try {
v = throwing_class(helper);
BOOST_TEST(v.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<Nonthrowing>(&v));
}
try {
throwing_class cl(helper);
v = cl;
BOOST_TEST(v.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v.which());
BOOST_TEST(boost::get<Nonthrowing>(&v));
}
}
inline void check_2(int helper = 1)
{
check_2_impl<nonthrowing_class>(helper);
check_2_impl<nonthrowing_class2>(helper);
check_2_impl<nonthrowing_class3>(helper);
check_2_impl<nonthrowing_class4>(helper);
check_2_impl<boost::blank>(helper);
}
template <class Nonthrowing>
inline void check_3_impl(int helper)
{
boost::variant<Nonthrowing, throwing_class> v1, v2;
swap(v1, v2);
try {
v1 = throwing_class(helper);
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v1.which());
BOOST_TEST(boost::get<Nonthrowing>(&v1));
}
try {
v2 = throwing_class(helper);
BOOST_TEST(v2.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v2));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v2.which());
BOOST_TEST(boost::get<Nonthrowing>(&v2));
}
if (!v1.which() && !v2.which()) {
swap(v1, v2); // Make sure that two backup holders swap well
BOOST_TEST(!v1.which());
BOOST_TEST(boost::get<Nonthrowing>(&v1));
BOOST_TEST(!v2.which());
BOOST_TEST(boost::get<Nonthrowing>(&v2));
v1 = v2;
}
}
inline void check_3(int helper = 1)
{
check_3_impl<nonthrowing_class>(helper);
check_3_impl<nonthrowing_class2>(helper);
check_3_impl<nonthrowing_class3>(helper);
check_3_impl<nonthrowing_class4>(helper);
check_3_impl<boost::blank>(helper);
}
inline void check_4(int helper = 1)
{
// This one has a fallback
boost::variant<int, throwing_class> v1, v2;
swap(v1, v2);
try {
v1 = throwing_class(helper);
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v1.which());
BOOST_TEST(boost::get<int>(&v1));
}
try {
v2 = throwing_class(helper);
BOOST_TEST(v2.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v2));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(!v2.which());
BOOST_TEST(boost::get<int>(&v2));
}
if (!v1.which() && !v2.which()) {
swap(v1, v2);
BOOST_TEST(!v1.which());
BOOST_TEST(boost::get<int>(&v1));
BOOST_TEST(!v2.which());
BOOST_TEST(boost::get<int>(&v2));
v1 = v2;
}
}
template <class Nonthrowing>
inline void check_5_impl(int helper)
{
boost::variant<Nonthrowing, throwing_class> v1, v2;
throwing_class throw_not_now;
throw_not_now.trash = throwing_class::do_not_throw;
v1 = throw_not_now;
v2 = throw_not_now;
boost::get<throwing_class>(v1).trash = 1;
boost::get<throwing_class>(v2).trash = 1;
try {
v1 = throwing_class(helper);
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
}
boost::get<throwing_class>(v1).trash = throwing_class::do_not_throw;
boost::get<throwing_class>(v2).trash = throwing_class::do_not_throw;
v1 = Nonthrowing();
v2 = Nonthrowing();
try {
v1 = throwing_class(helper);
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v1.which() == 0);
BOOST_TEST(boost::get<Nonthrowing>(&v1));
}
int v1_type = v1.which();
int v2_type = v2.which();
try {
swap(v1, v2); // Make sure that backup holders swap well
BOOST_TEST(v1.which() == v2_type);
BOOST_TEST(v2.which() == v1_type);
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v1.which() == v1_type);
BOOST_TEST(v2.which() == v2_type);
}
}
inline void check_5(int helper = 1)
{
check_5_impl<nonthrowing_class>(helper);
check_5_impl<nonthrowing_class2>(helper);
check_5_impl<nonthrowing_class3>(helper);
check_5_impl<nonthrowing_class4>(helper);
check_5_impl<boost::blank>(helper);
}
template <class Nonthrowing>
inline void check_6_impl(int helper)
{
boost::variant<Nonthrowing, throwing_class> v1, v2;
throwing_class throw_not_now;
throw_not_now.trash = throwing_class::do_not_throw;
v1 = throw_not_now;
v2 = throw_not_now;
v1 = throw_not_now;
v2 = throw_not_now;
swap(v1, v2);
boost::get<throwing_class>(v1).trash = 1;
boost::get<throwing_class>(v2).trash = 1;
v1 = throwing_class(throw_not_now);
v2 = v1;
v1 = Nonthrowing();
try {
throwing_class tc;
tc.trash = helper;
v1 = tc;
BOOST_TEST(v1.which() == 1);
BOOST_TEST(boost::get<throwing_class>(&v1));
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v1.which() == 0);
}
v2 = Nonthrowing();
try {
v2 = 2;
BOOST_TEST(false);
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v2.which() == 0);
}
// Probably the most significant test:
// unsuccessful swap must preserve old values of variant
v1 = throw_not_now;
boost::get<throwing_class>(v1).trash = helper;
try {
swap(v1, v2);
} catch (const exception_on_assignment& /*e*/) {
BOOST_TEST(v1.which() == 1);
BOOST_TEST(v2.which() == 0);
BOOST_TEST(boost::get<throwing_class>(v1).trash == helper);
}
}
inline void check_6(int helper = 1)
{
check_6_impl<nonthrowing_class>(helper);
check_6_impl<nonthrowing_class2>(helper);
check_6_impl<nonthrowing_class3>(helper);
check_6_impl<nonthrowing_class4>(helper);
check_6_impl<boost::blank>(helper);
}
int main()
{
// throwing_class::throw_after_1 + 1 => throw on first assignment/construction
// throwing_class::throw_after_1 => throw on second assignment/construction
// throwing_class::throw_after_2 => throw on third assignment/construction
// ...
for (int i = throwing_class::throw_after_1 + 1; i != throwing_class::do_not_throw; --i) {
check_1(i);
check_2(i);
check_3(i);
check_4(i);
check_5(i);
check_6(i);
}
return boost::report_errors();
}

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2017
// Mikhail Maximov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// The test is base on https://svn.boost.org/trac/boost/ticket/8554
// variant was not able to extract types from mpl::joint_view
#include <string>
#include "boost/config.hpp"
#include "boost/core/lightweight_test.hpp"
#include "boost/variant.hpp"
#include "boost/mpl/joint_view.hpp"
#include "boost/mpl/insert_range.hpp"
#include "boost/mpl/set.hpp"
template<class T, class Variant>
void check_exception_on_get(Variant& v) {
try {
boost::get<T>(v);
BOOST_ERROR("Expected exception boost::bad_get, but got nothing.");
} catch (boost::bad_get&) { //okay it is expected behaviour
} catch (...) { BOOST_ERROR("Expected exception boost::bad_get, but got something else."); }
}
void test_joint_view() {
typedef boost::variant<int> v1;
typedef boost::variant<std::string> v2;
typedef boost::make_variant_over<boost::mpl::joint_view<v1::types, v2::types>::type>::type v3;
v1 a = 1;
v2 b = "2";
v3 c = a;
BOOST_TEST(boost::get<int>(c) == 1);
BOOST_TEST(c.which() == 0);
v3 d = b;
BOOST_TEST(boost::get<std::string>(d) == "2");
BOOST_TEST(d.which() == 1);
check_exception_on_get<std::string>(c);
check_exception_on_get<int>(d);
}
void test_set() {
typedef boost::mpl::set2< std::string, int > types;
typedef boost::make_variant_over< types >::type v;
v a = 1;
BOOST_TEST(boost::get<int>(a) == 1);
check_exception_on_get<std::string>(a);
a = "2";
BOOST_TEST(boost::get<std::string>(a) == "2");
check_exception_on_get<int>(a);
}
int main()
{
test_joint_view();
test_set();
return boost::report_errors();
}

Some files were not shown because too many files have changed in this diff Show More