Bump mapbox/variant to version 1.2.0 (#6898)

This commit is contained in:
Siarhei Fedartsou 2024-05-24 20:39:45 +02:00 committed by GitHub
parent babdced52f
commit 8b48e2ccc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 10327 additions and 9617 deletions

View File

@ -21,6 +21,7 @@
- NodeJS: - NodeJS:
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452) - CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
- Misc: - Misc:
- CHANGED: Bump mapbox/variant to version 1.2.0 [#6898](https://github.com/Project-OSRM/osrm-backend/pull/6898)
- CHANGED: Avoid copy of std::function-based callback in path unpacking [#6895](https://github.com/Project-OSRM/osrm-backend/pull/6895) - CHANGED: Avoid copy of std::function-based callback in path unpacking [#6895](https://github.com/Project-OSRM/osrm-backend/pull/6895)
- CHANGED: Replace boost::hash by std::hash [#6892](https://github.com/Project-OSRM/osrm-backend/pull/6892) - CHANGED: Replace boost::hash by std::hash [#6892](https://github.com/Project-OSRM/osrm-backend/pull/6892)
- CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551) - CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551)

View File

@ -13,7 +13,7 @@ OSMIUM_PATH="osmcode/libosmium"
OSMIUM_TAG=v2.14.0 OSMIUM_TAG=v2.14.0
VARIANT_PATH="mapbox/variant" VARIANT_PATH="mapbox/variant"
VARIANT_TAG=v1.1.3 VARIANT_TAG=v1.2.0
SOL_PATH="ThePhD/sol2" SOL_PATH="ThePhD/sol2"
SOL_TAG=v2.17.5 SOL_TAG=v2.17.5
@ -34,7 +34,7 @@ FMT_PATH="fmtlib/fmt"
FMT_TAG=v10.2.1 FMT_TAG=v10.2.1
function update_subtree () { function update_subtree () {
name=${1^^} name=$(echo "$1" | tr '[:lower:]' '[:upper:]')
path=$(tmpvar=${name}_PATH && echo ${!tmpvar}) path=$(tmpvar=${name}_PATH && echo ${!tmpvar})
tag=$(tmpvar=${name}_TAG && echo ${!tmpvar}) tag=$(tmpvar=${name}_TAG && echo ${!tmpvar})
dir=$(basename $path) dir=$(basename $path)

1
third_party/variant/.mason vendored Submodule

@ -0,0 +1 @@
Subproject commit 6adb140160cb549400f73ea35c1d9eb5782210e0

View File

@ -2,102 +2,123 @@ language: generic
sudo: false sudo: false
# Save common build configurations as shortcuts, so we can reference them later.
addons_shortcuts:
addons_clang35: &clang35
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
packages: [ 'clang-3.5', 'llvm-3.5-dev' ]
addons_clang36: &clang36
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ]
packages: [ 'clang-3.6' ]
addons_clang37: &clang37
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7' ]
packages: [ 'clang-3.7' ]
addons_clang38: &clang38
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8' ]
packages: [ 'clang-3.8']
addons_clang39: &clang39
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise' ]
packages: [ 'clang-3.9']
addons_gcc47: &gcc47
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.7' ]
addons_gcc48: &gcc48
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.8' ]
addons_gcc49: &gcc49
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.9' ]
addons_gcc5: &gcc5
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-5' ]
matrix: matrix:
include: include:
# clang++ 4.0 via mason with -flto and -fsanitize=cfi
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-flto -fsanitize=cfi -fvisibility=hidden" LDFLAGS="-flto -fsanitize=cfi -fvisibility=hidden"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
- ./.mason/mason install binutils 2.27
- export PATH=$(./.mason/mason prefix binutils 2.27)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=address
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -fno-common" LDFLAGS="-fsanitize=address" ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1
sudo: required
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=undefined
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=integer
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=integer" LDFLAGS="-fsanitize=integer"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
# clang++ 4.0 via mason with -fsanitize=safe-stack
- os: linux
compiler: "clang++-40-mason"
env: CXX=clang++-4.0 CXXFLAGS="-fsanitize=safe-stack" LDFLAGS="-fsanitize=safe-stack"
addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libstdc++-4.9-dev' ]
before_install:
- git submodule update --init
- ./.mason/mason install clang++ 4.0.1
- export PATH=$(./.mason/mason prefix clang++ 4.0.1)/bin:${PATH}
- os: osx - os: osx
osx_image: xcode7 osx_image: xcode8
env: TEST_GYP_BUILD=True env: OSX_OLDEST_SUPPORTED=10.7 TEST_GYP_BUILD=True
compiler: clang
- os: osx
osx_image: xcode8
env: OSX_OLDEST_SUPPORTED=10.12
compiler: clang compiler: clang
- os: linux - os: linux
compiler: "clang35" compiler: "clang35"
env: CXX=clang++-3.5 COVERAGE=True env: CXX=clang++-3.5 COVERAGE=True
addons: *clang35 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
packages: [ 'clang-3.5', 'libstdc++-4.9-dev' ]
- os: linux - os: linux
compiler: "clang36" compiler: "clang36"
env: CXX=clang++-3.6 env: CXX=clang++-3.6
addons: *clang36 addons:
- os: linux apt:
compiler: "clang37" sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ]
env: CXX=clang++-3.7 packages: [ 'clang-3.6' ]
addons: *clang37
- os: linux
compiler: "clang38"
env: CXX=clang++-3.8
addons: *clang38
- os: linux
compiler: "clang38"
env: CXX=clang++-3.8 CXX_STD=c++14
addons: *clang38
# not whitelisted yet: https://github.com/travis-ci/apt-package-whitelist/issues/2764
#- os: linux
# compiler: "clang39"
# env: CXX=clang++-3.9
# addons: *clang39
- os: linux
compiler: "gcc47"
env: CXX=g++-4.7
addons: *gcc47
- os: linux - os: linux
compiler: "gcc48" compiler: "gcc48"
env: CXX=g++-4.8 env: CXX=g++-4.8
addons: *gcc48 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-4.8' ]
- os: linux - os: linux
compiler: "gcc49" compiler: "gcc49"
env: CXX=g++-4.9 env: CXX=g++-4.9
addons: *gcc49 addons:
- os: linux apt:
compiler: "gcc49" sources: [ 'ubuntu-toolchain-r-test' ]
env: CXX=g++-4.9 CXX_STD=c++14 packages: [ 'g++-4.9' ]
addons: *gcc49
- os: linux - os: linux
compiler: "gcc5" compiler: "gcc5"
env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" env: CXX=g++-5
addons: *gcc5 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-5' ]
- os: linux - os: linux
compiler: "gcc5" compiler: "gcc6"
env: CXX=g++-5 CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1" env: CXX=g++-6 CXX_STD=c++14
addons: *gcc5 addons:
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'g++-6' ]
before_install: install:
- echo ${CXX} - echo ${CXX}
- if [[ $(uname -s) == 'Linux' ]]; then - if [[ $(uname -s) == 'Linux' ]]; then
export PYTHONPATH=$(pwd)/.local/lib/python2.7/site-packages; export PYTHONPATH=$(pwd)/.local/lib/python2.7/site-packages;
@ -108,7 +129,17 @@ before_install:
PYTHONUSERBASE=$(pwd)/.local pip install --user cpp-coveralls; PYTHONUSERBASE=$(pwd)/.local pip install --user cpp-coveralls;
fi fi
install: script:
# Build in Release
- make
- make test
- make bench
- make sizes
- scripts/run_compilation_failure_tests.sh
- make clean;
# Build in Debug
- export BUILDTYPE=Debug
- make
- make test - make test
- make bench - make bench
- make sizes - make sizes
@ -118,11 +149,11 @@ install:
make gyp; make gyp;
fi fi
script: after_script:
- if [[ ${COVERAGE:-0} == 'True' ]]; then - if [[ ${COVERAGE:-0} == 'True' ]]; then
make clean; make clean;
make coverage; make coverage;
./out/cov-test; ./out/cov-test;
cp unit*gc* test/; cp unit*gc* test/;
./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp; ./.local/bin/cpp-coveralls --gcov /usr/bin/llvm-cov-3.5 --gcov-options '\-lp' -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp variant_cast.hpp;
fi fi

420
third_party/variant/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,420 @@
# Variant changelog
## 1.2.0
Released: July 3, 2020
(82f9561)
* Use perfect forwarding for internal value types deductions (#178) (#180)
* Implement support for "moving" values out (#142) (#178) (#180)
* Preserve ability to specify explicit `return_type` in visitors (#181)
* Add self-assignment checks in copy and move assignment operator= (#164)
* Add relevant tests
## 1.1.6
Released: April 25, 2019
(a4f87dc)
* make type used for `type_index` configurable via `type_index_t` typdef + use `unsigned int` by default. This addresses `sizeof` discrepancies between boost/std/mapbox variants (ref #19) [view commit](http://github.com/mapbox/variant/commit/9eec1fd48947d81af3debb82686c593b15f79aad)
* use `mapbox::util::type_index_t` (#19) [view commit](http://github.com/mapbox/variant/commit/05ee9aca16c3968e34db3b241c44eecb981344e0)
* Ensure internal index type is capable of holding all alternatives (ref #138) [view commit](http://github.com/mapbox/variant/commit/fa8e124a2367abc9c06f7e83926691085eed45c0)
* Add compile time check to disallow array types as alternatives. [view commit](http://github.com/mapbox/variant/commit/3f6fd131ef07a091338cec81ec8d23d6ca44528d)
* Make `type_index_t` configurable at compile time via `MAPBOX_VARIANT_MINIMIZE_SIZE` and `MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED`. Default is `unsigned int`. (ref #138) [view commit](http://github.com/mapbox/variant/commit/35487cd39400b9a4bd30a18e6dfbf9cb1aaa80cd)
* add missing <limits> [view commit](http://github.com/mapbox/variant/commit/c839c666c324306a252b0fbcadd31e80e02e2898)
* Adds a test for polymorphic lambdas in match, resolves #140 [view commit](http://github.com/mapbox/variant/commit/9ac8978f5125182ac1bd9a1b68533bf9695f7289)
* Merge pull request #138 from mapbox/sizeof [view commit](http://github.com/mapbox/variant/commit/3d807d31621d52a8b27494c8f80aa50f6464f17d)
* Merge pull request #141 from mapbox/match-otherwise [view commit](http://github.com/mapbox/variant/commit/916139a2e51e125816efce6e19d428385601273f)
* Update bundled Catch to v1.9.0 [view commit](http://github.com/mapbox/variant/commit/f9c265d7e7a188aa4437f534d4c0648af0118b51)
* REQUIRE_THROWS etc take an expression not a block [view commit](http://github.com/mapbox/variant/commit/a064940e2ce7e40ef5e4db5710b399c68a71be4b)
* Merge pull request #143 from tomhughes/catch [view commit](http://github.com/mapbox/variant/commit/550ac2f159ca883d360c196149b466955c77a573)
* Add static_variant_cast, dynamic_variant_cast [view commit](http://github.com/mapbox/variant/commit/51fccd755b05ee9d3dec9da239acd15d0823c381)
* Merge pull request #144 from narizhny/Casts [view commit](http://github.com/mapbox/variant/commit/291121f6ac682c6cc5a7a69f253492f03ca7324f)
* recursive_wrapper fail to compile when used with 2 classes which are base and derived #146 [view commit](http://github.com/mapbox/variant/commit/7a541ba10d2eb9a9da0f11bb27319cd125d43a3d)
* recursive_wrapper test - avoid constructing new functor in recursive calls, call itself via `this` pointer. [view commit](http://github.com/mapbox/variant/commit/ea106db54b167b8dce7c0b3b9b59bb06b209db33)
* Merge branch 'master' of https://github.com/BlueSolei/variant into BlueSolei-master [view commit](http://github.com/mapbox/variant/commit/195367cfc19e1e08933487fa7cc56cb7f6d25cc8)
* Merge branch 'BlueSolei-master' [view commit](http://github.com/mapbox/variant/commit/e01b7bf3334e788fb99f4a510d5bc87a4a581342)
* add test for ref #147 + https://github.com/mapbox/variant/pull/147 [view commit](http://github.com/mapbox/variant/commit/6247207595902dbf898a430346335af2a3485c74)
* - Add a project mapbox_variant. - Use of the 'os' module to capture CXX_STD. - Common configs moved to project. - Built targets moved to 'out' directory. [view commit](http://github.com/mapbox/variant/commit/b2471ffc74c163194943b17b2b2c5758c59655ca)
* - Remove the use of boost libraries. - Add default build. [view commit](http://github.com/mapbox/variant/commit/561a09dd005468f9cdef651030471a1215f1885f)
* - Use of the module 'os' to get BOOST_DIR. - Add macro SINGLE_THREADED to single threading mode. - Define single threading mode as default. - Add lambda_overload_test and hashable_test. [view commit](http://github.com/mapbox/variant/commit/bd0a2d559724b8daa7d1ff33df90976e26a595aa)
* - Add auxiliar rule exe-test. [view commit](http://github.com/mapbox/variant/commit/04a6797a6aa2a86dd3eb6517893255c010f6e524)
* Merge pull request #153 from ricardocosme/boost-build [view commit](http://github.com/mapbox/variant/commit/266f68d9f1c3ad65e6d6c264f0130bc4c652618a)
* Use forwarding reference in make_visitor and visitor [view commit](http://github.com/mapbox/variant/commit/9f991da78d3146d32be67695a89c2b1197c826b2)
* Add copy assignment and move assignment operators. [view commit](http://github.com/mapbox/variant/commit/f0b50062b4fd2bf2b86aeada2efa8e36cfa6cb1c)
* Merge pull request #154 from ricardocosme/forwarding_reference_make_visitor [view commit](http://github.com/mapbox/variant/commit/b78b51548743737357e5b3bbe296f465d5f4fdae)
* add CHANGELOG.md skeleton [view commit](http://github.com/mapbox/variant/commit/555436f715e5e0929a13664f0911ecc4931356d1)
* add <sha1> to CHANGELOG entries. [view commit](http://github.com/mapbox/variant/commit/6497bce683e6e8edf80f80bc4fed65235690b335)
* update CHANGELOG (git log <tag1>...<tag2> --pretty=format:'* %s [view commit](http://github.com/mapbox/variant/commit/%H)' --reverse) [view commit](http://github.com/mapbox/variant/commit/75bb549d233eb94c74d2730dc3a8d8ed35c87f3d)
* use full sha1 [view commit](http://github.com/mapbox/variant/commit/ba3085a5eb6e874d43432dc75f3392092e1e7214)
* add intial `variant_alternative` implementation (#161 http://en.cppreference.com/w/cpp/utility/variant/variant_alternative) [view commit](http://github.com/mapbox/variant/commit/43357808cc93e69d2975e31e68986137ac5e88c9)
* add lost test check + remove stderr [view commit](http://github.com/mapbox/variant/commit/4b98c485cf7d74691f7921145054641daa66936e)
* alternative implementation of `variant_alternative` [view commit](http://github.com/mapbox/variant/commit/3449d00cf525d8ef98cee0f4a276e2928398a8f9)
* add `variant_alternative_t` [view commit](http://github.com/mapbox/variant/commit/3ffef950b005f31961f167242911b2f97d2634c3)
* add optimized 'variant_alternative' implementation usinh built-in `__type_pack_element` when available (clang++) [view commit](http://github.com/mapbox/variant/commit/ae193141379c1706e17098c67c5b4e4f48b19c48)
* add compile index in range check for __type_pack_element branch. [view commit](http://github.com/mapbox/variant/commit/8b1de314711bff2f9f3c748ac0ed7cd7d6400331)
* fix preprocessor logic [view commit](http://github.com/mapbox/variant/commit/30560e19e60c23227b29bc3434a163d2343333d3)
* add `variant_size` helper [view commit](http://github.com/mapbox/variant/commit/835ebc19321c6a9696a2072b7fbd5ca3de818860)
* Merge pull request #162 from mapbox/variant_alternative [view commit](http://github.com/mapbox/variant/commit/237f83cad2c76b1717ba4076c30aca32339336a8)
* Removes deprecated static_visitor to avoid msvc C4996 compiler warning [view commit](http://github.com/mapbox/variant/commit/215d64585ef92e16f18f5da81195b0279f53f599)
* Merge pull request #163 from MaxRis/master [view commit](http://github.com/mapbox/variant/commit/859a8c933a0c2ab18941acb9dcf834799c0de46c)
* Fix README.md issues [view commit](http://github.com/mapbox/variant/commit/0888a8e92df4c1cfd85419b05910355b2d78013b)
* Merge pull request #165 from nick70/master [view commit](http://github.com/mapbox/variant/commit/5eee328d69aaa805bd0b43bdaede12a8eb4632eb)
* Fix the noexcept specifications for move assignment and conversion. [view commit](http://github.com/mapbox/variant/commit/9c81bef8cf285d9fb45f1eaf9b29eba4fee08d1b)
* Merge pull request #160 from mlogan/master [view commit](http://github.com/mapbox/variant/commit/256ddd55582bb7c06c342315dbacc6a42fee4b34)
* report actual file size not allocated size. [view commit](http://github.com/mapbox/variant/commit/ef3856c85f389d4be7feb6555336168c4adcfa0e)
* use `ls -lah` as `du -h --apparent-size` is not universally supported. [view commit](http://github.com/mapbox/variant/commit/a64062576d9af09469183a94b9770c8e7f877a93)
* fix Makefile [view commit](http://github.com/mapbox/variant/commit/502e32b8bade6e19d7fe511f4634e7033f61235f)
* try fixing travis via upgrading clang++ from 3.9.1 -> 4.0.1 [view commit](http://github.com/mapbox/variant/commit/f31bcfb4bc97cf4c5e89b01bbfa7df4cd553f576)
* steady .. downgrade clang++ to 4.0.0 [view commit](http://github.com/mapbox/variant/commit/11a36a9f12adc30ac47afc9681ec8aa1a2d68c28)
* update mason [view commit](http://github.com/mapbox/variant/commit/fe0a0666fc734033f6a9cd2256226eec5943138a)
* update mason + update clang++ to 4.0.1 [view commit](http://github.com/mapbox/variant/commit/c1a14e7d9e9a10ea7d793d83043d9a18b974ca8e)
* Run ASAN builda in isolated VM via `sudo : required` [view commit](http://github.com/mapbox/variant/commit/5a5ecca5bef02072109a714bab840a36ea772f01)
* Merge pull request #167 from mapbox/clang++4 [view commit](http://github.com/mapbox/variant/commit/0f734f01e685a298e3756d30044a4164786c58c5)
* Moved to in-class initialization [view commit](http://github.com/mapbox/variant/commit/2fef61f08e44bcc99b1acc21ea78554b08d8f6e7)
* Merge pull request #171 from mapbox/jrex-mute-clang-analyzer [view commit](http://github.com/mapbox/variant/commit/0305fdb2a462ca39db7b8cce189561bed17b48
## 1.1.5
Released: January 7, 2017
(d2588a8f1d6b5d480d228e6d8a906ce634bdea9a)
* add package.json for publishing to npm [view commit](http://github.com/mapbox/variant/commit/cb5635ba2556d76aaba97e4d0fc14b82b48f8b61)
* test with clang 3.9 and g++-6 [view commit](http://github.com/mapbox/variant/commit/efa75df2735d3f5a5fa2646528d4006bf9b5b3dc)
* travis: fix addons [view commit](http://github.com/mapbox/variant/commit/ce2eea64499cd37eec7932ddf82f72b9f1a1b79e)
* makefile improvements [view commit](http://github.com/mapbox/variant/commit/c81b475b40797d503f18ddad4c065f6b1694d341)
* upgrade boost to 1.62.0 [view commit](http://github.com/mapbox/variant/commit/b9c58d631a22e97f4069a819765f5c157525df6a)
* upgrade mason [view commit](http://github.com/mapbox/variant/commit/a760cea8dab53e587498470861b364f1256a5e0d)
* test clang++ via mason [view commit](http://github.com/mapbox/variant/commit/84eeb54c9408297db4bc57e3ea5a1b3d9f075a66)
* fix clang++ PATH [view commit](http://github.com/mapbox/variant/commit/e07a533a8f451fe541db683fc713eb0012730115)
* disable clang++ 3.9, will work on getting working in a branch [view commit](http://github.com/mapbox/variant/commit/702826365d1ea13710b82949c254af5920c92999)
* test with clang++ sanitizers and flto [view commit](http://github.com/mapbox/variant/commit/9b2de45460f4df3a22c6607043d50df730dd42af)
* fix LDFLAGS [view commit](http://github.com/mapbox/variant/commit/20d693ed9a04cc6b689f4c6a1ed58c96f964b08a)
* -fsanitize=cfi and -fsanitize=safe-stack [view commit](http://github.com/mapbox/variant/commit/d1bb6e54608c6bfe3970b2653971da49b3c15ef8)
* more sanitizer options [view commit](http://github.com/mapbox/variant/commit/4fe5ced5db2cb46b23a6e326b5bf9292d95c0642)
* re-enable older compilers, trim excess [view commit](http://github.com/mapbox/variant/commit/6317a0b7406395729139327a83a71cfa14513fac)
* avoid expensive instantiation of tuple constructor in noexcept [view commit](http://github.com/mapbox/variant/commit/4febf973c2a0fc297869d78fc82368a16ee7f4fb)
* Merge pull request #132 from lightmare/avoid-tuple-instantiation [view commit](http://github.com/mapbox/variant/commit/18919174da93165a79ca5fdbfde4b172182c6156)
* enable -Werror, suppress warnings from non variant headers using isystem [view commit](http://github.com/mapbox/variant/commit/253047f53549c3fb1df441859cfd42aecc9f3a8f)
* fix conversion warnings [view commit](http://github.com/mapbox/variant/commit/539d712746d08a172e68a47f7aa73ffdda40b70b)
* build in both release and debug on travis [view commit](http://github.com/mapbox/variant/commit/cf9a534991b5a36f86674975768e0a1600c776be)
* fortification flags + -pthreads for linux where needed [view commit](http://github.com/mapbox/variant/commit/886377de081dd8099ef4a7869ae3ff5d6c850c8d)
* try without pthreads [view commit](http://github.com/mapbox/variant/commit/1023f2d9adcf0a14be7cb729abab8156ecd962c5)
* limit some flags to clang++ [view commit](http://github.com/mapbox/variant/commit/904dcaee6d0d872eae52578e38199577418f9a32)
* Add -pthread [view commit](http://github.com/mapbox/variant/commit/b433986199b7dfbe59fa498eb80791a49c625170)
* upgrade libstdc++ for coverage build [view commit](http://github.com/mapbox/variant/commit/7b409402c3cf4a0260aa36ee768ee474aa3683c1)
* drop -Wstack-protector which gives unhelpful warnings [view commit](http://github.com/mapbox/variant/commit/c8ec829ffb4498a0aea8ffa9b62ba4932cdefbdf)
* disable -Wparentheses for older gcc [view commit](http://github.com/mapbox/variant/commit/a80beaafc20c2c015ace5fb1e4c99f6de8c24d75)
* Merge pull request #133 from mapbox/Werror [view commit](http://github.com/mapbox/variant/commit/a9707c3de095c715f84a1855684a3dc8e37a594a)
* remove useless and/or dubious compiler flags [view commit](http://github.com/mapbox/variant/commit/5141d8d21a5b648e9fef879bfc12b29ffac7288d)
* Merge pull request #134 from lightmare/warnings [view commit](http://github.com/mapbox/variant/commit/18a8055fef0e14110c313ca358f0f7c88290bed0)
* osx: test that will support both latest (10.12) and oldest with c++11 support: 10.7 [view commit](http://github.com/mapbox/variant/commit/4923eb527c129060ba970d622d639ad2ada42497)
* fix gyp build [view commit](http://github.com/mapbox/variant/commit/5baa948fa73313091bc082b9f3d17c5b5f600cac)
* upgrade to llvm 3.9.1 [view commit](http://github.com/mapbox/variant/commit/f5fb4661ebf1ecd0167bce50b00a8339604395b0)
* upgrade mason [view commit](http://github.com/mapbox/variant/commit/61f8acea1b09de639b46c8af0c5aae29f51dd05c)
* Merge pull request #135 from mapbox/llvm-3.9.1 [view commit](http://github.com/mapbox/variant/commit/05b7612aa86c28f95d39ba786c7b611e811e4bf8)
* Trivial missing comma in README example code [view commit](http://github.com/mapbox/variant/commit/d2588a8f1d6b5d480d228e6d8a906ce634bdea9a)
## 1.1.4
Released: December 21, 2016
(02bd1ac4c07e6db9fe0f01267853e43b41637b74)
* Provides Convenient Lambda Overload Visitor Interface, resolves #113. [view commit](http://github.com/mapbox/variant/commit/d09188640b6d5a637f391108f849a962d02dbb40)
* Removes ::type Usage [view commit](http://github.com/mapbox/variant/commit/2275a61974aaf117fa8d08c08d640ffd05935db8)
* Adds C++14 SFINAE Test [view commit](http://github.com/mapbox/variant/commit/4d462f27b2d852f66a3769e5983691c0f9233c9e)
* Merge branch 'daniel-j-h-lambda-visitor' [view commit](http://github.com/mapbox/variant/commit/9a115c5eb3c09509c70a57b25b283b6e1cbba919)
* Makes variant<Ts...> hashable iff Ts... are hashable, closes #125 [view commit](http://github.com/mapbox/variant/commit/97d0379f0afc87cd74a10be56fbccfa04785f568)
* Implements Pattern Matching for Sum Types via `.match` Member Function. [view commit](http://github.com/mapbox/variant/commit/720c23736bb318937d0f53a413a617ff05040b73)
* Adds Documentation for Readme, resolves #98 [view commit](http://github.com/mapbox/variant/commit/d0266436b18ea3b1f15c8a244985b57a0a2b3770)
* Merge pull request #126 from daniel-j-h/hashable [view commit](http://github.com/mapbox/variant/commit/3c17c37aea0d7e3d9e860b746d54160ec820e6a2)
* Merge pull request #128 from daniel-j-h/match [view commit](http://github.com/mapbox/variant/commit/ed84def128ed99a4b3b1ebcde278be7f761e782e)
* Merge pull request #129 from daniel-j-h/docs [view commit](http://github.com/mapbox/variant/commit/02bd1ac4c07e6db9fe0f01267853e43b41637b74)
## 1.1.3
Released: October 24, 2016
(a5a79a594f39d705a7ef969f54a0743516f0bc6d)
* use C++17 disjunction for no-references and one-convertible tests [view commit](http://github.com/mapbox/variant/commit/2c7ddecdb7ec3b1c1a6bc1797528375e513b7ab0)
* Merge pull request #116 from lightmare/disjunction [view commit](http://github.com/mapbox/variant/commit/8e2f6964157885f1655c1673d65f3aea9b90fe18)
* Update README [view commit](http://github.com/mapbox/variant/commit/aaddee9270e3956cee98cdd7d04aea848d69f5f0)
* expose `using types = std::tuple<Types...>;` - useful for adapting variant to `boost::spirit` (QI,Karma,X3) [view commit](http://github.com/mapbox/variant/commit/e5818212a8f7ef89df0aa76d5244eca78b8dbb8d)
* add `struct adapted_variant_tag;` [view commit](http://github.com/mapbox/variant/commit/173a7457952d0f24e2c55d5eb3ea785ad41639fb)
* Merge pull request #120 from mapbox/types [view commit](http://github.com/mapbox/variant/commit/84a426a31ad3b63c4b8f8d189841e19af48cda40)
* nicer stderr [view commit](http://github.com/mapbox/variant/commit/9b46167f5c42a19a3b66cb92eb60418486b4e424)
* Fix #122 by adding an extra compile check in universal ctor (via @lightmare) + test case [view commit](http://github.com/mapbox/variant/commit/a5a79a594f39d705a7ef969f54a0743516f0bc6d)
## 1.1.2
Released: July 26, 2016
(388376ac9f0102feba2d2122873b08e15a66a879)
* Re-implement type matching logic to reject ambigious conversions [view commit](http://github.com/mapbox/variant/commit/71ac8fdf96e547dca34fe58c5cd8d1dce2ef0dac)
* update tests [view commit](http://github.com/mapbox/variant/commit/8be6a2aa8f85e1455198eff31a577a1fb95e1d46)
* comment out code [view commit](http://github.com/mapbox/variant/commit/075d9636fdfe563b535fa3ba087409f940c018e4)
* Merge pull request #114 from mapbox/strict-conversions [view commit](http://github.com/mapbox/variant/commit/388376ac9f0102feba2d2122873b08e15a66a879)
## 1.1.1
Released: July 18, 2016
(c511b2f34d966c09e02a1b833db33a9a1f9b2196)
## 1.1.0
Released: February 11, 2016
(5aab5df0dc899b484c04ce9c649645787ee0bc5c)
* remove erroneous `;` ref #96 [view commit](http://github.com/mapbox/variant/commit/3f025adbf599d8dd9bfca02d45b37e49a2cae841)
* fix coverage to avoid warning: unit.gcno:version '402*', prefer '406*' [view commit](http://github.com/mapbox/variant/commit/b0ee4729bfc9ea649abe40f279de384df75b79d1)
* fix clang 3.8 compile, try 3.9 [view commit](http://github.com/mapbox/variant/commit/f034d5571de987d14b404dba94e7269ac41fa583)
* remove invalid option for llvm-cov [view commit](http://github.com/mapbox/variant/commit/5f6ed7149d737edf9f1f019beb54cbe5289c474c)
* run coverage with clang 3.5 - fix clang 3.8 build [view commit](http://github.com/mapbox/variant/commit/82bb901b6cc0de8c238a07292163dc7c28a26ce4)
* issue warning `-Wweak-vtables` so this issue is not forgotten (https://github.com/mapbox/variant/issues/95) [view commit](http://github.com/mapbox/variant/commit/35ca16c74f5712afb4f042f45ea64078fa0b630e)
* move headers into include/mapbox folder - closes #99 [view commit](http://github.com/mapbox/variant/commit/f00b24bf65e8af7fddc56ac4a3abe67ed974b0a5)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/13c631a6297d9abc9677c1afc1a3907fec7c16b4)
* Add include directory [view commit](http://github.com/mapbox/variant/commit/7e4a01189bb4050524954b2a88c82de7cb82ea4a)
* Merge branch 'master' into include [view commit](http://github.com/mapbox/variant/commit/9bd902536f533305186aaf70edb2f0b9713f6b6b)
* fix typo [view commit](http://github.com/mapbox/variant/commit/a606e90243dcf145cf06d46e8e30c447f85af178)
* ammend include dir [view commit](http://github.com/mapbox/variant/commit/343831611e60e324e311d67f05da953e357df0a1)
* update remaining `<variant.hpp>` to `<mapbox/variant.hpp>` [view commit](http://github.com/mapbox/variant/commit/bfe0f19dd14dedad9c0a6f1e211e81bd1233564e)
* fix compilation [view commit](http://github.com/mapbox/variant/commit/390229a59703d2467347d62f3e134e67ea6835cc)
* Merge pull request #101 from mapbox/include [view commit](http://github.com/mapbox/variant/commit/1bc46e525a9dec71af28f822e5fc031c1352ad2e)
* Remove Xcode 6 from CI matrix [view commit](http://github.com/mapbox/variant/commit/9b2fc858ccd84509fd7164a4847e7dc95e58d5a5)
* Install boost with mason; eliminate boost::timer dependency [view commit](http://github.com/mapbox/variant/commit/04dc3a46b02d6b8714d00280bb85c88716727862)
* `is<T>()` - add specialisation for recursive_wrapper<T> + update tests (ref #102) [view commit](http://github.com/mapbox/variant/commit/c6ae1ea0acf8c4392a806ad3abd5b11eb3b8a8ce)
* remove expected error string - current implementation emits compiler specific error message e.g [view commit](http://github.com/mapbox/variant/commit/4368d75292ae5149034b59b483fc3f8b3956a839)
* Jamroot - add missing include directory ./test/include for auto_cpu_timer.hpp [view commit](http://github.com/mapbox/variant/commit/7f7470fee6a42c3c68f1fa359a28cf762df385c3)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/8bdad6b6d73844ef8437f004654c0745f0cec96a)
* Fix building with GCC (g++-5.2.0) on OS X (Darwin) (ref #108) [view commit](http://github.com/mapbox/variant/commit/55579f03fba747500b3a105ae73a7dfe6059cfc1)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/33e27ec4c7cc5e1669f2181d13eacdfff15dfb61)
* Merge pull request #109 from mapbox/darwin-build-flags [view commit](http://github.com/mapbox/variant/commit/2f8a4a381f2ad8f9c2d3d068a757a3e0e9994495)
* Add get_unchecked<T>() to enable use with exceptions disabled [view commit](http://github.com/mapbox/variant/commit/434dab048d52e4141146bb95fdabdf7aa62e799b)
* remove unused internal metafunctions [view commit](http://github.com/mapbox/variant/commit/48d60445cca1d71fbebb6456b5d45a18bb9cb3b8)
* add static which<T>() function to get a contained types' which value [view commit](http://github.com/mapbox/variant/commit/74ce146d9b96081965d5fcdf53feefab6199468c)
* Merge branch 'master' into 111-which-constexpr [view commit](http://github.com/mapbox/variant/commit/dca3d967c165de1d0fb3bb5e1c2d6b4bcd76782f)
* Merge branch '111-which-constexpr' [view commit](http://github.com/mapbox/variant/commit/bb8c2d20317191f5228341a87b0c362c4d15be5b)
* variant - yield return type of mapbox::util::get<T> automatically and make interface consistent (addresses #82) [view commit](http://github.com/mapbox/variant/commit/adf0e02bceb74339b8ccc3e9e3f316917cb3cc22)
* uncomment tests ref #82 [view commit](http://github.com/mapbox/variant/commit/37acc5a7caef10d2f52dbdcee71be53b79dda027)
* Merge pull request #110 from mapbox/110-get_unchecked [view commit](http://github.com/mapbox/variant/commit/20e44accb1edf84d944d44f91ed7401198368aae)
* c++ apply formatting [view commit](http://github.com/mapbox/variant/commit/372d7c88fe796a138d0e578328914ac80e5a949a)
* use local HAS_EXCEPTIONS #define (__EXCEPTIONS is g++/clang specific macro) [view commit](http://github.com/mapbox/variant/commit/eedafd31f9fdbaffcb605d8d34a3a3443a4f7a2d)
* update .mason pkgs [view commit](http://github.com/mapbox/variant/commit/b5728ad76e1402c130a9330aa44b6f4b655b13b4)
* fix value_traits to be able to match T, T& and T const& to the direct type stored in variant (ref #112) [view commit](http://github.com/mapbox/variant/commit/b3a002d185afac295486e2ebd6b84c78a2267ba0)
* add test for b3a002d185afac295486e2ebd6b84c78a2267ba0 (ref #112) [view commit](http://github.com/mapbox/variant/commit/c511b2f34d966c09e02a1b833db33a9a1f9b2196)
## 1.0
Released: April 1, 2015
(bf485dfb59aef26f3ef2183d7c8c1111ad97062b)
* Initial commit [view commit](http://github.com/mapbox/variant/commit/9b82890ea11742eafd686f44b8cc7075029dbd7b)
* initial import [view commit](http://github.com/mapbox/variant/commit/bb95645b86a8fe427df9af799ecd139e4fab38ef)
* remove unused boost::static_visitor [view commit](http://github.com/mapbox/variant/commit/2dbc79fdd28c2ad9623c6516069ae616af11cdc5)
* call reserve in boost::variant test and change order [view commit](http://github.com/mapbox/variant/commit/9c1d245388396ac289ccee238b549e48a7916f9e)
* add readme and makefile [view commit](http://github.com/mapbox/variant/commit/5afa5b2e1756dfb0e332f3e11bffdfb33cd31f75)
* makefile fixups [view commit](http://github.com/mapbox/variant/commit/c627c07afc972b3f1bab3ca219416d6e918cd39b)
* turn on more aggressive warnings and fix them where appropriate [view commit](http://github.com/mapbox/variant/commit/20ee8ffe2889f9e0f4974ba2aba028ccd3ce347a)
* -Wsign-compare [view commit](http://github.com/mapbox/variant/commit/12ef94a8c0edb897858b82d0064093e251ac4024)
* remove unneeded headers [view commit](http://github.com/mapbox/variant/commit/eeba005f2f2e287f23661e9dd555e57e0365d22c)
* include <stdexcept> [view commit](http://github.com/mapbox/variant/commit/a7b562eb0ef665b57e3a29a2ff83721bc3f66a03)
* include headers for new/size_t/move [view commit](http://github.com/mapbox/variant/commit/c3963a96aab7d3d2e380652e4268c5d729778a59)
* add sizes target to check object sizes [view commit](http://github.com/mapbox/variant/commit/a1685041726cba13aa9fb728ec4963f3e7872200)
* add tests [view commit](http://github.com/mapbox/variant/commit/df1d00cc50d3b5a1cce203305d52f536f622663c)
* interleave test runs to ensure first run penalty does not murky the results [view commit](http://github.com/mapbox/variant/commit/969a346db6ab41adb66f7b3cbbcc92cd15c3b339)
* add to gitignore [view commit](http://github.com/mapbox/variant/commit/e98fc0736064d3131a25e899420b41276e801a45)
* fix build on ubuntu/g++-4.8 [view commit](http://github.com/mapbox/variant/commit/b8ab4b8c6beb2d0d4bb2afc9fda901c83588d153)
* debug/release builds + profiling [view commit](http://github.com/mapbox/variant/commit/a25c3597deb4d889085bc9492d2cf4f6df847a5a)
* pass release flags to make sizes [view commit](http://github.com/mapbox/variant/commit/23f112ae5e551a731939e8220a16a6c7a29d844b)
* force inlining to reduce final object size (yes **reduce**, with clang++ at least) [view commit](http://github.com/mapbox/variant/commit/c65aa114402e8f7b1d44062ff973f7c807741d06)
* optimization: avoid overhead of function call for invalid type check [view commit](http://github.com/mapbox/variant/commit/cebd6a31e54d84811cccab62991d142aa8aacbad)
* test threaded [view commit](http://github.com/mapbox/variant/commit/5a84ea2f40ccd2cadbc1091fae05b37b1d69c85c)
* 10 threads [view commit](http://github.com/mapbox/variant/commit/c06ebf15268925ef5e0f3ce763db13fd0c27ef2b)
* use perfect forwarding instead of move [view commit](http://github.com/mapbox/variant/commit/cd81aed73c9f1176e26090abc60a9d2467f5d5bf)
* const as const can. also reimplementation of operator= to allow for ADL in swap [view commit](http://github.com/mapbox/variant/commit/33603114129c387c5938287f1839f852a8f3a5f2)
* Merge pull request #1 from artemp/consts_and_fwds [view commit](http://github.com/mapbox/variant/commit/dff07459931e6d76b4eea6092041cbf247e01f64)
* implement comparison operators (==,<) implement operator<< [view commit](http://github.com/mapbox/variant/commit/cb9374b1ebb4c2da42e06af71ca738e9316b0582)
* make THREADS=4 ( we want to test variant not an operating system, better still make it config (TODO)) add simple test for operator== and operator<< ( define VARIANT_LOGICAL_TESTS to enable) [view commit](http://github.com/mapbox/variant/commit/68aa114c5d06a979b8fb31f0cdd2647833544cb1)
* c++ : better names (#2) [view commit](http://github.com/mapbox/variant/commit/48dd83308ebb5ab21c295499948d27d42801b306)
* c++ : better names (#2) [view commit](http://github.com/mapbox/variant/commit/46f40479fd02170b9d4bf48655a6a6a7845d77cc)
* Merge branch 'master' of github.com:artemp/variant [view commit](http://github.com/mapbox/variant/commit/41d5626bee25a4edd36c2e2d05bde46751417baa)
* Added const [view commit](http://github.com/mapbox/variant/commit/9d7afc7362e095acf032b5a3d2057d960157ffcb)
* Fixed var names [view commit](http://github.com/mapbox/variant/commit/7423b70b907b640b477c9675d79b43abb6bf21ed)
* changing const keyword position to 'T const &' [view commit](http://github.com/mapbox/variant/commit/f6677d163a1c1df6d960baa7d0d7983edac95cc3)
* Add -march=native to release build flags, implies -mtune=.. [view commit](http://github.com/mapbox/variant/commit/3ff69626f348da3f6827fc1573e014400d5f6813)
* Merge pull request #7 from artemp/const_correctness_part2 [view commit](http://github.com/mapbox/variant/commit/f8ff1da09fdb3902b39cb6893fda048b2760da68)
* Merge pull request #8 from artemp/architecture-optimizations [view commit](http://github.com/mapbox/variant/commit/4b325da289df3e91bc32d71d4adceb28d3cf8215)
* fix remaining names [view commit](http://github.com/mapbox/variant/commit/2de14db6a431689e07630f42ee18a30101ed11b3)
* add -march=native to Jamroot [view commit](http://github.com/mapbox/variant/commit/8c03239ed115ed51d181ea52a40f0e9e8ec73f42)
* more name fixing ref #2 [view commit](http://github.com/mapbox/variant/commit/f27bd4c7f514f9f646eb0766cfd8f4b7e8f0ed33)
* structs dont have private members [view commit](http://github.com/mapbox/variant/commit/3d0072d34600bbf2fc21bee3db65770cf6796402)
* add pgo option to Makefile [view commit](http://github.com/mapbox/variant/commit/7f4f85e93d09630dd78ba5eb113bb03fb9804979)
* Merge pull request #9 from artemp/classes_and_structs [view commit](http://github.com/mapbox/variant/commit/21ced9474d93a96bb5c7cd527efa5e0ba742e84a)
* Merge pull request #10 from artemp/profile_guided_optimization [view commit](http://github.com/mapbox/variant/commit/0fc8f6b3911b6b6c0dbe72d5c440c7c094add899)
* + implement binary visitation [view commit](http://github.com/mapbox/variant/commit/943b24689b918f13ee1bdeb43111cbdf49139797)
* more realistic test [view commit](http://github.com/mapbox/variant/commit/e481fdb58ac2fec43a18ba119715f539ba000007)
* fix return types [view commit](http://github.com/mapbox/variant/commit/b41b4f69c21e552198310ebaf17c4776e2b4dc1f)
* Return uint64_t [view commit](http://github.com/mapbox/variant/commit/de6db67da287a8f80b956c85a5a6bff2af6cd52f)
* recursive_wrapper init impl [view commit](http://github.com/mapbox/variant/commit/f1c12747d921763288435beb53fbf23eafb6100d)
* Merge branch 'master' of github.com:artemp/variant [view commit](http://github.com/mapbox/variant/commit/49274509129f7f5957cc785b82771ad772fb2478)
* + add static_visitor requirement to ease return_type deduction [view commit](http://github.com/mapbox/variant/commit/80d999a3471b5647a17c14217ef237f8e9f82543)
* fix binary visitor test [view commit](http://github.com/mapbox/variant/commit/87207d76fb81f87b0bbde00c1ed44ec6043103fa)
* use static_visitor as a base class for all visitors [view commit](http://github.com/mapbox/variant/commit/48f78bcd767b99575a5af4aeb0490342e8a2b7a9)
* recursive_wrapper test (work-in-progress) [view commit](http://github.com/mapbox/variant/commit/05af9c4f21eefc91c713bc1e34e0e04b0556519a)
* include recursive_wrapper [view commit](http://github.com/mapbox/variant/commit/cbd9e2cf91e58baebd79ce336ba4b20148f303af)
* update test (FIXME - inteface is very clunky atm and needs more work) [view commit](http://github.com/mapbox/variant/commit/d2cda9a88684d2e7fad3d3527e53f7c64c84378e)
* unwrap recursive_wrapper [view commit](http://github.com/mapbox/variant/commit/bc65cb8d7be23806dc63c2adf03fc8e9b5557f66)
* + const [view commit](http://github.com/mapbox/variant/commit/6e9a10f43eab476d68399d6dcc51a2464cd2f0b8)
* recursive variant test using std::unique_ptr move semantics [view commit](http://github.com/mapbox/variant/commit/5ebf86772daade4490652218e3437d5d0ca7d1de)
* add missing test file [view commit](http://github.com/mapbox/variant/commit/b4abfa58efb676aa86a3dd2dfee04f7e95aee7fd)
* update recursive_wrapper and unique_ptr tests to accept <num-iter> arg [view commit](http://github.com/mapbox/variant/commit/edcb444afc193784cb6237616d68973b36e7920e)
* make test -> make bench [view commit](http://github.com/mapbox/variant/commit/fc80297390285e83394983201473d01edfa17d4c)
* fix compile of test/variant [view commit](http://github.com/mapbox/variant/commit/da417016e6af968cdcea1b2ec9f2023d3ee77cad)
* recursive_wrapper.hpp depends on boost checked delete for the moment [view commit](http://github.com/mapbox/variant/commit/a8d019d470e11eb3a569581ce140397bb6f6e31d)
* shuffle code, all build targets in out/ directory [view commit](http://github.com/mapbox/variant/commit/8e5abd0f14e298b9cc93f7428c2cd21ce732fad9)
* all tests in ./test directory [view commit](http://github.com/mapbox/variant/commit/dadea1f2a7d9c08e1a5979cc5bb824779fb73380)
* add travis [view commit](http://github.com/mapbox/variant/commit/7e775d10774261b5461474013b840fdd899db023)
* fix travis targets [view commit](http://github.com/mapbox/variant/commit/c6bd4f8131f6a58d6d6dfaf3017c8793a0da9819)
* travis: upgrade to gcc-4.8 for c++11 support [view commit](http://github.com/mapbox/variant/commit/84fdc9e2c0701980c083ff3cb8701f3076f10fa6)
* fix a few -Wsign-compare warnings [view commit](http://github.com/mapbox/variant/commit/d3d0704c59dba67f925b707d6c72babadd607ce9)
* fix -Wshadow warning [view commit](http://github.com/mapbox/variant/commit/e19d0e5aca3b4e4a76e29e34352d634b7c495202)
* fix linux compile of binary_visitor_test.cpp [view commit](http://github.com/mapbox/variant/commit/d8df077f29428c55688910d5f96e79b6d351d5e1)
* qualify c++11 int types [view commit](http://github.com/mapbox/variant/commit/62e7165925bfce3e4c11a2fce1cad8d486825613)
* fix #12 [view commit](http://github.com/mapbox/variant/commit/c0593af2c3066d13f30bf15241da313539539f18)
* test with both gcc 4.7 and 4.8 [view commit](http://github.com/mapbox/variant/commit/916719bb38cec2e9f4ff7c3d2ef480734badbb7d)
* Add BSD license [view commit](http://github.com/mapbox/variant/commit/cf7f7bef518d7dd67d74e84bdbaf40a6c5826114)
* add unit tests [view commit](http://github.com/mapbox/variant/commit/0ef558f9607844fa88b1857e6ff993121dd84d71)
* port logical tests to test/unit.cpp - refs #15 [view commit](http://github.com/mapbox/variant/commit/7109df9c4f423b846839240d720de4a89be101c8)
* version, starting at 0.1.0 [view commit](http://github.com/mapbox/variant/commit/e5c89779e59bc22571ce5beb27a823b94b2be786)
* try building on windows with gyp [view commit](http://github.com/mapbox/variant/commit/b97876a2e5ddaf8931cecd36b5a649fb3e1eb420)
* call gyp_main.py [view commit](http://github.com/mapbox/variant/commit/24cddfbc76c713046b130158c72231bd827d4a23)
* be explicit about config and platform [view commit](http://github.com/mapbox/variant/commit/bc80b31f8c4afd469f65046cfc3fe18bba95fbd3)
* also test building with gyp on travis [view commit](http://github.com/mapbox/variant/commit/51eda4f439c24223a964fe25d077ff1efa27dce0)
* try 'any cpu' [view commit](http://github.com/mapbox/variant/commit/41056fa781bf3c6a79182db338595b44d6370c25)
* put msbuild on path [view commit](http://github.com/mapbox/variant/commit/948a6ccb89ae2b4a3682805519b585bf573763a9)
* appveyor: try building 32 bit [view commit](http://github.com/mapbox/variant/commit/1b89ab841021d28da193e3b1fab27269651bdc17)
* Update README.md [view commit](http://github.com/mapbox/variant/commit/011b5125a4bb139f794bb37080bd33cae6519f7c)
* + it breaks builds for me - I have 'using clang ..' in $(boost-dir)/tools/build/v2/user-config.jam where it should be. [view commit](http://github.com/mapbox/variant/commit/1b2fc49bbc7e76bbaf2c64ea44cb3f287d5948a5)
* ```apply_visitor``` interface not-compatible with boost::apply_visitor (by changing args order) wasn't smart [view commit](http://github.com/mapbox/variant/commit/67ac560672e5ea7bf99a4a823b5259ccd6d1bd5d)
* fix syntax [view commit](http://github.com/mapbox/variant/commit/002ccdcde4aacfcc6b67ad4981c05402514c09f1)
* windows support [view commit](http://github.com/mapbox/variant/commit/64f8fb4473f3ef6f7117dc02f02a20645e415b72)
* update readme [view commit](http://github.com/mapbox/variant/commit/20f26eceebef717a0ee759b42bfe939a95874807)
* appeveyor: try building for just x86 [view commit](http://github.com/mapbox/variant/commit/b3f8117d05071981106b7d1fe15405a318d3c1df)
* fix setting of msbuild_toolset for c++11 support [view commit](http://github.com/mapbox/variant/commit/d0603d41a8597089c0c1cd099ebb8bcf5e1414d3)
* Add vcbuild.bat [view commit](http://github.com/mapbox/variant/commit/bb12b87574fcdaa7bdca6c1529d442eab2d52b97)
* remove sizeof checks since they are implementation depedenent [view commit](http://github.com/mapbox/variant/commit/f5af06c20329a0c762af9420a3ae2e3d22c02c91)
* comment failing test on windows [view commit](http://github.com/mapbox/variant/commit/7d4dc68667659e7585d28f743509956e92759255)
* appveyor: re-enable matrix [view commit](http://github.com/mapbox/variant/commit/6dbc0546bdab9e8dc291eb08d2e6dce13a0dcfe8)
* add <utility> to be include order agnostic [view commit](http://github.com/mapbox/variant/commit/9be8c519c67ef2ec8d3b5a7b736f0a8b870b43ed)
* Merge pull request #16 from DennisOSRM/master [view commit](http://github.com/mapbox/variant/commit/b27a14e98d9eadf2aabd628a602f9e4a5fcb0a5f)
* move detail tests + add initial comments (@artemp, please review) [view commit](http://github.com/mapbox/variant/commit/ea25e84aeec16588857ac83c1241d34a5df4adac)
* fix typo in code comment [skip ci] [view commit](http://github.com/mapbox/variant/commit/b773421f5868315eccd504204f32ee8c02e78dc6)
* rename internal id to index, add tests [view commit](http://github.com/mapbox/variant/commit/390e2315b97bbc71aa575d98bacc1ed760d0aa4a)
* Merge pull request #18 from mapbox/type_index [view commit](http://github.com/mapbox/variant/commit/046296a95c9d34224c23c843bc8bd6d502f81b47)
* modify tests slightly to output num_iter ((3+2)-4) [view commit](http://github.com/mapbox/variant/commit/602eceb753751ae30cd5ca7a25d3337179ba6b5e)
* boost is uneeded for unit.cpp tests [view commit](http://github.com/mapbox/variant/commit/e1de3d78e8827d5b6819cc91b430429a46093c95)
* enable ctor's for valid types at compile time [view commit](http://github.com/mapbox/variant/commit/31e3fd96fe4f86d9ac5ac53d6e3e07605307eb5c)
* [travis] multi-os [view commit](http://github.com/mapbox/variant/commit/2f1e36d25f152c31cc3b2673946a8670dd189e74)
* fix path to boost/variant.hpp on linux [view commit](http://github.com/mapbox/variant/commit/b31579c99042d36672fa9eefb09bcdb01e1bcc0a)
* move variant and friends into mapbox namespace for easy integration [view commit](http://github.com/mapbox/variant/commit/df55ab6ef48d1a28c58e409d71b3ee4b416cdf31)
* fix namespace [view commit](http://github.com/mapbox/variant/commit/397ed9c90bc55bbf2f3331f43a707789869d064a)
* inline accessors/setters [view commit](http://github.com/mapbox/variant/commit/2ebabd9b6cb1b95605b01708899498ac70b84201)
* default ctor : initialise with default contructed first type in parameters pack [view commit](http://github.com/mapbox/variant/commit/4d038f1462698c0977e14eacfd9abeb8da95c852)
* add default ctor test [view commit](http://github.com/mapbox/variant/commit/d7fa62b52f771f0d194441b5889409e792eff740)
* c++11 : use type aliases instead of typedefs [view commit](http://github.com/mapbox/variant/commit/03eb4c7d287b72eb43d2b6456ef38437c8c0ac34)
* converting operator= [view commit](http://github.com/mapbox/variant/commit/0eed7c3c1477e0673d379336b0745606d2780d8f)
* avoid wrapped object copying [view commit](http://github.com/mapbox/variant/commit/f7648ba392aea548fe0d583ceee2048ad57e2f54)
* fix move ctor + housekeeping [view commit](http://github.com/mapbox/variant/commit/6aee8c4a7543e0d38f64a07d67aaf394bea704d9)
* add <string> [view commit](http://github.com/mapbox/variant/commit/82cc6e2335b377b5e61e9a3bc974e619658ab515)
* remove unused header [view commit](http://github.com/mapbox/variant/commit/74425f135a6b7cdd49d86d2dd84cf9bdfe9154c2)
* uncomment to test single threaded [view commit](http://github.com/mapbox/variant/commit/7296d18458e2dbfc7ddb39f0fe5b96962c264dc6)
* fix bug : assign correct index (in reverse order of args) e.g first type is sizeof...(Types) - 1 [view commit](http://github.com/mapbox/variant/commit/7eb748eb65729c2d91a7c4f16e5bd56eb3038bdd)
* fix default ctor unit test [view commit](http://github.com/mapbox/variant/commit/03af9e421b36e17a9b873cb24347f6bad7c3dc6d)
* [gyp] fix typo in Windows release targets [view commit](http://github.com/mapbox/variant/commit/2d8ca78704f69c6498a0e689222588275c8f33aa)
* add non-const visitor interface (#22) [view commit](http://github.com/mapbox/variant/commit/54d07c9d336c989fe3c1231bbb7f6465ebc68da2)
* add unary_visitor test [view commit](http://github.com/mapbox/variant/commit/3b31c34368613c4cd101e6f7ee9677c2c7b6b75e)
* support implicit type convertions [view commit](http://github.com/mapbox/variant/commit/724a40baec3ded142c631b66521502840d8d183f)
* update to use recursive_wrapper<T> -> T conversions [view commit](http://github.com/mapbox/variant/commit/7e609812f15cbf41fab978fd3222c6029a5b67eb)
* unit test : update to use latest variant impl [view commit](http://github.com/mapbox/variant/commit/d1392fa431b5b5dac99cdb8b937ec05e13d98847)
* Mapbox name without the inner uppercase B. [view commit](http://github.com/mapbox/variant/commit/4e11d41723af714895c90cb8b9798527c946b2b4)
* Fix typo in comment. [view commit](http://github.com/mapbox/variant/commit/01509c76c30bea7a6bfffd0e59f9bbdbae8f1026)
* Formatting fixes. [view commit](http://github.com/mapbox/variant/commit/cfd7d991b23b2ecc659d18f22a2f78a05074450c)
* Use formatting "TYPE const&". [view commit](http://github.com/mapbox/variant/commit/9253ffdda65bd41ed21f9328a20a335fa0f5d582)
* Remove superfluous and inconsistent whitespace. [view commit](http://github.com/mapbox/variant/commit/d855ba8672fc5f439594325663899564f0632c94)
* Add comments for closing namespaces. [view commit](http://github.com/mapbox/variant/commit/3c2d662abb352bd429777251ddc613e751e49123)
* Merge branch 'joto-master' [view commit](http://github.com/mapbox/variant/commit/49e9f351a7a8d5615f8fb5ae2d4840042fc95bcc)
* Fix typos, whitespace and test tags. [view commit](http://github.com/mapbox/variant/commit/a12326984f323d10648115d94ace0b510d097b06)
* Add tests for implicit conversion and exceptions for wrong types. [view commit](http://github.com/mapbox/variant/commit/12c70938b00215ce86e48657d60a650dbfd8966e)
* Add test for printer visitor. [view commit](http://github.com/mapbox/variant/commit/fd470a6fde0941407a74c3d544c009eac0579e4f)
* Add test case for issue #25. [view commit](http://github.com/mapbox/variant/commit/74f1c5d9b02788fb9524ae674d43fdf07671d9cc)
* fix appveyor link in readme [view commit](http://github.com/mapbox/variant/commit/d49f82efb7689b8bc67be30633dd7f41b54f2e5a)
* Remove the need for the static_visitor class. [view commit](http://github.com/mapbox/variant/commit/e9283622a33231500c8cc3d1f27358d431c1e8a2)
* msvs: also define _DEBUG for debug builds [view commit](http://github.com/mapbox/variant/commit/c4bb359f883b568a88d5be8b3e4ce5c45626d71f)
* [appveyor] more debug flags [view commit](http://github.com/mapbox/variant/commit/b852c8d386e59a145a6b684d036ee7e327d0efe2)
* [appveyor][gyp] correct msvs_settings usage [view commit](http://github.com/mapbox/variant/commit/1f707864e37c305779e3398006b20e2ee5f14866)
* customize release builds [view commit](http://github.com/mapbox/variant/commit/4661a3c06b3738c7564c18474577d4faece6613a)
* [gyp][windows] add exception handling/rtti [view commit](http://github.com/mapbox/variant/commit/02556c9c317834ad3f05aa88dacc072ad9a63c99)
* use numeric values in valid range to avoid overflowing [view commit](http://github.com/mapbox/variant/commit/854c5a7a115d92b67698f3654d915edd483456b9)
* Removed wrong comments. [view commit](http://github.com/mapbox/variant/commit/8b6c0b34b76144d697ede0f386f1ea2f9c6ae2d1)
* Removed test case. [view commit](http://github.com/mapbox/variant/commit/08a7e04e3cf3ebd54e289201b1bd3d85225248ee)
* allow explicit un-initilised variant ctor [view commit](http://github.com/mapbox/variant/commit/d99139d4dee3ae4fa2b7465000d08fc5f5907e82)
* add boost::variant compatible accessors [view commit](http://github.com/mapbox/variant/commit/2afd3415cc28b8b7184e2750ac90e739c078b335)
* more verbose output to test script [view commit](http://github.com/mapbox/variant/commit/0c8b6b736788718ed28a0676cdb0b390249d5540)
* variant : make operator<< stricter to avoid unexpected instantiations [view commit](http://github.com/mapbox/variant/commit/76027798360405d910f8af9d6ae873fa5905be13)
* Add details on advantages of Mapbox variant [view commit](http://github.com/mapbox/variant/commit/a5ee02b2aacb0109725c611beaafc27dce89c12d)
* remove unneeded header [view commit](http://github.com/mapbox/variant/commit/73da70737f0e55b2276173ca923eb91bd8ae4f32)
* less debug info in release mode [view commit](http://github.com/mapbox/variant/commit/607ed1344f8117000e03da0b8bfb9268a1f826ee)
* rough cut of an optional type [view commit](http://github.com/mapbox/variant/commit/9badbd0fa37863240cf678be61116003d345a20a)
* add operator* and a static assert against reference types [view commit](http://github.com/mapbox/variant/commit/1141292eeed4a95f3e54c85e98f9ded180f84f32)
* Merge pull request #30 from DennisOSRM/optional [view commit](http://github.com/mapbox/variant/commit/32f971794c643d11f5bf374caef44cee295cdf7d)
* remove some whitespace [view commit](http://github.com/mapbox/variant/commit/f4bcf3ff733acbd4a798f1e9a5f80d5422bc9b79)
* explicit operator bool() const noexcept [view commit](http://github.com/mapbox/variant/commit/c77d98b3e8d06714ed0b0c288cd9ad457f2708c4)
* rename none_t -> none_type, move to private member of optional [view commit](http://github.com/mapbox/variant/commit/43e2e9a943555c09ce6ffb9c825a64bff229a3a6)
* remove instantiation of none_type as per @kkaefer's suggestion [view commit](http://github.com/mapbox/variant/commit/7242396fb5468defba37afd03e7a633075fa51ce)
* remove none_type and its complicated typedef from detail namespace, add it as private member class to optional [view commit](http://github.com/mapbox/variant/commit/c5f720515ad21fe3913fc841ea427ebdd1fa4c68)
* guard against self-assignment [view commit](http://github.com/mapbox/variant/commit/10a039c78b58857f8793dae3b0359cf1d6fb11ef)
* add unit tests for optional type [view commit](http://github.com/mapbox/variant/commit/607c6332cb96261a43a16fa94aea5d034ae58aac)
* Merge pull request #31 from mapbox/optional [view commit](http://github.com/mapbox/variant/commit/4cdd805a04175248b221753a0974de15c8f5b397)
* reformat optional.hpp to be more legible and less linty [view commit](http://github.com/mapbox/variant/commit/54e1dfe7631207da3f6a2bbc895c5240592ea5ea)
* universal-references: template <typename T> variant(T && val) {} it turned out we don't need a separate converting copy ctor (fixes windows compiler) [view commit](http://github.com/mapbox/variant/commit/82df4ed9cd2a8335c7e50b913f827216604dab07)
* Merge pull request #32 from mapbox/universal-references [view commit](http://github.com/mapbox/variant/commit/804fb6f370a35eaea3e273ebfcb2f92ef7379e91)
* use std::forward<T> for perfect forwarding (via @DennisOSRM) [view commit](http://github.com/mapbox/variant/commit/eb995158362307cea98e36eb782dd4ae63593d0f)
* fix assignment of optionals, adds a unit test [view commit](http://github.com/mapbox/variant/commit/f69f317069523cb6994fa9d594240deeb537753c)
* Merge pull request #33 from mapbox/fix_assignment_operator [view commit](http://github.com/mapbox/variant/commit/c56af229af98b71ba8ef637f3237cab828f0ec14)
* readme improvements [view commit](http://github.com/mapbox/variant/commit/5b8972b6ebcd095f35b810c43639785235218bbd)
* Merge branch 'master' into result_of [view commit](http://github.com/mapbox/variant/commit/4900027d0f66a7c701e22c667e92ce7b7521a73c)
* cast lhs to rhs type to avoid signed/unsigned comparisons warnings [view commit](http://github.com/mapbox/variant/commit/17074a3de539256ccab3871033df33c9d387dcbf)
* attempting to fix travis [view commit](http://github.com/mapbox/variant/commit/4fb9bd65ac4a204f8721f9528df9c14907a151f9)
* Merge branch 'master' into result_of [view commit](http://github.com/mapbox/variant/commit/fbcc50b57e58460e0cd90a232673271eff72311c)
* make deriving from static_visitor and providing result_type an option [view commit](http://github.com/mapbox/variant/commit/76ab6d4aa54664d7f8849695896ca57f4984bed0)
* Merge branch 'result_of' [view commit](http://github.com/mapbox/variant/commit/3cc2d708e0552ba4ebce11d4d67f798813f15aa2)
* fix automatic return_type calculation - ref #35 [view commit](http://github.com/mapbox/variant/commit/00ab88117ed25f78cdca2faa00beea0061271e85)
* test either g++ or clang++ [view commit](http://github.com/mapbox/variant/commit/199b3eca054075319a1978f09bdd77f9ff42e681)
* try adding code coverage / coveralls upload [view commit](http://github.com/mapbox/variant/commit/11e65282e335ed4a50bf261d21b8194230787ed8)
* fix bash syntax [view commit](http://github.com/mapbox/variant/commit/2fbfcd33998992df4d77f329e7a75c864616d0ab)
* add recursive wrapper to coverage [view commit](http://github.com/mapbox/variant/commit/f87a1cf10d62814d3bf4e72ac260a92e483ffb25)
* move operator<< into separate header <variant_io.hpp> [view commit](http://github.com/mapbox/variant/commit/24dcab23c4f70e54838e4a32a228aba8045ae17b)
* add coverage report [view commit](http://github.com/mapbox/variant/commit/89f8a41a4da81c2a01d39f83cf52e61997ce76ba)
* clean up coverage files in test directory too [skip ci] [view commit](http://github.com/mapbox/variant/commit/7dfdfa271e43780aff640852a632e88443b6fe32)
* add get<T>() overloads for when T is stored in recursive_wrapper<T> also makes get<T>() a compile time error where T is not in Types... (ref #24) [view commit](http://github.com/mapbox/variant/commit/36f1e12f66570f2a1f04535dc0ac0485d48e2bbe)
* update unit test to match c64c74775a80474f2012c1a49ab2865e3666107a [view commit](http://github.com/mapbox/variant/commit/c117592337cc20c238d4ce9f9d8847aff0cd55ab)
* add which() method returning zero based index of stored T in Types... for boost::variant() compatibility [view commit](http://github.com/mapbox/variant/commit/3b02ca0e3ab1a36dd6ec9138e7f93eb3176ae5f7)
* add reference_wrapper test [view commit](http://github.com/mapbox/variant/commit/5a2d5c5f292ae2d6128d02e7ee2b3b3d72facfc2)
* remove boost variant header [view commit](http://github.com/mapbox/variant/commit/c53422fb2d4e44b7e276fcde65498b603f429a2f)
* add support for 'unwrapping' std::reference_wrapper<T> and accessing std::reference_wrapper<T>::type through get<T>() + update test [view commit](http://github.com/mapbox/variant/commit/587519521ae0d9a24f997ab2dff77f13309aa5d2)
* pass F (functor) by ref/const ref [view commit](http://github.com/mapbox/variant/commit/2e0ce4a86d0b9d0ff9855838349fb599b15a274a)
* pass by const ref in 'apply_const' [view commit](http://github.com/mapbox/variant/commit/a3014f54651b71e25d81fbeaf99f29d63c625703)
* Revert "pass by const ref in 'apply_const'" [view commit](http://github.com/mapbox/variant/commit/e031c53d0c876ecf2b9d4a6e0a5383bd4169df71)
* Revert "pass F (functor) by ref/const ref" [view commit](http://github.com/mapbox/variant/commit/bf485dfb59aef26f3ef2183d7c8c1111ad97062b)

View File

@ -1,78 +1,62 @@
# Unofficial and incomplete build file using Boost build system. # Unofficial and incomplete build file using Boost build system.
# You should use make unless you know what you are doing. # You should use make unless you know what you are doing.
local BOOST_DIR = "/usr/local" ; import os ;
local boost_dir = [ os.environ BOOST_DIR ] ;
if ! $(boost_dir)
{
boost_dir = "/usr/local" ;
}
#using clang : : ; #using clang : : ;
lib system : : <name>boost_system <search>$(BOOST_DIR)/lib ; local cxx_std = [ os.environ CXX_STD ] ;
lib timer : chrono : <name>boost_timer <search>$(BOOST_DIR)/lib ; if ! $(cxx_std)
lib chrono : system : <name>boost_chrono <search>$(BOOST_DIR)/lib ; {
cxx_std = c++11 ;
}
exe variant-test project mapbox_variant
: : requirements
test/bench_variant.cpp <cxxflags>-std=$(cxx_std)
.//system <include>$(boost_dir)/include
.//timer <include>include
.//chrono <include>test/include
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
#<define>SINGLE_THREADED
<variant>release:<cxxflags>"-march=native -Wweak-vtables"
;
exe binary-visitor-test
:
test/binary_visitor_test.cpp
.//system
.//timer
.//chrono
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native <variant>release:<cxxflags>-march=native
<threading>single:<define>SINGLE_THREADED
: default-build
<variant>release
<optimization>speed
<threading>single
; ;
exe recursive-wrapper-test rule exe-test ( name : reqs * : deps * )
: {
test/recursive_wrapper_test.cpp exe $(name)
.//system : test/$(name).cpp
.//timer : $(reqs)
.//chrono : $(deps)
: ;
<include>$(BOOST_DIR)/include explicit $(name) ;
<include>./include }
<include>./test/include
<variant>release:<cxxflags>-march=native exe-test bench_variant
: <variant>release:<cxxflags>-Wweak-vtables
; ;
exe unique-ptr-test exe-test binary_visitor_test ;
: exe-test recursive_wrapper_test ;
test/unique_ptr_test.cpp exe-test unique_ptr_test ;
.//system exe-test reference_wrapper_test ;
.//timer exe-test lambda_overload_test ;
.//chrono exe-test hashable_test ;
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native
;
install out
exe reference_wrapper_test : bench_variant
: binary_visitor_test
test/reference_wrapper_test.cpp unique_ptr_test
.//system reference_wrapper_test
.//timer lambda_overload_test
.//chrono hashable_test
:
<include>$(BOOST_DIR)/include
<include>./include
<include>./test/include
<variant>release:<cxxflags>-march=native
; ;

View File

@ -1,23 +1,53 @@
MASON = .mason/mason MASON = .mason/mason
BOOST_VERSION = boost 1.60.0 BOOST_VERSION = 1.62.0
CXX := $(CXX) CXX := $(CXX)
CXX_STD ?= c++11 CXX_STD ?= c++11
BOOST_FLAGS = `$(MASON) cflags $(BOOST_VERSION)` BOOST_ROOT = $(shell $(MASON) prefix boost $(BOOST_VERSION))
RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden BOOST_FLAGS = -isystem $(BOOST_ROOT)/include/
DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden -fvisibility=hidden
COMMON_FLAGS = -Wall -pedantic -Wextra -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -std=$(CXX_STD) DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions -fno-omit-frame-pointer -fPIE
WARNING_FLAGS = -Werror -Wall -Wextra -pedantic \
-Wformat=2 -Wsign-conversion -Wshadow -Wunused-parameter
COMMON_FLAGS = -std=$(CXX_STD)
COMMON_FLAGS += $(WARNING_FLAGS)
CXXFLAGS := $(CXXFLAGS) CXXFLAGS := $(CXXFLAGS)
LDFLAGS := $(LDFLAGS) LDFLAGS := $(LDFLAGS)
export BUILDTYPE ?= Release
OS := $(shell uname -s)
ifeq ($(OS), Linux)
EXTRA_FLAGS = -pthread
endif
ifeq ($(OS), Darwin)
OSX_OLDEST_SUPPORTED ?= 10.7
# we need to explicitly ask for libc++ otherwise the
# default will flip back to libstdc++ for mmacosx-version-min < 10.9
EXTRA_FLAGS = -stdlib=libc++ -mmacosx-version-min=$(OSX_OLDEST_SUPPORTED)
endif
ifeq ($(BUILDTYPE),Release)
FINAL_CXXFLAGS := $(COMMON_FLAGS) $(RELEASE_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS)
else
FINAL_CXXFLAGS := $(COMMON_FLAGS) $(DEBUG_FLAGS) $(CXXFLAGS) $(EXTRA_FLAGS)
endif
ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')') ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')')
all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test out/lambda_overload_test out/hashable_test
mason_packages: $(MASON):
git submodule update --init .mason git submodule update --init .mason
$(MASON) install $(BOOST_VERSION)
mason_packages/headers/boost: $(MASON)
$(MASON) install boost $(BOOST_VERSION)
./deps/gyp: ./deps/gyp:
git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp git clone --depth 1 https://chromium.googlesource.com/external/gyp.git ./deps/gyp
@ -25,35 +55,35 @@ mason_packages:
gyp: ./deps/gyp gyp: ./deps/gyp
deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make deps/gyp/gyp --depth=. -Goutput_dir=./ --generator-output=./out -f make
make V=1 -C ./out tests make V=1 -C ./out tests
./out/Release/tests ./out/$(BUILDTYPE)/tests
out/bench-variant-debug: Makefile mason_packages test/bench_variant.cpp out/bench-variant-debug: Makefile mason_packages/headers/boost test/bench_variant.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -Itest/include -pthreads $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/bench-variant: Makefile mason_packages test/bench_variant.cpp out/bench-variant: Makefile mason_packages/headers/boost test/bench_variant.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/unique_ptr_test: Makefile mason_packages test/unique_ptr_test.cpp out/unique_ptr_test: Makefile mason_packages/headers/boost test/unique_ptr_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/recursive_wrapper_test: Makefile mason_packages test/recursive_wrapper_test.cpp out/recursive_wrapper_test: Makefile mason_packages/headers/boost test/recursive_wrapper_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/binary_visitor_test: Makefile mason_packages test/binary_visitor_test.cpp out/binary_visitor_test: Makefile mason_packages/headers/boost test/binary_visitor_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/lambda_overload_test: Makefile mason_packages test/lambda_overload_test.cpp out/lambda_overload_test: Makefile mason_packages/headers/boost test/lambda_overload_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/lambda_overload_test test/lambda_overload_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/lambda_overload_test test/lambda_overload_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
out/hashable_test: Makefile mason_packages test/hashable_test.cpp out/hashable_test: Makefile mason_packages/headers/boost test/hashable_test.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) $(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test
./out/bench-variant 100000 ./out/bench-variant 100000
@ -63,13 +93,31 @@ bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_w
out/unit.o: Makefile test/unit.cpp out/unit.o: Makefile test/unit.cpp
mkdir -p ./out mkdir -p ./out
$(CXX) -c -o $@ test/unit.cpp -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(CXX) -c -o $@ test/unit.cpp -isystem test/include $(FINAL_CXXFLAGS)
out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS) out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS)
mkdir -p ./out mkdir -p ./out
$(CXX) -c -o $@ $< -Iinclude -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(CXX) -c -o $@ $< -Iinclude -isystem test/include $(FINAL_CXXFLAGS)
out/unit: out/unit.o \
out/binary_visitor_1.o \
out/binary_visitor_2.o \
out/binary_visitor_3.o \
out/binary_visitor_4.o \
out/binary_visitor_5.o \
out/binary_visitor_6.o \
out/issue21.o \
out/issue122.o \
out/mutating_visitor.o \
out/optional.o \
out/recursive_wrapper.o \
out/sizeof.o \
out/unary_visitor.o \
out/variant.o \
out/variant_alternative.o \
out/nothrow_move.o \
out/visitor_result_type.o \
out/unit: out/unit.o out/binary_visitor_1.o out/binary_visitor_2.o out/binary_visitor_3.o out/binary_visitor_4.o out/binary_visitor_5.o out/binary_visitor_6.o out/issue21.o out/issue122.o out/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.o
mkdir -p ./out mkdir -p ./out
$(CXX) -o $@ $^ $(LDFLAGS) $(CXX) -o $@ $^ $(LDFLAGS)
@ -78,14 +126,14 @@ test: out/unit
coverage: coverage:
mkdir -p ./out mkdir -p ./out
$(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -isystem test/include $(FINAL_CXXFLAGS) $(LDFLAGS)
sizes: Makefile sizes: Makefile
mkdir -p ./out mkdir -p ./out
@$(CXX) -o ./out/our_variant_hello_world.out include/mapbox/variant.hpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world.out @$(CXX) -o ./out/our_variant_hello_world.out include/mapbox/variant.hpp -I./include $(FINAL_CXXFLAGS) && ls -lah ./out/our_variant_hello_world.out
@$(CXX) -o ./out/boost_variant_hello_world.out `$(MASON) prefix boost 1.60.0`/include/boost/variant.hpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world.out @$(CXX) -o ./out/boost_variant_hello_world.out $(BOOST_ROOT)/include/boost/variant.hpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && ls -lah ./out/boost_variant_hello_world.out
@$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world @$(CXX) -o ./out/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) && ls -lah ./out/our_variant_hello_world
@$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(BOOST_FLAGS) && du -h ./out/boost_variant_hello_world @$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./include $(FINAL_CXXFLAGS) $(BOOST_FLAGS) && ls -lah ./out/boost_variant_hello_world
profile: out/bench-variant-debug profile: out/bench-variant-debug
mkdir -p profiling/ mkdir -p profiling/
@ -102,8 +150,8 @@ clean:
rm -f *.gcda *.gcno rm -f *.gcda *.gcno
pgo: out Makefile pgo: out Makefile
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -pg -fprofile-generate $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -pg -fprofile-generate
./test-variant 500000 >/dev/null 2>/dev/null ./test-variant 500000 >/dev/null 2>/dev/null
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use $(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(FINAL_CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use
.PHONY: sizes test .PHONY: sizes test

View File

@ -9,13 +9,13 @@ An header-only alternative to `boost::variant` for C++11 and C++14
## Introduction ## Introduction
Variant's basic building blocks are: Variant's basic building blocks are:
- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions - `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
- `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants - `recursive_wrapper<T>` - a helper type to represent recursive "tree-like" variants
- `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type - `apply_visitor(visitor, myVariant)` - to invoke a custom visitor on the variant's underlying type
- `get<T>()` - a function to directly unwrap a variant's underlying type - `get<T>()` - a function to directly unwrap a variant's underlying type
- `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant - `.match([](Type){})` - a variant convenience member function taking an arbitrary number of lambdas creating a visitor behind the scenes and applying it to the variant
### Basic Usage - HTTP API Example ### Basic Usage - HTTP API Example
Suppose you want to represent a HTTP API response which is either a JSON result or an error: Suppose you want to represent a HTTP API response which is either a JSON result or an error:
@ -46,7 +46,7 @@ Response ret = makeRequest();
To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value: To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
```c++ ```c++
ret.match([] (Result r) { print(r.object); } ret.match([] (Result r) { print(r.object); },
[] (Error e) { print(e.message); }); [] (Error e) { print(e.message); });
``` ```
@ -69,12 +69,10 @@ apply_visitor(visitor, ret);
In both cases the compiler makes sure you handle all types the variant can represent at compile. In both cases the compiler makes sure you handle all types the variant can represent at compile.
### Recursive Variants - JSON Example ### Recursive Variants - JSON Example
[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`. [JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
```c++ ```c++
struct String { string value; }; struct String { string value; };
struct Number { double value; }; struct Number { double value; };
@ -111,7 +109,7 @@ struct Object {
}; };
``` ```
For walkig the JSON representation you can again either create a `JSONVisitor`: For walking the JSON representation you can again either create a `JSONVisitor`:
```c++ ```c++
struct JSONVisitor { struct JSONVisitor {
@ -146,6 +144,7 @@ struct Node {
uint64_t value; uint64_t value;
} }
``` ```
### Advanced Usage Tips ### Advanced Usage Tips
Creating type aliases for variants is a great way to reduce repetition. Creating type aliases for variants is a great way to reduce repetition.
@ -164,7 +163,6 @@ struct APIResult : variant<Error, Result> {
} }
``` ```
## Why use Mapbox Variant? ## Why use Mapbox Variant?
Mapbox variant has the same speedy performance of `boost::variant` but is Mapbox variant has the same speedy performance of `boost::variant` but is
@ -180,7 +178,6 @@ Time to compile header | 185 ms | 675 ms
(Numbers from an older version of Mapbox variant.) (Numbers from an older version of Mapbox variant.)
## Goals ## Goals
Mapbox `variant` has been a very valuable, lightweight alternative for apps Mapbox `variant` has been a very valuable, lightweight alternative for apps
@ -206,7 +203,6 @@ Want to know more about the upcoming standard? Have a look at our
Most modern high-level languages provide ways to express sum types directly. Most modern high-level languages provide ways to express sum types directly.
If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums. If you're curious have a look at Haskell's pattern matching or Rust's and Swift's enums.
## Depends ## Depends
- Compiler supporting `-std=c++11` or `-std=c++14` - Compiler supporting `-std=c++11` or `-std=c++14`
@ -224,35 +220,29 @@ Tested with:
- clang++-3.9 - clang++-3.9
- Visual Studio 2015 - Visual Studio 2015
## Unit Tests ## Unit Tests
On Unix systems compile and run the unit tests with `make test`. On Unix systems compile and run the unit tests with `make test`.
On Windows run `scripts/build-local.bat`. On Windows run `scripts/build-local.bat`.
## Limitations ## Limitations
* The `variant` can not hold references (something like `variant<int&>` is - The `variant` can not hold references (something like `variant<int&>` is
not possible). You might want to try `std::reference_wrapper` instead. not possible). You might want to try `std::reference_wrapper` instead.
## Deprecations ## Deprecations
* The included implementation of `optional` is deprecated and will be removed - The included implementation of `optional` is deprecated and will be removed
in a future version. See https://github.com/mapbox/variant/issues/64. in a future version. See [issue #64](https://github.com/mapbox/variant/issues/64).
* Old versions of the code needed visitors to derive from `static_visitor`. - Old versions of the code needed visitors to derive from `static_visitor`.
This is not needed any more and marked as deprecated. The `static_visitor` This is not needed any more and marked as deprecated. The `static_visitor`
class will be removed in future versions. class will be removed in future versions.
## Benchmarks ## Benchmarks
make bench make bench
## Check object sizes ## Check object sizes
make sizes /path/to/boost/variant.hpp make sizes /path/to/boost/variant.hpp

View File

@ -11,6 +11,7 @@
#include <typeinfo> #include <typeinfo>
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <limits>
#include <mapbox/recursive_wrapper.hpp> #include <mapbox/recursive_wrapper.hpp>
#include <mapbox/variant_visitor.hpp> #include <mapbox/variant_visitor.hpp>
@ -74,19 +75,19 @@ public:
}; // class bad_variant_access }; // class bad_variant_access
template <typename R = void> #if !defined(MAPBOX_VARIANT_MINIMIZE_SIZE)
struct MAPBOX_VARIANT_DEPRECATED static_visitor using type_index_t = unsigned int;
{ #else
using result_type = R; #if defined(MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED)
using type_index_t = std::uint_fast8_t;
protected: #else
static_visitor() {} using type_index_t = std::uint_least8_t;
~static_visitor() {} #endif
}; #endif
namespace detail { namespace detail {
static constexpr std::size_t invalid_value = std::size_t(-1); static constexpr type_index_t invalid_value = type_index_t(-1);
template <typename T, typename... Types> template <typename T, typename... Types>
struct direct_type; struct direct_type;
@ -94,7 +95,7 @@ struct direct_type;
template <typename T, typename First, typename... Types> template <typename T, typename First, typename... Types>
struct direct_type<T, First, Types...> struct direct_type<T, First, Types...>
{ {
static constexpr std::size_t index = std::is_same<T, First>::value static constexpr type_index_t index = std::is_same<T, First>::value
? sizeof...(Types) ? sizeof...(Types)
: direct_type<T, Types...>::index; : direct_type<T, Types...>::index;
}; };
@ -102,15 +103,28 @@ struct direct_type<T, First, Types...>
template <typename T> template <typename T>
struct direct_type<T> struct direct_type<T>
{ {
static constexpr std::size_t index = invalid_value; static constexpr type_index_t index = invalid_value;
}; };
#if __cpp_lib_logical_traits >= 201510L #if __cpp_lib_logical_traits >= 201510L
using std::conjunction;
using std::disjunction; using std::disjunction;
#else #else
template <typename...>
struct conjunction : std::true_type {};
template <typename B1>
struct conjunction<B1> : B1 {};
template <typename B1, typename B2>
struct conjunction<B1, B2> : std::conditional<B1::value, B2, B1>::type {};
template <typename B1, typename... Bs>
struct conjunction<B1, Bs...> : std::conditional<B1::value, conjunction<Bs...>, B1>::type {};
template <typename...> template <typename...>
struct disjunction : std::false_type {}; struct disjunction : std::false_type {};
@ -131,7 +145,7 @@ struct convertible_type;
template <typename T, typename First, typename... Types> template <typename T, typename First, typename... Types>
struct convertible_type<T, First, Types...> struct convertible_type<T, First, Types...>
{ {
static constexpr std::size_t index = std::is_convertible<T, First>::value static constexpr type_index_t index = std::is_convertible<T, First>::value
? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types) ? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
: convertible_type<T, Types...>::index; : convertible_type<T, Types...>::index;
}; };
@ -139,64 +153,88 @@ struct convertible_type<T, First, Types...>
template <typename T> template <typename T>
struct convertible_type<T> struct convertible_type<T>
{ {
static constexpr std::size_t index = invalid_value; static constexpr type_index_t index = invalid_value;
}; };
template <typename T, typename... Types> template <typename T, typename... Types>
struct value_traits struct value_traits
{ {
using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type; using value_type = typename std::remove_const<typename std::remove_reference<T>::type>::type;
static constexpr std::size_t direct_index = direct_type<value_type, Types...>::index; using value_type_wrapper = recursive_wrapper<value_type>;
static constexpr type_index_t direct_index = direct_type<value_type, Types...>::index;
static constexpr bool is_direct = direct_index != invalid_value; static constexpr bool is_direct = direct_index != invalid_value;
static constexpr std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index; static constexpr type_index_t index_direct_or_wrapper = is_direct ? direct_index : direct_type<value_type_wrapper, Types...>::index;
static constexpr bool is_direct_or_wrapper = index_direct_or_wrapper != invalid_value;
static constexpr type_index_t index = is_direct_or_wrapper ? index_direct_or_wrapper : convertible_type<value_type, Types...>::index;
static constexpr bool is_valid = index != invalid_value; static constexpr bool is_valid = index != invalid_value;
static constexpr std::size_t tindex = is_valid ? sizeof...(Types)-index : 0; static constexpr type_index_t tindex = is_valid ? sizeof...(Types)-index : 0;
using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type; using target_type = typename std::tuple_element<tindex, std::tuple<void, Types...>>::type;
}; };
template <typename T, typename R = void> template <typename Src, typename Dest>
struct enable_if_type struct copy_cvref
{ {
using type = R; using type = Dest;
}; };
template <typename F, typename V, typename Enable = void> template <typename Src, typename Dest>
struct result_of_unary_visit struct copy_cvref<Src const&, Dest>
{ {
using type = typename std::result_of<F(V&)>::type; using type = Dest const&;
}; };
template <typename F, typename V> template <typename Src, typename Dest>
struct result_of_unary_visit<F, V, typename enable_if_type<typename F::result_type>::type> struct copy_cvref<Src&, Dest>
{ {
using type = typename F::result_type; using type = Dest&;
}; };
template <typename F, typename V, typename Enable = void> template <typename Src, typename Dest>
struct result_of_binary_visit struct copy_cvref<Src&&, Dest>
{ {
using type = typename std::result_of<F(V&, V&)>::type; using type = Dest&&;
}; };
template <typename F, typename V> template <typename F, typename = void>
struct result_of_binary_visit<F, V, typename enable_if_type<typename F::result_type>::type> struct deduced_result_type
{};
template <typename F, typename... Args>
struct deduced_result_type<F(Args...), decltype((void)std::declval<F>()(std::declval<Args>()...))>
{ {
using type = typename F::result_type; using type = decltype(std::declval<F>()(std::declval<Args>()...));
}; };
template <std::size_t arg1, std::size_t... others> template <typename F, typename = void>
struct visitor_result_type : deduced_result_type<F>
{};
// specialization for explicit result_type member in visitor class
template <typename F, typename... Args>
struct visitor_result_type<F(Args...), decltype((void)std::declval<typename std::decay<F>::type::result_type>())>
{
using type = typename std::decay<F>::type::result_type;
};
template <typename F, typename T>
using result_of_unary_visit = typename visitor_result_type<F&&(T&&)>::type;
template <typename F, typename T>
using result_of_binary_visit = typename visitor_result_type<F&&(T&&, T&&)>::type;
template <type_index_t arg1, type_index_t... others>
struct static_max; struct static_max;
template <std::size_t arg> template <type_index_t arg>
struct static_max<arg> struct static_max<arg>
{ {
static const std::size_t value = arg; static const type_index_t value = arg;
}; };
template <std::size_t arg1, std::size_t arg2, std::size_t... others> template <type_index_t arg1, type_index_t arg2, type_index_t... others>
struct static_max<arg1, arg2, others...> struct static_max<arg1, arg2, others...>
{ {
static const std::size_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value; static const type_index_t value = arg1 >= arg2 ? static_max<arg1, others...>::value : static_max<arg2, others...>::value;
}; };
template <typename... Types> template <typename... Types>
@ -205,7 +243,7 @@ struct variant_helper;
template <typename T, typename... Types> template <typename T, typename... Types>
struct variant_helper<T, Types...> struct variant_helper<T, Types...>
{ {
VARIANT_INLINE static void destroy(const std::size_t type_index, void* data) VARIANT_INLINE static void destroy(const type_index_t type_index, void* data)
{ {
if (type_index == sizeof...(Types)) if (type_index == sizeof...(Types))
{ {
@ -217,7 +255,7 @@ struct variant_helper<T, Types...>
} }
} }
VARIANT_INLINE static void move(const std::size_t old_type_index, void* old_value, void* new_value) VARIANT_INLINE static void move(const type_index_t old_type_index, void* old_value, void* new_value)
{ {
if (old_type_index == sizeof...(Types)) if (old_type_index == sizeof...(Types))
{ {
@ -229,7 +267,7 @@ struct variant_helper<T, Types...>
} }
} }
VARIANT_INLINE static void copy(const std::size_t old_type_index, const void* old_value, void* new_value) VARIANT_INLINE static void copy(const type_index_t old_type_index, const void* old_value, void* new_value)
{ {
if (old_type_index == sizeof...(Types)) if (old_type_index == sizeof...(Types))
{ {
@ -245,253 +283,182 @@ struct variant_helper<T, Types...>
template <> template <>
struct variant_helper<> struct variant_helper<>
{ {
VARIANT_INLINE static void destroy(const std::size_t, void*) {} VARIANT_INLINE static void destroy(const type_index_t, void*) {}
VARIANT_INLINE static void move(const std::size_t, void*, void*) {} VARIANT_INLINE static void move(const type_index_t, void*, void*) {}
VARIANT_INLINE static void copy(const std::size_t, const void*, void*) {} VARIANT_INLINE static void copy(const type_index_t, const void*, void*) {}
}; };
template <typename T> template <typename T>
struct unwrapper struct unwrapper
{ {
static T const& apply_const(T const& obj) { return obj; } using value_type = T;
static T& apply(T& obj) { return obj; }
};
template <typename T> template <typename V>
struct unwrapper<recursive_wrapper<T>> static auto apply(typename std::remove_reference<V>::type& var)
-> typename std::enable_if<std::is_lvalue_reference<V>::value,
decltype(var.template get_unchecked<T>())>::type
{ {
static auto apply_const(recursive_wrapper<T> const& obj) return var.template get_unchecked<T>();
-> typename recursive_wrapper<T>::type const&
{
return obj.get();
} }
static auto apply(recursive_wrapper<T>& obj)
-> typename recursive_wrapper<T>::type& template <typename V>
static auto apply(typename std::remove_reference<V>::type& var)
-> typename std::enable_if<!std::is_lvalue_reference<V>::value,
decltype(std::move(var.template get_unchecked<T>()))>::type
{ {
return obj.get(); return std::move(var.template get_unchecked<T>());
} }
}; };
template <typename T> template <typename T>
struct unwrapper<std::reference_wrapper<T>> struct unwrapper<recursive_wrapper<T>> : unwrapper<T>
{ {};
static auto apply_const(std::reference_wrapper<T> const& obj)
-> typename std::reference_wrapper<T>::type const&
{
return obj.get();
}
static auto apply(std::reference_wrapper<T>& obj)
-> typename std::reference_wrapper<T>::type&
{
return obj.get();
}
};
template <typename F, typename V, typename R, typename... Types> template <typename T>
struct unwrapper<std::reference_wrapper<T>> : unwrapper<T>
{};
template <typename R, typename... Types>
struct dispatcher; struct dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct dispatcher<F, V, R, T, Types...> struct dispatcher<R, T, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& v, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v, F&& f)
{ {
if (v.template is<T>()) if (v.template is<T>())
{ {
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>())); return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
} }
else else
{ {
return dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)); return dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
}
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
if (v.template is<T>())
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
}
else
{
return dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T> template <typename R, typename T>
struct dispatcher<F, V, R, T> struct dispatcher<R, T>
{ {
VARIANT_INLINE static R apply_const(V const& v, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v, F&& f)
{ {
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>())); return std::forward<F>(f)(unwrapper<T>::template apply<V>(v));
}
VARIANT_INLINE static R apply(V& v, F&& f)
{
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
} }
}; };
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher_rhs; struct binary_dispatcher_rhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types> template <typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...> struct binary_dispatcher_rhs<R, T0, T1, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
if (rhs.template is<T1>()) // call binary functor if (rhs.template is<T1>()) // call binary functor
{ {
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()), return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>())); unwrapper<T1>::template apply<V>(rhs));
} }
else else
{ {
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f)); return binary_dispatcher_rhs<R, T0, Types...>::apply(std::forward<V>(lhs),
} std::forward<V>(rhs),
} std::forward<F>(f));
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (rhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
}
else
{
return binary_dispatcher_rhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T0, typename T1> template <typename R, typename T0, typename T1>
struct binary_dispatcher_rhs<F, V, R, T0, T1> struct binary_dispatcher_rhs<R, T0, T1>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()), return std::forward<F>(f)(unwrapper<T0>::template apply<V>(lhs),
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>())); unwrapper<T1>::template apply<V>(rhs));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
} }
}; };
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher_lhs; struct binary_dispatcher_lhs;
template <typename F, typename V, typename R, typename T0, typename T1, typename... Types> template <typename R, typename T0, typename T1, typename... Types>
struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...> struct binary_dispatcher_lhs<R, T0, T1, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
if (lhs.template is<T1>()) // call binary functor if (lhs.template is<T1>()) // call binary functor
{ {
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()), return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>())); unwrapper<T0>::template apply<V>(rhs));
} }
else else
{ {
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply_const(lhs, rhs, std::forward<F>(f)); return binary_dispatcher_lhs<R, T0, Types...>::apply(std::forward<V>(lhs),
} std::forward<V>(rhs),
} std::forward<F>(f));
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
if (lhs.template is<T1>()) // call binary functor
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
}
else
{
return binary_dispatcher_lhs<F, V, R, T0, Types...>::apply(lhs, rhs, std::forward<F>(f));
} }
} }
}; };
template <typename F, typename V, typename R, typename T0, typename T1> template <typename R, typename T0, typename T1>
struct binary_dispatcher_lhs<F, V, R, T0, T1> struct binary_dispatcher_lhs<R, T0, T1>
{ {
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& lhs, V&& rhs, F&& f)
{ {
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()), return std::forward<F>(f)(unwrapper<T1>::template apply<V>(lhs),
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>())); unwrapper<T0>::template apply<V>(rhs));
}
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
{
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
} }
}; };
template <typename F, typename V, typename R, typename... Types> template <typename R, typename... Types>
struct binary_dispatcher; struct binary_dispatcher;
template <typename F, typename V, typename R, typename T, typename... Types> template <typename R, typename T, typename... Types>
struct binary_dispatcher<F, V, R, T, Types...> struct binary_dispatcher<R, T, Types...>
{ {
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
{ {
if (v0.template is<T>()) if (v0.template is<T>())
{ {
if (v1.template is<T>()) if (v1.template is<T>())
{ {
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()), return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor unwrapper<T>::template apply<V>(v1)); // call binary functor
} }
else else
{ {
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher_rhs<R, T, Types...>::apply(std::forward<V>(v0),
std::forward<V>(v1),
std::forward<F>(f));
} }
} }
else if (v1.template is<T>()) else if (v1.template is<T>())
{ {
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher_lhs<R, T, Types...>::apply(std::forward<V>(v0),
std::forward<V>(v1),
std::forward<F>(f));
} }
return binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)); return binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
} std::forward<V>(v1),
std::forward<F>(f));
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
if (v0.template is<T>())
{
if (v1.template is<T>())
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
}
else
{
return binary_dispatcher_rhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
}
else if (v1.template is<T>())
{
return binary_dispatcher_lhs<F, V, R, T, Types...>::apply(v0, v1, std::forward<F>(f));
}
return binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
} }
}; };
template <typename F, typename V, typename R, typename T> template <typename R, typename T>
struct binary_dispatcher<F, V, R, T> struct binary_dispatcher<R, T>
{ {
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) template <typename V, typename F>
VARIANT_INLINE static R apply(V&& v0, V&& v1, F&& f)
{ {
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()), return std::forward<F>(f)(unwrapper<T>::template apply<V>(v0),
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor unwrapper<T>::template apply<V>(v1)); // call binary functor
}
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
{
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
} }
}; };
@ -545,16 +512,15 @@ struct hasher
} // namespace detail } // namespace detail
struct no_init struct no_init {};
{
};
template <typename... Types> template <typename... Types>
class variant class variant
{ {
static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty"); static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty.");
static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?"); static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
static_assert(!detail::disjunction<std::is_array<Types>...>::value, "Variant can not hold array types.");
static_assert(sizeof...(Types) < std::numeric_limits<type_index_t>::max(), "Internal index type must be able to accommodate all alternatives.");
private: private:
static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value; static const std::size_t data_size = detail::static_max<sizeof(Types)...>::value;
static const std::size_t data_align = detail::static_max<alignof(Types)...>::value; static const std::size_t data_align = detail::static_max<alignof(Types)...>::value;
@ -563,17 +529,25 @@ public:
using types = std::tuple<Types...>; using types = std::tuple<Types...>;
private: private:
using first_type = typename std::tuple_element<0, types>::type; using first_type = typename std::tuple_element<0, types>::type;
using unwrap_first_type = typename detail::unwrapper<first_type>::value_type;
using data_type = typename std::aligned_storage<data_size, data_align>::type; using data_type = typename std::aligned_storage<data_size, data_align>::type;
using helper_type = detail::variant_helper<Types...>; using helper_type = detail::variant_helper<Types...>;
std::size_t type_index; template <typename V, typename T = unwrap_first_type>
using alternative_ref = typename detail::copy_cvref<V, T>::type;
type_index_t type_index;
#ifdef __clang_analyzer__
data_type data {};
#else
data_type data; data_type data;
#endif
public: public:
VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value) VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible<first_type>::value)
: type_index(sizeof...(Types)-1) : type_index(sizeof...(Types)-1)
{ {
static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant"); static_assert(std::is_default_constructible<first_type>::value, "First type in variant must be default constructible to allow default construction of variant.");
new (&data) first_type(); new (&data) first_type();
} }
@ -595,7 +569,8 @@ public:
helper_type::copy(old.type_index, &old.data, &data); helper_type::copy(old.type_index, &old.data, &data);
} }
VARIANT_INLINE variant(variant<Types...>&& old) noexcept(std::is_nothrow_move_constructible<types>::value) VARIANT_INLINE variant(variant<Types...>&& old)
noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
: type_index(old.type_index) : type_index(old.type_index)
{ {
helper_type::move(old.type_index, &old.data, &data); helper_type::move(old.type_index, &old.data, &data);
@ -620,21 +595,34 @@ private:
public: public:
VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other) VARIANT_INLINE variant<Types...>& operator=(variant<Types...>&& other)
// note we check for nothrow-constructible, not nothrow-assignable, since
// move_assign uses move-construction via placement new.
noexcept(detail::conjunction<std::is_nothrow_move_constructible<Types>...>::value)
{ {
if (this == &other) { // playing safe in release mode, hit assertion in debug.
assert(false);
return *this;
}
move_assign(std::move(other)); move_assign(std::move(other));
return *this; return *this;
} }
VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other) VARIANT_INLINE variant<Types...>& operator=(variant<Types...> const& other)
{ {
if (this != &other)
copy_assign(other); copy_assign(other);
return *this; return *this;
} }
// conversions // conversions
// move-assign // move-assign
template <typename T> template <typename T, typename Traits = detail::value_traits<T, Types...>,
VARIANT_INLINE variant<Types...>& operator=(T&& rhs) noexcept typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
VARIANT_INLINE variant<Types...>& operator=(T&& rhs)
// not that we check is_nothrow_constructible<T>, not is_nothrow_move_assignable<T>,
// since we construct a temporary
noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value
&& std::is_nothrow_move_assignable<variant<Types...>>::value)
{ {
variant<Types...> temp(std::forward<T>(rhs)); variant<Types...> temp(std::forward<T>(rhs));
move_assign(std::move(temp)); move_assign(std::move(temp));
@ -824,7 +812,7 @@ public:
// This function is deprecated because it returns an internal index field. // This function is deprecated because it returns an internal index field.
// Use which() instead. // Use which() instead.
MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE std::size_t get_type_index() const MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE type_index_t get_type_index() const
{ {
return type_index; return type_index;
} }
@ -843,51 +831,44 @@ public:
// visitor // visitor
// unary // unary
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type> template <typename F, typename V, typename T0 = alternative_ref<V>,
auto VARIANT_INLINE static visit(V const& v, F&& f) typename R = detail::result_of_unary_visit<F, T0>>
-> decltype(detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f))) VARIANT_INLINE static R visit(V&& v, F&& f)
{ {
return detail::dispatcher<F, V, R, Types...>::apply_const(v, std::forward<F>(f)); return detail::dispatcher<R, Types...>::apply(std::forward<V>(v), std::forward<F>(f));
}
// non-const
template <typename F, typename V, typename R = typename detail::result_of_unary_visit<F, first_type>::type>
auto VARIANT_INLINE static visit(V& v, F&& f)
-> decltype(detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f)))
{
return detail::dispatcher<F, V, R, Types...>::apply(v, std::forward<F>(f));
} }
// binary // binary
// const template <typename F, typename V, typename T0 = alternative_ref<V>,
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type> typename R = detail::result_of_binary_visit<F, T0>>
auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f) VARIANT_INLINE static R binary_visit(V&& v0, V&& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)))
{ {
return detail::binary_dispatcher<F, V, R, Types...>::apply_const(v0, v1, std::forward<F>(f)); return detail::binary_dispatcher<R, Types...>::apply(std::forward<V>(v0),
} std::forward<V>(v1),
// non-const std::forward<F>(f));
template <typename F, typename V, typename R = typename detail::result_of_binary_visit<F, first_type>::type>
auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f)
-> decltype(detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f)))
{
return detail::binary_dispatcher<F, V, R, Types...>::apply(v0, v1, std::forward<F>(f));
} }
// match // match
// unary // unary
template <typename... Fs> template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) const auto VARIANT_INLINE match(Fs&&... fs) const&
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...))) -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{ {
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)); return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
} }
// non-const // non-const
template <typename... Fs> template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) auto VARIANT_INLINE match(Fs&&... fs) &
-> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...))) -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{ {
return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)); return variant::visit(*this, ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
} }
template <typename... Fs>
auto VARIANT_INLINE match(Fs&&... fs) &&
-> decltype(variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...)))
{
return variant::visit(std::move(*this), ::mapbox::util::make_visitor(std::forward<Fs>(fs)...));
}
~variant() noexcept // no-throw destructor ~variant() noexcept // no-throw destructor
{ {
@ -938,33 +919,19 @@ public:
}; };
// unary visitor interface // unary visitor interface
// const
template <typename F, typename V> template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward<F>(f))) auto VARIANT_INLINE apply_visitor(F&& f, V&& v)
-> decltype(v.visit(std::forward<V>(v), std::forward<F>(f)))
{ {
return V::visit(v, std::forward<F>(f)); return v.visit(std::forward<V>(v), std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward<F>(f)))
{
return V::visit(v, std::forward<F>(f));
} }
// binary visitor interface // binary visitor interface
// const
template <typename F, typename V> template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f))) auto VARIANT_INLINE apply_visitor(F&& f, V&& v0, V&& v1)
-> decltype(v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f)))
{ {
return V::binary_visit(v0, v1, std::forward<F>(f)); return v0.binary_visit(std::forward<V>(v0), std::forward<V>(v1), std::forward<F>(f));
}
// non-const
template <typename F, typename V>
auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward<F>(f)))
{
return V::binary_visit(v0, v1, std::forward<F>(f));
} }
// getter interface // getter interface
@ -996,6 +963,78 @@ ResultType const& get_unchecked(T const& var)
{ {
return var.template get_unchecked<ResultType>(); return var.template get_unchecked<ResultType>();
} }
// variant_size
template <typename T>
struct variant_size;
//variable templates is c++14
//template <typename T>
//constexpr std::size_t variant_size_v = variant_size<T>::value;
template <typename T>
struct variant_size<const T>
: variant_size<T> {};
template <typename T>
struct variant_size<volatile T>
: variant_size<T> {};
template <typename T>
struct variant_size<const volatile T>
: variant_size<T> {};
template <typename... Types>
struct variant_size<variant<Types...>>
: std::integral_constant<std::size_t, sizeof...(Types)> {};
// variant_alternative
template <std::size_t Index, typename T>
struct variant_alternative;
#if defined(__clang__)
#if __has_builtin(__type_pack_element)
#define has_type_pack_element
#endif
#endif
#if defined(has_type_pack_element)
template <std::size_t Index, typename ...Types>
struct variant_alternative<Index, variant<Types...>>
{
static_assert(sizeof...(Types) > Index , "Index out of range");
using type = __type_pack_element<Index, Types...>;
};
#else
template <std::size_t Index, typename First, typename...Types>
struct variant_alternative<Index, variant<First, Types...>>
: variant_alternative<Index - 1, variant<Types...>>
{
static_assert(sizeof...(Types) > Index -1 , "Index out of range");
};
template <typename First, typename...Types>
struct variant_alternative<0, variant<First, Types...>>
{
using type = First;
};
#endif
template <size_t Index, typename T>
using variant_alternative_t = typename variant_alternative<Index, T>::type;
template <size_t Index, typename T>
struct variant_alternative<Index, const T>
: std::add_const<variant_alternative<Index, T>> {};
template <size_t Index, typename T>
struct variant_alternative<Index, volatile T>
: std::add_volatile<variant_alternative<Index, T>> {};
template <size_t Index, typename T>
struct variant_alternative<Index, const volatile T>
: std::add_cv<variant_alternative<Index, T>> {};
} // namespace util } // namespace util
} // namespace mapbox } // namespace mapbox
@ -1008,6 +1047,7 @@ struct hash< ::mapbox::util::variant<Types...>> {
return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v); return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
} }
}; };
} }
#endif // MAPBOX_UTIL_VARIANT_HPP #endif // MAPBOX_UTIL_VARIANT_HPP

View File

@ -0,0 +1,85 @@
#ifndef VARIANT_CAST_HPP
#define VARIANT_CAST_HPP
#include <type_traits>
namespace mapbox {
namespace util {
namespace detail {
template <class T>
class static_caster
{
public:
template <class V>
T& operator()(V& v) const
{
return static_cast<T&>(v);
}
};
template <class T>
class dynamic_caster
{
public:
using result_type = T&;
template <class V>
T& operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
throw std::bad_cast();
}
template <class V>
T& operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T&>(v);
}
};
template <class T>
class dynamic_caster<T*>
{
public:
using result_type = T*;
template <class V>
T* operator()(V& v, typename std::enable_if<!std::is_polymorphic<V>::value>::type* = nullptr) const
{
return nullptr;
}
template <class V>
T* operator()(V& v, typename std::enable_if<std::is_polymorphic<V>::value>::type* = nullptr) const
{
return dynamic_cast<T*>(&v);
}
};
}
template <class T, class V>
typename detail::dynamic_caster<T>::result_type
dynamic_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<T>(), v);
}
template <class T, class V>
typename detail::dynamic_caster<const T>::result_type
dynamic_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::dynamic_caster<const T>(), v);
}
template <class T, class V>
T& static_variant_cast(V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<T>(), v);
}
template <class T, class V>
const T& static_variant_cast(const V& v)
{
return mapbox::util::apply_visitor(detail::static_caster<const T>(), v);
}
}
}
#endif // VARIANT_CAST_HPP

View File

@ -1,6 +1,8 @@
#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP #ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
#define MAPBOX_UTIL_VARIANT_VISITOR_HPP #define MAPBOX_UTIL_VARIANT_VISITOR_HPP
#include <utility>
namespace mapbox { namespace mapbox {
namespace util { namespace util {
@ -10,26 +12,29 @@ struct visitor;
template <typename Fn> template <typename Fn>
struct visitor<Fn> : Fn struct visitor<Fn> : Fn
{ {
using type = Fn;
using Fn::operator(); using Fn::operator();
visitor(Fn fn) : Fn(fn) {} template<typename T>
visitor(T&& fn) : Fn(std::forward<T>(fn)) {}
}; };
template <typename Fn, typename... Fns> template <typename Fn, typename... Fns>
struct visitor<Fn, Fns...> : Fn, visitor<Fns...> struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
{ {
using type = visitor;
using Fn::operator(); using Fn::operator();
using visitor<Fns...>::operator(); using visitor<Fns...>::operator();
visitor(Fn fn, Fns... fns) : Fn(fn), visitor<Fns...>(fns...) {} template<typename T, typename... Ts>
visitor(T&& fn, Ts&&... fns)
: Fn(std::forward<T>(fn))
, visitor<Fns...>(std::forward<Ts>(fns)...) {}
}; };
template <typename... Fns> template <typename... Fns>
visitor<Fns...> make_visitor(Fns... fns) visitor<typename std::decay<Fns>::type...> make_visitor(Fns&&... fns)
{ {
return visitor<Fns...>(fns...); return visitor<typename std::decay<Fns>::type...>
(std::forward<Fns>(fns)...);
} }
} // namespace util } // namespace util

10
third_party/variant/package.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"name": "variant",
"version": "1.1.6",
"description": "C++11/C++14 variant",
"main": "./package.json",
"repository" : {
"type" : "git",
"url" : "git://github.com/mapbox/variant.git"
}
}

View File

@ -1,4 +1,4 @@
// @EXPECTED: enable_if // @EXPECTED: no matching .*\<function for call to .*\<get\>
#include <mapbox/variant.hpp> #include <mapbox/variant.hpp>

View File

@ -1,4 +1,4 @@
// @EXPECTED: const int // @EXPECTED: no matching function for call to .*\<apply_visitor\>
#include <mapbox/variant.hpp> #include <mapbox/variant.hpp>

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,15 @@
using namespace mapbox::util; using namespace mapbox::util;
template <typename T>
struct tag
{
static void dump(const char* prefix)
{
std::cout << prefix << ": " << typeid(tag<T>).name() << std::endl;
}
};
template <typename Left, typename Right> template <typename Left, typename Right>
using Either = mapbox::util::variant<Left, Right>; using Either = mapbox::util::variant<Left, Right>;
@ -55,6 +64,37 @@ void test_singleton_variant()
apply_visitor(make_visitor([](int) {}), singleton); apply_visitor(make_visitor([](int) {}), singleton);
} }
// See #180
struct test_call_nonconst_member_visitor
{
template <typename T>
void operator() (T & obj) const
{
tag<decltype(obj)>::dump("test_call_nonconst_member: visitor");
obj.foo();
}
};
void test_call_nonconst_member()
{
struct object
{
void foo() { val = 42;}
int val = 0;
};
variant<object> v = object{};
apply_visitor(test_call_nonconst_member_visitor{}, v);
#ifdef HAS_CPP14_SUPPORT
apply_visitor([](auto& obj)
{
tag<decltype(obj)>::dump("test_call_nonconst_member: lambda");
obj.foo();
}, v);
#endif
}
void test_lambda_overloads_sfinae() void test_lambda_overloads_sfinae()
#ifdef HAS_CPP14_SUPPORT #ifdef HAS_CPP14_SUPPORT
{ {
@ -85,6 +125,9 @@ void test_match_singleton()
{ {
variant<int> singleton = 5; variant<int> singleton = 5;
singleton.match([](int) {}); singleton.match([](int) {});
auto lambda = [](int) {};
singleton.match(lambda);
} }
void test_match_overloads() void test_match_overloads()
@ -112,16 +155,128 @@ void test_match_overloads_capture()
std::cout << "Got " << ok << " ok, " << err << " err" << std::endl; std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
} }
struct MovableOnly
{
MovableOnly() = default;
MovableOnly(MovableOnly&&) = default;
MovableOnly& operator=(MovableOnly&&) = default;
};
struct MovableCopyable
{
MovableCopyable() = default;
MovableCopyable(MovableCopyable&&) = default;
MovableCopyable& operator=(MovableCopyable&&) = default;
MovableCopyable(const MovableCopyable&) = default;
MovableCopyable& operator=(const MovableCopyable&) = default;
};
void test_match_overloads_init_capture()
#ifdef HAS_CPP14_SUPPORT
{
Either<Error, Response> rv;
rv = Error{};
rv.match([p = MovableOnly{}](auto&&) {});
{
auto lambda = [p = MovableCopyable{}](auto&&) {};
rv.match(lambda);
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
[p = MovableOnly{}](Error) { std::cout << "Error\n"; });
}
{
auto lambda = [](Error) { std::cout << "Error\n"; };
rv.match([p = MovableOnly{}](Response) { std::cout << "Response\n"; },
lambda);
rv.match(lambda,
[p = MovableOnly{}](Response) { std::cout << "Response\n"; });
}
}
#else
{
}
#endif
// See #140
void test_match_overloads_otherwise()
#ifdef HAS_CPP14_SUPPORT
{
struct Center
{
};
struct Indent
{
};
struct Justify
{
};
struct None
{
};
using Properties = mapbox::util::variant<Center, Indent, Justify, None>;
Properties props = Justify{};
props.match([&](Center) { std::cout << "Center\n"; }, //
[&](Indent) { std::cout << "Indent\n"; }, //
[&](auto&&) { std::cout << "Otherwise\n"; }); //
}
#else
{
}
#endif
template <typename>
struct Moveable
{
Moveable() = default; // Default constructible
Moveable(const Moveable&) = delete; // Disable copy ctor
Moveable& operator=(const Moveable&) = delete; // Disable copy assign op
Moveable(Moveable&&) = default; // Enable move ctor
Moveable& operator=(Moveable&&) = default; // Enable move assign op
};
void test_match_move_out_of_variant()
{
// Distinguishable at type level
using T1 = Moveable<struct Tag1>;
using T2 = Moveable<struct Tag2>;
using T3 = mapbox::util::recursive_wrapper<int>;
mapbox::util::variant<T1, T2> v = T1{};
std::move(v).match([](T1&&) {}, // Consume T1 by value
[](T2&&) {}); // Consume T2 by value
mapbox::util::variant<T3, T2> w = T2{};
std::move(w).match([](int&&) {}, // Consume unwrapped int
[](T2&&) {}); // Consume T2 by value
}
int main() int main()
{ {
test_lambda_overloads(); test_lambda_overloads();
test_singleton_variant(); test_singleton_variant();
test_call_nonconst_member();
test_lambda_overloads_capture(); test_lambda_overloads_capture();
test_lambda_overloads_sfinae(); test_lambda_overloads_sfinae();
test_match_singleton(); test_match_singleton();
test_match_overloads(); test_match_overloads();
test_match_overloads_capture(); test_match_overloads_capture();
test_match_overloads_init_capture();
test_match_overloads_otherwise();
test_match_move_out_of_variant();
} }
#undef HAS_CPP14_SUPPORT #undef HAS_CPP14_SUPPORT

View File

@ -1,4 +1,3 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -64,12 +63,12 @@ struct calculator
int operator()(binary_op<add> const& binary) const int operator()(binary_op<add> const& binary) const
{ {
return util::apply_visitor(calculator(), binary.left) + util::apply_visitor(calculator(), binary.right); return util::apply_visitor(*this, binary.left) + util::apply_visitor(*this, binary.right);
} }
int operator()(binary_op<sub> const& binary) const int operator()(binary_op<sub> const& binary) const
{ {
return util::apply_visitor(calculator(), binary.left) - util::apply_visitor(calculator(), binary.right); return util::apply_visitor(*this, binary.left) - util::apply_visitor(*this, binary.right);
} }
}; };
@ -83,12 +82,12 @@ struct to_string
std::string operator()(binary_op<add> const& binary) const std::string operator()(binary_op<add> const& binary) const
{ {
return util::apply_visitor(to_string(), binary.left) + std::string("+") + util::apply_visitor(to_string(), binary.right); return util::apply_visitor(*this, binary.left) + std::string("+") + util::apply_visitor(*this, binary.right);
} }
std::string operator()(binary_op<sub> const& binary) const std::string operator()(binary_op<sub> const& binary) const
{ {
return util::apply_visitor(to_string(), binary.left) + std::string("-") + util::apply_visitor(to_string(), binary.right); return util::apply_visitor(*this, binary.left) + std::string("-") + util::apply_visitor(*this, binary.right);
} }
}; };

View File

@ -160,8 +160,8 @@ struct swap_visitor
{ {
using T = typename std::common_type<A, B>::type; using T = typename std::common_type<A, B>::type;
T tmp = a; T tmp = a;
a = b; a = static_cast<A>(b);
b = tmp; b = static_cast<B>(tmp);
} }
}; };

View File

@ -46,9 +46,7 @@ TEST_CASE("set() works cleanly even if the constructor throws ", "[variant]")
variant_type v = obj; variant_type v = obj;
REQUIRE(v.is<t1>()); REQUIRE(v.is<t1>());
REQUIRE(v.get<t1>().value == 42); REQUIRE(v.get<t1>().value == 42);
REQUIRE_THROWS({ REQUIRE_THROWS(v.set<t2>(13));
v.set<t2>(13);
});
} }
REQUIRE(count == 0); REQUIRE(count == 0);
} }

View File

@ -0,0 +1,66 @@
#include <typeinfo>
#include <utility>
#include <mapbox/variant.hpp>
using namespace mapbox;
namespace test {
struct t_noexcept_true_1 {
t_noexcept_true_1(t_noexcept_true_1&&) noexcept = default;
t_noexcept_true_1& operator=(t_noexcept_true_1&&) noexcept = default;
};
struct t_noexcept_true_2 {
t_noexcept_true_2(t_noexcept_true_2&&) noexcept = default;
t_noexcept_true_2& operator=(t_noexcept_true_2&&) noexcept = default;
};
struct t_noexcept_false_1 {
t_noexcept_false_1(t_noexcept_false_1&&) noexcept(false) {}
t_noexcept_false_1& operator=(t_noexcept_false_1&&) noexcept(false) { return *this; }
};
using should_be_no_throw_copyable = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
static_assert(std::is_nothrow_move_assignable<should_be_no_throw_copyable>::value,
"variants with no-throw move assignable types should be "
"no-throw move nothrow assignable");
using should_be_no_throw_assignable = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
static_assert(std::is_nothrow_move_constructible<should_be_no_throw_assignable>::value,
"variants with no-throw move assignable types should be "
"no-throw move nothrow assignable");
using should_not_be_no_throw_copyable = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
static_assert(not std::is_nothrow_move_assignable<should_not_be_no_throw_copyable>::value,
"variants with no-throw move assignable types should be "
"no-throw move nothrow assignable");
using should_not_be_no_throw_assignable = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
static_assert(not std::is_nothrow_move_constructible<should_not_be_no_throw_assignable>::value,
"variants with no-throw move assignable types should be "
"no-throw move nothrow assignable");
// this type cannot be nothrow converted from either of its types, even the nothrow moveable one,
// because the conversion operator moves the whole variant.
using convertable_test_type = util::variant<t_noexcept_true_1, t_noexcept_false_1>;
// this type can be nothrow converted from either of its types.
using convertable_test_type_2 = util::variant<t_noexcept_true_1, t_noexcept_true_2>;
static_assert(not std::is_nothrow_assignable<convertable_test_type, t_noexcept_true_1>::value,
"variants with noexcept(true) move constructible types should be nothrow-convertible "
"from those types only IF the variant itself is nothrow_move_assignable");
static_assert(not std::is_nothrow_assignable<convertable_test_type, t_noexcept_false_1>::value,
"variants with noexcept(false) move constructible types should not be nothrow-convertible "
"from those types");
static_assert(std::is_nothrow_assignable<convertable_test_type_2, t_noexcept_true_2>::value,
"variants with noexcept(true) move constructible types should be nothrow-convertible "
"from those types only IF the variant itself is nothrow_move_assignable");
} // namespace test

View File

@ -1,4 +1,3 @@
#include "catch.hpp" #include "catch.hpp"
#include <mapbox/optional.hpp> #include <mapbox/optional.hpp>
@ -97,6 +96,8 @@ TEST_CASE("self assignment", "[optional]")
a = 1; a = 1;
REQUIRE(a.get() == 1); REQUIRE(a.get() == 1);
#if !defined(__clang__)
a = a; a = a;
REQUIRE(a.get() == 1); REQUIRE(a.get() == 1);
#endif
} }

View File

@ -1,6 +1,6 @@
#include "catch.hpp" #include "catch.hpp"
#include <mapbox/variant.hpp>
#include <mapbox/recursive_wrapper.hpp> #include <mapbox/recursive_wrapper.hpp>
#include <type_traits> #include <type_traits>
@ -155,4 +155,31 @@ TEST_CASE("recursive wrapper of pair<int, int>")
REQUIRE(b.get().second == 6); REQUIRE(b.get().second == 6);
//REQUIRE(c.get_pointer() == nullptr); //REQUIRE(c.get_pointer() == nullptr);
} }
SECTION("Multiple recurssive wrappers of polymorphic types")
{
// https://github.com/mapbox/variant/issues/146
// (Visual Studio 2015 update 3)
using namespace mapbox::util;
struct Base;
struct Derived;
using Variant = variant<recursive_wrapper<Base>, recursive_wrapper<Derived>>;
struct Base { };
struct Derived : public Base { };
{
Base base;
Derived derived;
Variant v;
v = base;
v = derived; // compile error prior https://github.com/mapbox/variant/pull/147
CHECK(v.is<Derived>());
}
{
Derived derived;
Variant v(derived); // compile error prior https://github.com/mapbox/variant/pull/147
CHECK(v.is<Derived>());
}
}
} }

View File

@ -1,4 +1,3 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@ -15,7 +14,7 @@ struct some_struct
std::string c; std::string c;
}; };
using variant_internal_index_type = size_t; using variant_internal_index_type = mapbox::util::type_index_t;
TEST_CASE("size of variants") TEST_CASE("size of variants")
{ {

View File

@ -208,9 +208,7 @@ TEST_CASE("get with wrong type (here: double) should throw", "[variant]")
REQUIRE(var.is<int>()); REQUIRE(var.is<int>());
REQUIRE_FALSE(var.is<double>()); REQUIRE_FALSE(var.is<double>());
REQUIRE(var.get<int>() == 5); REQUIRE(var.get<int>() == 5);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<double>(),
var.get<double>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -222,13 +220,9 @@ TEST_CASE("get with wrong type (here: int) should throw", "[variant]")
REQUIRE_FALSE(var.is<int>()); REQUIRE_FALSE(var.is<int>());
REQUIRE(var.get<double>() == 5.0); REQUIRE(var.get<double>() == 5.0);
REQUIRE(mapbox::util::get<double>(var) == 5.0); REQUIRE(mapbox::util::get<double>(var) == 5.0);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<int>(),
var.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<int>(var),
mapbox::util::get<int>(var);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -240,26 +234,18 @@ TEST_CASE("get on const varint with wrong type (here: int) should throw", "[vari
REQUIRE_FALSE(var.is<int>()); REQUIRE_FALSE(var.is<int>());
REQUIRE(var.get<double>() == 5.0); REQUIRE(var.get<double>() == 5.0);
REQUIRE(mapbox::util::get<double>(var) == 5.0); REQUIRE(mapbox::util::get<double>(var) == 5.0);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<int>(),
var.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<int>(var),
mapbox::util::get<int>(var);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
TEST_CASE("get with any type should throw if not initialized", "[variant]") TEST_CASE("get with any type should throw if not initialized", "[variant]")
{ {
mapbox::util::variant<int, double> var{mapbox::util::no_init()}; mapbox::util::variant<int, double> var{mapbox::util::no_init()};
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<int>(),
var.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<double>(),
var.get<double>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -273,16 +259,12 @@ TEST_CASE("no_init variant can be copied and moved from", "[variant]")
REQUIRE(v2.get<int>() == 42); REQUIRE(v2.get<int>() == 42);
v2 = v1; v2 = v1;
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v2.get<int>(),
v2.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE(v3.get<int>() == 23); REQUIRE(v3.get<int>() == 23);
v3 = std::move(v1); v3 = std::move(v1);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v3.get<int>(),
v3.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -294,9 +276,7 @@ TEST_CASE("no_init variant can be copied and moved to", "[variant]")
variant_type v2{mapbox::util::no_init()}; variant_type v2{mapbox::util::no_init()};
variant_type v3{mapbox::util::no_init()}; variant_type v3{mapbox::util::no_init()};
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v2.get<int>(),
v2.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE(v1.get<int>() == 42); REQUIRE(v1.get<int>() == 42);
@ -304,9 +284,7 @@ TEST_CASE("no_init variant can be copied and moved to", "[variant]")
REQUIRE(v2.get<int>() == 42); REQUIRE(v2.get<int>() == 42);
REQUIRE(v1.get<int>() == 42); REQUIRE(v1.get<int>() == 42);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v3.get<int>(),
v3.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
v3 = std::move(v1); v3 = std::move(v1);
@ -327,9 +305,7 @@ TEST_CASE("implicit conversion to first type in variant type list", "[variant][i
using variant_type = mapbox::util::variant<long, char>; using variant_type = mapbox::util::variant<long, char>;
variant_type var = 5l; // converted to long variant_type var = 5l; // converted to long
REQUIRE(var.get<long>() == 5); REQUIRE(var.get<long>() == 5);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(var.get<char>(),
var.get<char>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -498,13 +474,9 @@ TEST_CASE("storing reference wrappers works")
variant_type v{std::ref(a)}; variant_type v{std::ref(a)};
REQUIRE(v.get<int>() == 1); REQUIRE(v.get<int>() == 1);
REQUIRE(mapbox::util::get<int>(v) == 1); REQUIRE(mapbox::util::get<int>(v) == 1);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v.get<double>(),
v.get<double>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<double>(v),
mapbox::util::get<double>(v);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
a = 2; a = 2;
REQUIRE(v.get<int>() == 2); REQUIRE(v.get<int>() == 2);
@ -515,13 +487,9 @@ TEST_CASE("storing reference wrappers works")
v = std::ref(b); v = std::ref(b);
REQUIRE(v.get<double>() == Approx(3.141)); REQUIRE(v.get<double>() == Approx(3.141));
REQUIRE(mapbox::util::get<double>(v) == Approx(3.141)); REQUIRE(mapbox::util::get<double>(v) == Approx(3.141));
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v.get<int>(),
v.get<int>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<int>(v),
mapbox::util::get<int>(v);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
b = 2.718; b = 2.718;
REQUIRE(v.get<double>() == Approx(2.718)); REQUIRE(v.get<double>() == Approx(2.718));
@ -530,9 +498,7 @@ TEST_CASE("storing reference wrappers works")
v.get<double>() = 4.1; v.get<double>() = 4.1;
REQUIRE(b == Approx(4.1)); REQUIRE(b == Approx(4.1));
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v.get<int>() = 4,
v.get<int>() = 4;
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }
@ -546,26 +512,18 @@ TEST_CASE("storing reference wrappers to consts works")
REQUIRE(v.get<int>() == 1); REQUIRE(v.get<int>() == 1);
REQUIRE(mapbox::util::get<int const>(v) == 1); REQUIRE(mapbox::util::get<int const>(v) == 1);
REQUIRE(mapbox::util::get<int>(v) == 1); REQUIRE(mapbox::util::get<int>(v) == 1);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v.get<double const>(),
v.get<double const>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<double const>(v),
mapbox::util::get<double const>(v);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
double b = 3.141; double b = 3.141;
v = std::cref(b); v = std::cref(b);
REQUIRE(v.get<double const>() == Approx(3.141)); REQUIRE(v.get<double const>() == Approx(3.141));
REQUIRE(mapbox::util::get<double const>(v) == Approx(3.141)); REQUIRE(mapbox::util::get<double const>(v) == Approx(3.141));
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(v.get<int const>(),
v.get<int const>();
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
REQUIRE_THROWS_AS({ REQUIRE_THROWS_AS(mapbox::util::get<int const>(v),
mapbox::util::get<int const>(v);
},
mapbox::util::bad_variant_access&); mapbox::util::bad_variant_access&);
} }

View File

@ -0,0 +1,31 @@
#include "catch.hpp"
#include <mapbox/variant.hpp>
#include <mapbox/variant_io.hpp>
#include <string>
TEST_CASE("variant_alternative", "[types]")
{
using variant_type = mapbox::util::variant<int, double, std::string>;
using type_0 = mapbox::util::variant_alternative<0, variant_type>::type;
using type_1 = mapbox::util::variant_alternative<1, variant_type>::type;
using type_2 = mapbox::util::variant_alternative<2, variant_type>::type;
//using type_3 = mapbox::util::variant_alternative<3, variant_type>::type; // compile error
constexpr bool check_0 = std::is_same<int, type_0>::value;
constexpr bool check_1 = std::is_same<double, type_1>::value;
constexpr bool check_2 = std::is_same<std::string, type_2>::value;
CHECK(check_0);
CHECK(check_1);
CHECK(check_2);
}
TEST_CASE("variant_size", "[types]")
{
constexpr auto value_0 = mapbox::util::variant_size<mapbox::util::variant<>>::value;
constexpr auto value_1 = mapbox::util::variant_size<mapbox::util::variant<int>>::value;
constexpr auto value_2 = mapbox::util::variant_size<mapbox::util::variant<int, std::string>>::value;
CHECK(value_0 == 0);
CHECK(value_1 == 1);
CHECK(value_2 == 2);
}

View File

@ -0,0 +1,52 @@
#include <mapbox/variant.hpp>
using namespace mapbox::util;
namespace {
template <typename... T>
struct tag {};
struct deduced_result_visitor
{
template <typename T>
tag<T> operator() (T);
template <typename T>
tag<T const> operator() (T) const;
template <typename T, typename U>
tag<T, U> operator() (T, U);
template <typename T, typename U>
tag<T, U const> operator() (T, U) const;
};
struct explicit_result_visitor : deduced_result_visitor
{
using result_type = tag<float>;
};
// Doing this compile-time test via assignment to typed tag objects gives
// more useful error messages when something goes wrong, than std::is_same
// in a static_assert would. Here if result_of_unary_visit returns anything
// other than the expected type on the left hand side, the conversion error
// message will tell you exactly what it was.
#ifdef __clang__
# pragma clang diagnostic ignored "-Wunused-variable"
#endif
tag<int> d1m = detail::result_of_unary_visit<deduced_result_visitor, int>{};
tag<int const> d1c = detail::result_of_unary_visit<deduced_result_visitor const, int>{};
tag<float> e1m = detail::result_of_unary_visit<explicit_result_visitor, int>{};
tag<float> e1c = detail::result_of_unary_visit<explicit_result_visitor const, int>{};
tag<int, int> d2m = detail::result_of_binary_visit<deduced_result_visitor, int>{};
tag<int, int const> d2c = detail::result_of_binary_visit<deduced_result_visitor const, int>{};
tag<float> e2m = detail::result_of_binary_visit<explicit_result_visitor, int>{};
tag<float> e2c = detail::result_of_binary_visit<explicit_result_visitor const, int>{};
} // namespace