Upgrade to mapbox/variant 1.1.4
This commit is contained in:
parent
20c8ac0272
commit
29b3caf529
1
third_party/variant/.gitignore
vendored
1
third_party/variant/.gitignore
vendored
@ -6,3 +6,4 @@ deps
|
|||||||
*.gcda
|
*.gcda
|
||||||
*.gcno
|
*.gcno
|
||||||
.ycm_extra_conf.pyc
|
.ycm_extra_conf.pyc
|
||||||
|
mason_packages
|
||||||
|
3
third_party/variant/.gitmodules
vendored
Normal file
3
third_party/variant/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule ".mason"]
|
||||||
|
path = .mason
|
||||||
|
url = https://github.com/mapbox/mason.git
|
59
third_party/variant/.travis.yml
vendored
59
third_party/variant/.travis.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
language: c
|
language: generic
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
@ -6,49 +6,50 @@ sudo: false
|
|||||||
addons_shortcuts:
|
addons_shortcuts:
|
||||||
addons_clang35: &clang35
|
addons_clang35: &clang35
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
|
||||||
packages: [ 'clang-3.5', 'libboost1.55-all-dev' ]
|
packages: [ 'clang-3.5', 'llvm-3.5-dev' ]
|
||||||
addons_clang36: &clang36
|
addons_clang36: &clang36
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6' ]
|
||||||
packages: [ 'clang-3.6', 'libboost1.55-all-dev' ]
|
packages: [ 'clang-3.6' ]
|
||||||
addons_clang37: &clang37
|
addons_clang37: &clang37
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7' ]
|
||||||
packages: [ 'clang-3.7', 'libboost1.55-all-dev' ]
|
packages: [ 'clang-3.7' ]
|
||||||
addons_clang38: &clang38
|
addons_clang38: &clang38
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8' ]
|
||||||
packages: [ 'clang-3.8', 'libboost1.55-all-dev']
|
packages: [ 'clang-3.8']
|
||||||
|
addons_clang39: &clang39
|
||||||
|
apt:
|
||||||
|
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise' ]
|
||||||
|
packages: [ 'clang-3.9']
|
||||||
addons_gcc47: &gcc47
|
addons_gcc47: &gcc47
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||||
packages: [ 'g++-4.7', 'libboost1.55-all-dev' ]
|
packages: [ 'g++-4.7' ]
|
||||||
addons_gcc48: &gcc48
|
addons_gcc48: &gcc48
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||||
packages: [ 'g++-4.8', 'libboost1.55-all-dev' ]
|
packages: [ 'g++-4.8' ]
|
||||||
addons_gcc49: &gcc49
|
addons_gcc49: &gcc49
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||||
packages: [ 'g++-4.9', 'libboost1.55-all-dev' ]
|
packages: [ 'g++-4.9' ]
|
||||||
addons_gcc5: &gcc5
|
addons_gcc5: &gcc5
|
||||||
apt:
|
apt:
|
||||||
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ]
|
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||||
packages: [ 'g++-5', 'libboost1.55-all-dev' ]
|
packages: [ 'g++-5' ]
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: osx
|
|
||||||
osx_image: xcode6
|
|
||||||
compiler: clang
|
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode7
|
osx_image: xcode7
|
||||||
env: TEST_GYP_BUILD=True
|
env: TEST_GYP_BUILD=True
|
||||||
compiler: clang
|
compiler: clang
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang35"
|
compiler: "clang35"
|
||||||
env: CXX=clang++-3.5
|
env: CXX=clang++-3.5 COVERAGE=True
|
||||||
addons: *clang35
|
addons: *clang35
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang36"
|
compiler: "clang36"
|
||||||
@ -56,7 +57,7 @@ matrix:
|
|||||||
addons: *clang36
|
addons: *clang36
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang37"
|
compiler: "clang37"
|
||||||
env: CXX=clang++-3.7 COVERAGE=True
|
env: CXX=clang++-3.7
|
||||||
addons: *clang37
|
addons: *clang37
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: "clang38"
|
compiler: "clang38"
|
||||||
@ -66,6 +67,11 @@ matrix:
|
|||||||
compiler: "clang38"
|
compiler: "clang38"
|
||||||
env: CXX=clang++-3.8 CXX_STD=c++14
|
env: CXX=clang++-3.8 CXX_STD=c++14
|
||||||
addons: *clang38
|
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
|
- os: linux
|
||||||
compiler: "gcc47"
|
compiler: "gcc47"
|
||||||
env: CXX=g++-4.7
|
env: CXX=g++-4.7
|
||||||
@ -96,7 +102,6 @@ before_install:
|
|||||||
- 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;
|
||||||
else
|
else
|
||||||
brew install boost;
|
|
||||||
export PYTHONPATH=$(pwd)/.local/lib/python/site-packages;
|
export PYTHONPATH=$(pwd)/.local/lib/python/site-packages;
|
||||||
fi
|
fi
|
||||||
- if [[ ${COVERAGE:-0} == 'True' ]]; then
|
- if [[ ${COVERAGE:-0} == 'True' ]]; then
|
||||||
@ -106,11 +111,7 @@ before_install:
|
|||||||
install:
|
install:
|
||||||
- make test
|
- make test
|
||||||
- make bench
|
- make bench
|
||||||
- if [[ $(uname -s) == 'Linux' ]]; then
|
- make sizes
|
||||||
make sizes /usr/include/boost/variant.hpp;
|
|
||||||
else
|
|
||||||
make sizes `brew --prefix`/include/boost/variant.hpp;
|
|
||||||
fi
|
|
||||||
- scripts/run_compilation_failure_tests.sh
|
- scripts/run_compilation_failure_tests.sh
|
||||||
- if [[ ${TEST_GYP_BUILD:-0} == 'True' ]]; then
|
- if [[ ${TEST_GYP_BUILD:-0} == 'True' ]]; then
|
||||||
make clean;
|
make clean;
|
||||||
@ -123,5 +124,5 @@ script:
|
|||||||
make coverage;
|
make coverage;
|
||||||
./out/cov-test;
|
./out/cov-test;
|
||||||
cp unit*gc* test/;
|
cp unit*gc* test/;
|
||||||
./.local/bin/cpp-coveralls -i optional.hpp -i recursive_wrapper.hpp -i variant.hpp -i variant_io.hpp --gcov-options '\-lp';
|
./.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;
|
||||||
fi
|
fi
|
||||||
|
19
third_party/variant/Jamroot
vendored
19
third_party/variant/Jamroot
vendored
@ -1,4 +1,4 @@
|
|||||||
# Inofficial 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" ;
|
local BOOST_DIR = "/usr/local" ;
|
||||||
@ -17,9 +17,10 @@ exe variant-test
|
|||||||
.//chrono
|
.//chrono
|
||||||
:
|
:
|
||||||
<include>$(BOOST_DIR)/include
|
<include>$(BOOST_DIR)/include
|
||||||
<include>./
|
<include>./include
|
||||||
|
<include>./test/include
|
||||||
#<define>SINGLE_THREADED
|
#<define>SINGLE_THREADED
|
||||||
<variant>release:<cxxflags>-march=native
|
<variant>release:<cxxflags>"-march=native -Wweak-vtables"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ exe binary-visitor-test
|
|||||||
.//chrono
|
.//chrono
|
||||||
:
|
:
|
||||||
<include>$(BOOST_DIR)/include
|
<include>$(BOOST_DIR)/include
|
||||||
<include>./
|
<include>./include
|
||||||
|
<include>./test/include
|
||||||
<variant>release:<cxxflags>-march=native
|
<variant>release:<cxxflags>-march=native
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -43,7 +45,8 @@ exe recursive-wrapper-test
|
|||||||
.//chrono
|
.//chrono
|
||||||
:
|
:
|
||||||
<include>$(BOOST_DIR)/include
|
<include>$(BOOST_DIR)/include
|
||||||
<include>./
|
<include>./include
|
||||||
|
<include>./test/include
|
||||||
<variant>release:<cxxflags>-march=native
|
<variant>release:<cxxflags>-march=native
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -55,7 +58,8 @@ exe unique-ptr-test
|
|||||||
.//chrono
|
.//chrono
|
||||||
:
|
:
|
||||||
<include>$(BOOST_DIR)/include
|
<include>$(BOOST_DIR)/include
|
||||||
<include>./
|
<include>./include
|
||||||
|
<include>./test/include
|
||||||
<variant>release:<cxxflags>-march=native
|
<variant>release:<cxxflags>-march=native
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -68,6 +72,7 @@ exe reference_wrapper_test
|
|||||||
.//chrono
|
.//chrono
|
||||||
:
|
:
|
||||||
<include>$(BOOST_DIR)/include
|
<include>$(BOOST_DIR)/include
|
||||||
<include>./
|
<include>./include
|
||||||
|
<include>./test/include
|
||||||
<variant>release:<cxxflags>-march=native
|
<variant>release:<cxxflags>-march=native
|
||||||
;
|
;
|
||||||
|
77
third_party/variant/Makefile
vendored
77
third_party/variant/Makefile
vendored
@ -1,32 +1,23 @@
|
|||||||
|
MASON = .mason/mason
|
||||||
|
BOOST_VERSION = boost 1.60.0
|
||||||
|
|
||||||
CXX := $(CXX)
|
CXX := $(CXX)
|
||||||
CXX_STD ?= c++11
|
CXX_STD ?= c++11
|
||||||
|
|
||||||
BOOST_LIBS = -lboost_timer -lboost_system -lboost_chrono
|
BOOST_FLAGS = `$(MASON) cflags $(BOOST_VERSION)`
|
||||||
RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden
|
RELEASE_FLAGS = -O3 -DNDEBUG -march=native -DSINGLE_THREADED -fvisibility-inlines-hidden
|
||||||
DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions
|
DEBUG_FLAGS = -O0 -g -DDEBUG -fno-inline-functions
|
||||||
COMMON_FLAGS = -Wall -pedantic -Wextra -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -std=$(CXX_STD)
|
COMMON_FLAGS = -Wall -pedantic -Wextra -Wsign-compare -Wsign-conversion -Wshadow -Wunused-parameter -std=$(CXX_STD)
|
||||||
CXXFLAGS := $(CXXFLAGS)
|
CXXFLAGS := $(CXXFLAGS)
|
||||||
LDFLAGS := $(LDFLAGS)
|
LDFLAGS := $(LDFLAGS)
|
||||||
|
|
||||||
OS:=$(shell uname -s)
|
ALL_HEADERS = $(shell find include/mapbox/ '(' -name '*.hpp' ')')
|
||||||
ifeq ($(OS),Darwin)
|
|
||||||
CXXFLAGS += -stdlib=libc++
|
|
||||||
LDFLAGS += -stdlib=libc++ -F/ -framework CoreFoundation
|
|
||||||
else
|
|
||||||
BOOST_LIBS += -lrt
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq (sizes,$(firstword $(MAKECMDGOALS)))
|
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
|
||||||
RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
|
|
||||||
$(eval $(RUN_ARGS):;@:)
|
|
||||||
ifndef RUN_ARGS
|
|
||||||
$(error sizes target requires you pass full path to boost variant.hpp)
|
|
||||||
endif
|
|
||||||
.PHONY: $(RUN_ARGS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_wrapper_test out/binary_visitor_test
|
mason_packages:
|
||||||
|
git submodule update --init .mason
|
||||||
|
$(MASON) install $(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
|
||||||
@ -36,25 +27,33 @@ gyp: ./deps/gyp
|
|||||||
make V=1 -C ./out tests
|
make V=1 -C ./out tests
|
||||||
./out/Release/tests
|
./out/Release/tests
|
||||||
|
|
||||||
out/bench-variant-debug: Makefile test/bench_variant.cpp variant.hpp recursive_wrapper.hpp
|
out/bench-variant-debug: Makefile mason_packages test/bench_variant.cpp
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./ -pthreads $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS)
|
$(CXX) -o out/bench-variant-debug test/bench_variant.cpp -I./include -Itest/include -pthreads $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
|
||||||
|
|
||||||
out/bench-variant: Makefile test/bench_variant.cpp variant.hpp recursive_wrapper.hpp
|
out/bench-variant: Makefile mason_packages test/bench_variant.cpp
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS)
|
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
|
||||||
|
|
||||||
out/unique_ptr_test: Makefile test/unique_ptr_test.cpp variant.hpp recursive_wrapper.hpp
|
out/unique_ptr_test: Makefile mason_packages test/unique_ptr_test.cpp
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS)
|
$(CXX) -o out/unique_ptr_test test/unique_ptr_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
|
||||||
|
|
||||||
out/recursive_wrapper_test: Makefile test/recursive_wrapper_test.cpp variant.hpp recursive_wrapper.hpp
|
out/recursive_wrapper_test: Makefile mason_packages test/recursive_wrapper_test.cpp
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS)
|
$(CXX) -o out/recursive_wrapper_test test/recursive_wrapper_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
|
||||||
|
|
||||||
out/binary_visitor_test: Makefile test/binary_visitor_test.cpp variant.hpp variant_io.hpp recursive_wrapper.hpp
|
out/binary_visitor_test: Makefile mason_packages test/binary_visitor_test.cpp
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS)
|
$(CXX) -o out/binary_visitor_test test/binary_visitor_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS)
|
||||||
|
|
||||||
|
out/lambda_overload_test: Makefile mason_packages test/lambda_overload_test.cpp
|
||||||
|
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)
|
||||||
|
|
||||||
|
out/hashable_test: Makefile mason_packages test/hashable_test.cpp
|
||||||
|
mkdir -p ./out
|
||||||
|
$(CXX) -o out/hashable_test test/hashable_test.cpp -I./include -Itest/include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(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
|
||||||
@ -66,11 +65,11 @@ 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 -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS)
|
||||||
|
|
||||||
out/%.o: test/t/%.cpp Makefile optional.hpp recursive_wrapper.hpp variant.hpp variant_io.hpp
|
out/%.o: test/t/%.cpp Makefile $(ALL_HEADERS)
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
$(CXX) -c -o $@ $< -I. -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS)
|
$(CXX) -c -o $@ $< -Iinclude -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(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/mutating_visitor.o out/optional.o out/recursive_wrapper.o out/sizeof.o out/unary_visitor.o out/variant.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)
|
||||||
|
|
||||||
@ -79,14 +78,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./ -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS)
|
$(CXX) -o out/cov-test --coverage test/unit.cpp test/t/*.cpp -I./include -Itest/include $(DEBUG_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS)
|
||||||
|
|
||||||
sizes: Makefile variant.hpp recursive_wrapper.hpp
|
sizes: Makefile
|
||||||
mkdir -p ./out
|
mkdir -p ./out
|
||||||
@$(CXX) -o ./out/our_variant_hello_world.out variant.hpp $(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 $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world.out
|
||||||
@$(CXX) -o ./out/boost_variant_hello_world.out $(RUN_ARGS) $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_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/our_variant_hello_world ./test/our_variant_hello_world.cpp -I./ $(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 $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/our_variant_hello_world
|
||||||
@$(CXX) -o ./out/boost_variant_hello_world ./test/boost_variant_hello_world.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) && du -h ./out/boost_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
|
||||||
|
|
||||||
profile: out/bench-variant-debug
|
profile: out/bench-variant-debug
|
||||||
mkdir -p profiling/
|
mkdir -p profiling/
|
||||||
@ -102,9 +101,9 @@ clean:
|
|||||||
rm -f test/*gcov
|
rm -f test/*gcov
|
||||||
rm -f *.gcda *.gcno
|
rm -f *.gcda *.gcno
|
||||||
|
|
||||||
pgo: out Makefile variant.hpp recursive_wrapper.hpp
|
pgo: out Makefile
|
||||||
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -pg -fprofile-generate
|
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(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./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_LIBS) -fprofile-use
|
$(CXX) -o out/bench-variant test/bench_variant.cpp -I./include $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS) $(BOOST_FLAGS) -fprofile-use
|
||||||
|
|
||||||
.PHONY: sizes test
|
.PHONY: sizes test
|
||||||
|
181
third_party/variant/README.md
vendored
181
third_party/variant/README.md
vendored
@ -1,11 +1,169 @@
|
|||||||
# Mapbox Variant
|
# Mapbox Variant
|
||||||
|
|
||||||
An alternative to `boost::variant` for C++11.
|
An header-only alternative to `boost::variant` for C++11 and C++14
|
||||||
|
|
||||||
[](https://travis-ci.org/mapbox/variant)
|
[](https://travis-ci.org/mapbox/variant)
|
||||||
[](https://ci.appveyor.com/project/Mapbox/variant)
|
[](https://ci.appveyor.com/project/Mapbox/variant)
|
||||||
[](https://coveralls.io/r/mapbox/variant?branch=master)
|
[](https://coveralls.io/r/mapbox/variant?branch=master)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Variant's basic building blocks are:
|
||||||
|
- `variant<Ts...>` - a type-safe representation for sum-types / discriminated unions
|
||||||
|
- `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
|
||||||
|
- `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
|
||||||
|
|
||||||
|
|
||||||
|
### Basic Usage - HTTP API Example
|
||||||
|
|
||||||
|
Suppose you want to represent a HTTP API response which is either a JSON result or an error:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct Result {
|
||||||
|
Json object;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Error {
|
||||||
|
int32_t code;
|
||||||
|
string message;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
You can represent this at type level using a variant which is either an `Error` or a `Result`:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
using Response = variant<Error, Result>;
|
||||||
|
|
||||||
|
Response makeRequest() {
|
||||||
|
return Error{501, "Not Implemented"};
|
||||||
|
}
|
||||||
|
|
||||||
|
Response ret = makeRequest();
|
||||||
|
```
|
||||||
|
|
||||||
|
To see which type the `Response` holds you pattern match on the variant unwrapping the underlying value:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
ret.match([] (Result r) { print(r.object); }
|
||||||
|
[] (Error e) { print(e.message); });
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of using the variant's convenience `.match` pattern matching function you can create a type visitor functor and use `apply_visitor` manually:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct ResponseVisitor {
|
||||||
|
void operator()(Result r) const {
|
||||||
|
print(r.object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(Error e) const {
|
||||||
|
print(e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseVisitor visitor;
|
||||||
|
apply_visitor(visitor, ret);
|
||||||
|
```
|
||||||
|
|
||||||
|
In both cases the compiler makes sure you handle all types the variant can represent at compile.
|
||||||
|
|
||||||
|
|
||||||
|
### Recursive Variants - JSON Example
|
||||||
|
|
||||||
|
[JSON](http://www.json.org/) consists of types `String`, `Number`, `True`, `False`, `Null`, `Array` and `Object`.
|
||||||
|
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct String { string value; };
|
||||||
|
struct Number { double value; };
|
||||||
|
struct True { };
|
||||||
|
struct False { };
|
||||||
|
struct Null { };
|
||||||
|
struct Array { vector<?> values; };
|
||||||
|
struct Object { unordered_map<string, ?> values; };
|
||||||
|
```
|
||||||
|
|
||||||
|
This works for primitive types but how do we represent recursive types such as `Array` which can hold multiple elements and `Array` itself, too?
|
||||||
|
|
||||||
|
For these use cases Variant provides a `recursive_wrapper` helper type which lets you express recursive Variants.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct String { string value; };
|
||||||
|
struct Number { double value; };
|
||||||
|
struct True { };
|
||||||
|
struct False { };
|
||||||
|
struct Null { };
|
||||||
|
|
||||||
|
// Forward declarations only
|
||||||
|
struct Array;
|
||||||
|
struct Object;
|
||||||
|
|
||||||
|
using Value = variant<String, Number, True, False, Null, recursive_wrapper<Array>, recursive_wrapper<Object>>;
|
||||||
|
|
||||||
|
struct Array {
|
||||||
|
vector<Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Object {
|
||||||
|
unordered_map<string, Value> values;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
For walkig the JSON representation you can again either create a `JSONVisitor`:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct JSONVisitor {
|
||||||
|
|
||||||
|
void operator()(Null) const {
|
||||||
|
print("null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// same for all other JSON types
|
||||||
|
};
|
||||||
|
|
||||||
|
JSONVisitor visitor;
|
||||||
|
apply_visitor(visitor, json);
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use the convenience `.match` pattern matching function:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
json.match([] (Null) { print("null"); },
|
||||||
|
...);
|
||||||
|
```
|
||||||
|
|
||||||
|
To summarize: use `recursive_wrapper` to represent recursive "tree-like" representations:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct Empty { };
|
||||||
|
struct Node;
|
||||||
|
|
||||||
|
using Tree = variant<Empty, recursive_wrapper<Node>>;
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
uint64_t value;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Advanced Usage Tips
|
||||||
|
|
||||||
|
Creating type aliases for variants is a great way to reduce repetition.
|
||||||
|
Keep in mind those type aliases are not checked at type level, though.
|
||||||
|
We recommend creating a new type for all but basic variant usage:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// the compiler can't tell the following two apart
|
||||||
|
using APIResult = variant<Error, Result>;
|
||||||
|
using FilesystemResult = variant<Error, Result>;
|
||||||
|
|
||||||
|
// new type
|
||||||
|
struct APIResult : variant<Error, Result> {
|
||||||
|
using Base = variant<Error, Result>;
|
||||||
|
using Base::Base;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Why use Mapbox Variant?
|
## Why use Mapbox Variant?
|
||||||
|
|
||||||
@ -45,6 +203,9 @@ implementations](doc/other_implementations.md).
|
|||||||
Want to know more about the upcoming standard? Have a look at our
|
Want to know more about the upcoming standard? Have a look at our
|
||||||
[overview](doc/standards_effort.md).
|
[overview](doc/standards_effort.md).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
## Depends
|
## Depends
|
||||||
|
|
||||||
@ -55,19 +216,14 @@ Tested with:
|
|||||||
- g++-4.7
|
- g++-4.7
|
||||||
- g++-4.8
|
- g++-4.8
|
||||||
- g++-4.9
|
- g++-4.9
|
||||||
- g++-5
|
- g++-5.2
|
||||||
- clang++-3.5
|
- clang++-3.5
|
||||||
- clang++-3.6
|
- clang++-3.6
|
||||||
- clang++-3.7
|
- clang++-3.7
|
||||||
- clang++-3.8
|
- clang++-3.8
|
||||||
|
- clang++-3.9
|
||||||
- Visual Studio 2015
|
- Visual Studio 2015
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
There is nothing to build, just include `variant.hpp` and
|
|
||||||
`recursive_wrapper.hpp` in your project. Include `variant_io.hpp` if you need
|
|
||||||
the `operator<<` overload for variant.
|
|
||||||
|
|
||||||
|
|
||||||
## Unit Tests
|
## Unit Tests
|
||||||
|
|
||||||
@ -93,15 +249,6 @@ On Windows run `scripts/build-local.bat`.
|
|||||||
|
|
||||||
## Benchmarks
|
## Benchmarks
|
||||||
|
|
||||||
The benchmarks depend on:
|
|
||||||
|
|
||||||
- Boost headers (for benchmarking against `boost::variant`)
|
|
||||||
- Boost built with `--with-timer` (used for benchmark timing)
|
|
||||||
|
|
||||||
On Unix systems set your boost includes and libs locations and run `make test`:
|
|
||||||
|
|
||||||
export LDFLAGS='-L/opt/boost/lib'
|
|
||||||
export CXXFLAGS='-I/opt/boost/include'
|
|
||||||
make bench
|
make bench
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
namespace mapbox {
|
namespace mapbox {
|
||||||
namespace util {
|
namespace util {
|
@ -42,9 +42,9 @@ class recursive_wrapper
|
|||||||
* @throws any exception thrown by the default constructur of T.
|
* @throws any exception thrown by the default constructur of T.
|
||||||
*/
|
*/
|
||||||
recursive_wrapper()
|
recursive_wrapper()
|
||||||
: p_(new T){};
|
: p_(new T){}
|
||||||
|
|
||||||
~recursive_wrapper() noexcept { delete p_; };
|
~recursive_wrapper() noexcept { delete p_; }
|
||||||
|
|
||||||
recursive_wrapper(recursive_wrapper const& operand)
|
recursive_wrapper(recursive_wrapper const& operand)
|
||||||
: p_(new T(operand.get())) {}
|
: p_(new T(operand.get())) {}
|
@ -10,8 +10,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "recursive_wrapper.hpp"
|
#include <mapbox/recursive_wrapper.hpp>
|
||||||
|
#include <mapbox/variant_visitor.hpp>
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// [[deprecated]] is only available in C++14, use this for the time being
|
// [[deprecated]] is only available in C++14, use this for the time being
|
||||||
@ -33,17 +35,22 @@
|
|||||||
# ifdef NDEBUG
|
# ifdef NDEBUG
|
||||||
# define VARIANT_INLINE __forceinline
|
# define VARIANT_INLINE __forceinline
|
||||||
# else
|
# else
|
||||||
#define VARIANT_INLINE __declspec(noinline)
|
# define VARIANT_INLINE //__declspec(noinline)
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# ifdef NDEBUG
|
# ifdef NDEBUG
|
||||||
#define VARIANT_INLINE inline __attribute__((always_inline))
|
# define VARIANT_INLINE //inline __attribute__((always_inline))
|
||||||
# else
|
# else
|
||||||
# define VARIANT_INLINE __attribute__((noinline))
|
# define VARIANT_INLINE __attribute__((noinline))
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
// Exceptions
|
||||||
|
#if defined( __EXCEPTIONS) || defined( _MSC_VER)
|
||||||
|
#define HAS_EXCEPTIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VARIANT_MAJOR_VERSION 1
|
#define VARIANT_MAJOR_VERSION 1
|
||||||
#define VARIANT_MINOR_VERSION 1
|
#define VARIANT_MINOR_VERSION 1
|
||||||
#define VARIANT_PATCH_VERSION 0
|
#define VARIANT_PATCH_VERSION 0
|
||||||
@ -98,6 +105,26 @@ struct direct_type<T>
|
|||||||
static constexpr std::size_t index = invalid_value;
|
static constexpr std::size_t index = invalid_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if __cpp_lib_logical_traits >= 201510L
|
||||||
|
|
||||||
|
using std::disjunction;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
template <typename...>
|
||||||
|
struct disjunction : std::false_type {};
|
||||||
|
|
||||||
|
template <typename B1>
|
||||||
|
struct disjunction<B1> : B1 {};
|
||||||
|
|
||||||
|
template <typename B1, typename B2>
|
||||||
|
struct disjunction<B1, B2> : std::conditional<B1::value, B1, B2>::type {};
|
||||||
|
|
||||||
|
template <typename B1, typename... Bs>
|
||||||
|
struct disjunction<B1, Bs...> : std::conditional<B1::value, B1, disjunction<Bs...>>::type {};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T, typename... Types>
|
template <typename T, typename... Types>
|
||||||
struct convertible_type;
|
struct convertible_type;
|
||||||
|
|
||||||
@ -105,7 +132,7 @@ 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 std::size_t index = std::is_convertible<T, First>::value
|
||||||
? sizeof...(Types)
|
? disjunction<std::is_convertible<T, Types>...>::value ? invalid_value : sizeof...(Types)
|
||||||
: convertible_type<T, Types...>::index;
|
: convertible_type<T, Types...>::index;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -118,7 +145,7 @@ struct convertible_type<T>
|
|||||||
template <typename T, typename... Types>
|
template <typename T, typename... Types>
|
||||||
struct value_traits
|
struct value_traits
|
||||||
{
|
{
|
||||||
using value_type = typename std::remove_reference<T>::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;
|
static constexpr std::size_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 std::size_t index = is_direct ? direct_index : convertible_type<value_type, Types...>::index;
|
||||||
@ -127,35 +154,6 @@ struct value_traits
|
|||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
// check if T is in Types...
|
|
||||||
template <typename T, typename... Types>
|
|
||||||
struct has_type;
|
|
||||||
|
|
||||||
template <typename T, typename First, typename... Types>
|
|
||||||
struct has_type<T, First, Types...>
|
|
||||||
{
|
|
||||||
static constexpr bool value = std::is_same<T, First>::value || has_type<T, Types...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct has_type<T> : std::false_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename... Types>
|
|
||||||
struct is_valid_type;
|
|
||||||
|
|
||||||
template <typename T, typename First, typename... Types>
|
|
||||||
struct is_valid_type<T, First, Types...>
|
|
||||||
{
|
|
||||||
static constexpr bool value = std::is_convertible<T, First>::value || is_valid_type<T, Types...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct is_valid_type<T> : std::false_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename R = void>
|
template <typename T, typename R = void>
|
||||||
struct enable_if_type
|
struct enable_if_type
|
||||||
{
|
{
|
||||||
@ -299,7 +297,7 @@ struct dispatcher<F, V, R, T, Types...>
|
|||||||
{
|
{
|
||||||
if (v.template is<T>())
|
if (v.template is<T>())
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply_const(v.template get<T>()));
|
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -311,7 +309,7 @@ struct dispatcher<F, V, R, T, Types...>
|
|||||||
{
|
{
|
||||||
if (v.template is<T>())
|
if (v.template is<T>())
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply(v.template get<T>()));
|
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -325,12 +323,12 @@ struct dispatcher<F, V, R, T>
|
|||||||
{
|
{
|
||||||
VARIANT_INLINE static R apply_const(V const& v, F&& f)
|
VARIANT_INLINE static R apply_const(V const& v, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply_const(v.template get<T>()));
|
return f(unwrapper<T>::apply_const(v.template get_unchecked<T>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIANT_INLINE static R apply(V& v, F&& f)
|
VARIANT_INLINE static R apply(V& v, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply(v.template get<T>()));
|
return f(unwrapper<T>::apply(v.template get_unchecked<T>()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -344,8 +342,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
|
|||||||
{
|
{
|
||||||
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<T0>()),
|
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
|
||||||
unwrapper<T1>::apply_const(rhs.template get<T1>()));
|
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -357,8 +355,8 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1, Types...>
|
|||||||
{
|
{
|
||||||
if (rhs.template is<T1>()) // call binary functor
|
if (rhs.template is<T1>()) // call binary functor
|
||||||
{
|
{
|
||||||
return f(unwrapper<T0>::apply(lhs.template get<T0>()),
|
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
|
||||||
unwrapper<T1>::apply(rhs.template get<T1>()));
|
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -372,14 +370,14 @@ struct binary_dispatcher_rhs<F, V, R, T0, T1>
|
|||||||
{
|
{
|
||||||
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T0>::apply_const(lhs.template get<T0>()),
|
return f(unwrapper<T0>::apply_const(lhs.template get_unchecked<T0>()),
|
||||||
unwrapper<T1>::apply_const(rhs.template get<T1>()));
|
unwrapper<T1>::apply_const(rhs.template get_unchecked<T1>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T0>::apply(lhs.template get<T0>()),
|
return f(unwrapper<T0>::apply(lhs.template get_unchecked<T0>()),
|
||||||
unwrapper<T1>::apply(rhs.template get<T1>()));
|
unwrapper<T1>::apply(rhs.template get_unchecked<T1>()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -393,8 +391,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
|
|||||||
{
|
{
|
||||||
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<T1>()),
|
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
|
||||||
unwrapper<T0>::apply_const(rhs.template get<T0>()));
|
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -406,8 +404,8 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1, Types...>
|
|||||||
{
|
{
|
||||||
if (lhs.template is<T1>()) // call binary functor
|
if (lhs.template is<T1>()) // call binary functor
|
||||||
{
|
{
|
||||||
return f(unwrapper<T1>::apply(lhs.template get<T1>()),
|
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
|
||||||
unwrapper<T0>::apply(rhs.template get<T0>()));
|
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -421,14 +419,14 @@ struct binary_dispatcher_lhs<F, V, R, T0, T1>
|
|||||||
{
|
{
|
||||||
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T1>::apply_const(lhs.template get<T1>()),
|
return f(unwrapper<T1>::apply_const(lhs.template get_unchecked<T1>()),
|
||||||
unwrapper<T0>::apply_const(rhs.template get<T0>()));
|
unwrapper<T0>::apply_const(rhs.template get_unchecked<T0>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T1>::apply(lhs.template get<T1>()),
|
return f(unwrapper<T1>::apply(lhs.template get_unchecked<T1>()),
|
||||||
unwrapper<T0>::apply(rhs.template get<T0>()));
|
unwrapper<T0>::apply(rhs.template get_unchecked<T0>()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -444,8 +442,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
|
|||||||
{
|
{
|
||||||
if (v1.template is<T>())
|
if (v1.template is<T>())
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply_const(v0.template get<T>()),
|
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
|
||||||
unwrapper<T>::apply_const(v1.template get<T>())); // call binary functor
|
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -465,8 +463,8 @@ struct binary_dispatcher<F, V, R, T, Types...>
|
|||||||
{
|
{
|
||||||
if (v1.template is<T>())
|
if (v1.template is<T>())
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply(v0.template get<T>()),
|
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
|
||||||
unwrapper<T>::apply(v1.template get<T>())); // call binary functor
|
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -486,14 +484,14 @@ struct binary_dispatcher<F, V, R, T>
|
|||||||
{
|
{
|
||||||
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
|
VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply_const(v0.template get<T>()),
|
return f(unwrapper<T>::apply_const(v0.template get_unchecked<T>()),
|
||||||
unwrapper<T>::apply_const(v1.template get<T>())); // call binary functor
|
unwrapper<T>::apply_const(v1.template get_unchecked<T>())); // call binary functor
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
|
VARIANT_INLINE static R apply(V& v0, V& v1, F&& f)
|
||||||
{
|
{
|
||||||
return f(unwrapper<T>::apply(v0.template get<T>()),
|
return f(unwrapper<T>::apply(v0.template get_unchecked<T>()),
|
||||||
unwrapper<T>::apply(v1.template get<T>())); // call binary functor
|
unwrapper<T>::apply(v1.template get_unchecked<T>())); // call binary functor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -527,7 +525,7 @@ class comparer
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator()(T const& rhs_content) const
|
bool operator()(T const& rhs_content) const
|
||||||
{
|
{
|
||||||
T const& lhs_content = lhs_.template get<T>();
|
T const& lhs_content = lhs_.template get_unchecked<T>();
|
||||||
return Comp()(lhs_content, rhs_content);
|
return Comp()(lhs_content, rhs_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,18 +533,14 @@ class comparer
|
|||||||
Variant const& lhs_;
|
Variant const& lhs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// True if Predicate matches for all of the types Ts
|
// hashing visitor
|
||||||
template <template <typename> class Predicate, typename... Ts>
|
struct hasher
|
||||||
struct static_all_of : std::is_same<std::tuple<std::true_type, typename Predicate<Ts>::type...>,
|
|
||||||
std::tuple<typename Predicate<Ts>::type..., std::true_type>>
|
|
||||||
{
|
{
|
||||||
};
|
template <typename T>
|
||||||
|
std::size_t operator()(const T& hashable) const
|
||||||
// True if Predicate matches for none of the types Ts
|
|
||||||
template <template <typename> class Predicate, typename... Ts>
|
|
||||||
struct static_none_of : std::is_same<std::tuple<std::false_type, typename Predicate<Ts>::type...>,
|
|
||||||
std::tuple<typename Predicate<Ts>::type..., std::false_type>>
|
|
||||||
{
|
{
|
||||||
|
return std::hash<T>{}(hashable);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -559,13 +553,16 @@ 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::static_none_of<std::is_reference, Types...>::value, "Variant can not hold reference types. Maybe use std::reference?");
|
static_assert(!detail::disjunction<std::is_reference<Types>...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?");
|
||||||
|
|
||||||
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;
|
||||||
|
public:
|
||||||
using first_type = typename std::tuple_element<0, std::tuple<Types...>>::type;
|
struct adapted_variant_tag;
|
||||||
|
using types = std::tuple<Types...>;
|
||||||
|
private:
|
||||||
|
using first_type = typename std::tuple_element<0, types>::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...>;
|
||||||
|
|
||||||
@ -585,7 +582,7 @@ class variant
|
|||||||
|
|
||||||
// http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
|
// http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
|
||||||
template <typename T, typename Traits = detail::value_traits<T, Types...>,
|
template <typename T, typename Traits = detail::value_traits<T, Types...>,
|
||||||
typename Enable = typename std::enable_if<Traits::is_valid>::type>
|
typename Enable = typename std::enable_if<Traits::is_valid && !std::is_same<variant<Types...>, typename Traits::value_type>::value>::type >
|
||||||
VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
|
VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible<typename Traits::target_type, T&&>::value)
|
||||||
: type_index(Traits::index)
|
: type_index(Traits::index)
|
||||||
{
|
{
|
||||||
@ -598,7 +595,7 @@ class variant
|
|||||||
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<std::tuple<Types...>>::value)
|
VARIANT_INLINE variant(variant<Types...>&& old) noexcept(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);
|
||||||
@ -653,13 +650,20 @@ class variant
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
VARIANT_INLINE bool is() const
|
VARIANT_INLINE bool is() const
|
||||||
{
|
{
|
||||||
static_assert(detail::has_type<T, Types...>::value, "invalid type in T in `is<T>()` for this variant");
|
|
||||||
return type_index == detail::direct_type<T, Types...>::index;
|
return type_index == detail::direct_type<T, Types...>::index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T,typename std::enable_if<
|
||||||
|
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE bool is() const
|
||||||
|
{
|
||||||
|
return type_index == detail::direct_type<recursive_wrapper<T>, Types...>::index;
|
||||||
|
}
|
||||||
|
|
||||||
VARIANT_INLINE bool valid() const
|
VARIANT_INLINE bool valid() const
|
||||||
{
|
{
|
||||||
return type_index != detail::invalid_value;
|
return type_index != detail::invalid_value;
|
||||||
@ -674,6 +678,15 @@ class variant
|
|||||||
type_index = detail::direct_type<T, Types...>::index;
|
type_index = detail::direct_type<T, Types...>::index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_unchecked<T>()
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T& get_unchecked()
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<T*>(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
// get<T>()
|
// get<T>()
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
@ -688,7 +701,16 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T const& get_unchecked() const
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<T const*>(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
VARIANT_INLINE T const& get() const
|
VARIANT_INLINE T const& get() const
|
||||||
@ -702,7 +724,17 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// get_unchecked<T>() - T stored as recursive_wrapper<T>
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T& get_unchecked()
|
||||||
|
{
|
||||||
|
return (*reinterpret_cast<recursive_wrapper<T>*>(&data)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
// get<T>() - T stored as recursive_wrapper<T>
|
// get<T>() - T stored as recursive_wrapper<T>
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
@ -717,7 +749,16 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T const& get_unchecked() const
|
||||||
|
{
|
||||||
|
return (*reinterpret_cast<recursive_wrapper<T> const*>(&data)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<recursive_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
VARIANT_INLINE T const& get() const
|
VARIANT_INLINE T const& get() const
|
||||||
@ -731,7 +772,17 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// get_unchecked<T>() - T stored as std::reference_wrapper<T>
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T& get_unchecked()
|
||||||
|
{
|
||||||
|
return (*reinterpret_cast<std::reference_wrapper<T>*>(&data)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
// get<T>() - T stored as std::reference_wrapper<T>
|
// get<T>() - T stored as std::reference_wrapper<T>
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<std::reference_wrapper<T>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
@ -746,7 +797,16 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE T const& get_unchecked() const
|
||||||
|
{
|
||||||
|
return (*reinterpret_cast<std::reference_wrapper<T const> const*>(&data)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
template <typename T, typename std::enable_if<
|
template <typename T, typename std::enable_if<
|
||||||
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
(detail::direct_type<std::reference_wrapper<T const>, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
VARIANT_INLINE T const& get() const
|
VARIANT_INLINE T const& get() const
|
||||||
@ -760,6 +820,7 @@ class variant
|
|||||||
throw bad_variant_access("in get<T>()");
|
throw bad_variant_access("in get<T>()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// 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.
|
||||||
@ -773,6 +834,13 @@ class variant
|
|||||||
return static_cast<int>(sizeof...(Types)-type_index - 1);
|
return static_cast<int>(sizeof...(Types)-type_index - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename std::enable_if<
|
||||||
|
(detail::direct_type<T, Types...>::index != detail::invalid_value)>::type* = nullptr>
|
||||||
|
VARIANT_INLINE static constexpr int which() noexcept
|
||||||
|
{
|
||||||
|
return static_cast<int>(sizeof...(Types)-detail::direct_type<T, Types...>::index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// 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 R = typename detail::result_of_unary_visit<F, first_type>::type>
|
||||||
@ -805,6 +873,22 @@ class variant
|
|||||||
return 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
|
||||||
|
// unary
|
||||||
|
template <typename... Fs>
|
||||||
|
auto VARIANT_INLINE match(Fs&&... fs) const
|
||||||
|
-> decltype(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
|
||||||
|
template <typename... Fs>
|
||||||
|
auto VARIANT_INLINE match(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)...));
|
||||||
|
}
|
||||||
|
|
||||||
~variant() noexcept // no-throw destructor
|
~variant() noexcept // no-throw destructor
|
||||||
{
|
{
|
||||||
helper_type::destroy(type_index, &data);
|
helper_type::destroy(type_index, &data);
|
||||||
@ -884,18 +968,46 @@ auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_vis
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getter interface
|
// getter interface
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
template <typename ResultType, typename T>
|
template <typename ResultType, typename T>
|
||||||
ResultType& get(T& var)
|
auto get(T& var)->decltype(var.template get<ResultType>())
|
||||||
{
|
{
|
||||||
return var.template get<ResultType>();
|
return var.template get<ResultType>();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename ResultType, typename T>
|
template <typename ResultType, typename T>
|
||||||
ResultType const& get(T const& var)
|
ResultType& get_unchecked(T& var)
|
||||||
|
{
|
||||||
|
return var.template get_unchecked<ResultType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_EXCEPTIONS
|
||||||
|
template <typename ResultType, typename T>
|
||||||
|
auto get(T const& var)->decltype(var.template get<ResultType>())
|
||||||
{
|
{
|
||||||
return var.template get<ResultType>();
|
return var.template get<ResultType>();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename ResultType, typename T>
|
||||||
|
ResultType const& get_unchecked(T const& var)
|
||||||
|
{
|
||||||
|
return var.template get_unchecked<ResultType>();
|
||||||
|
}
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace mapbox
|
} // namespace mapbox
|
||||||
|
|
||||||
|
// hashable iff underlying types are hashable
|
||||||
|
namespace std {
|
||||||
|
template <typename... Types>
|
||||||
|
struct hash< ::mapbox::util::variant<Types...>> {
|
||||||
|
std::size_t operator()(const ::mapbox::util::variant<Types...>& v) const noexcept
|
||||||
|
{
|
||||||
|
return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MAPBOX_UTIL_VARIANT_HPP
|
#endif // MAPBOX_UTIL_VARIANT_HPP
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
namespace mapbox {
|
namespace mapbox {
|
||||||
namespace util {
|
namespace util {
|
38
third_party/variant/include/mapbox/variant_visitor.hpp
vendored
Normal file
38
third_party/variant/include/mapbox/variant_visitor.hpp
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||||
|
#define MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
||||||
|
|
||||||
|
namespace mapbox {
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
template <typename... Fns>
|
||||||
|
struct visitor;
|
||||||
|
|
||||||
|
template <typename Fn>
|
||||||
|
struct visitor<Fn> : Fn
|
||||||
|
{
|
||||||
|
using type = Fn;
|
||||||
|
using Fn::operator();
|
||||||
|
|
||||||
|
visitor(Fn fn) : Fn(fn) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Fn, typename... Fns>
|
||||||
|
struct visitor<Fn, Fns...> : Fn, visitor<Fns...>
|
||||||
|
{
|
||||||
|
using type = visitor;
|
||||||
|
using Fn::operator();
|
||||||
|
using visitor<Fns...>::operator();
|
||||||
|
|
||||||
|
visitor(Fn fn, Fns... fns) : Fn(fn), visitor<Fns...>(fns...) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Fns>
|
||||||
|
visitor<Fns...> make_visitor(Fns... fns)
|
||||||
|
{
|
||||||
|
return visitor<Fns...>(fns...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
} // namespace mapbox
|
||||||
|
|
||||||
|
#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP
|
@ -22,7 +22,7 @@ exit_code=0
|
|||||||
for test_code in $DIR/*.cpp; do
|
for test_code in $DIR/*.cpp; do
|
||||||
name=`basename $test_code .cpp`
|
name=`basename $test_code .cpp`
|
||||||
|
|
||||||
result=`${CXX} -std=c++11 -c -o /dev/null -I. ${CXXFLAGS} ${test_code} 2>&1`
|
result=`${CXX} -std=c++11 -c -o /dev/null -I./include ${CXXFLAGS} ${test_code} 2>&1`
|
||||||
status=$?
|
status=$?
|
||||||
|
|
||||||
if [ $status = 1 ]; then
|
if [ $status = 1 ]; then
|
||||||
@ -47,4 +47,3 @@ for test_code in $DIR/*.cpp; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
exit ${exit_code}
|
exit ${exit_code}
|
||||||
|
|
||||||
|
15
third_party/variant/test/bench_variant.cpp
vendored
15
third_party/variant/test/bench_variant.cpp
vendored
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -8,10 +7,10 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/timer/timer.hpp>
|
#include "auto_cpu_timer.hpp"
|
||||||
#include <boost/variant.hpp>
|
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <boost/variant.hpp>
|
||||||
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define TEXT_SHORT "Test"
|
#define TEXT_SHORT "Test"
|
||||||
#define TEXT_LONG "Testing various variant implementations with a longish string ........................................."
|
#define TEXT_LONG "Testing various variant implementations with a longish string ........................................."
|
||||||
@ -140,12 +139,12 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::cerr << "custom variant: ";
|
std::cerr << "custom variant: ";
|
||||||
boost::timer::auto_cpu_timer t;
|
auto_cpu_timer t;
|
||||||
run_variant_test(NUM_RUNS);
|
run_variant_test(NUM_RUNS);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::cerr << "boost variant: ";
|
std::cerr << "boost variant: ";
|
||||||
boost::timer::auto_cpu_timer t;
|
auto_cpu_timer t;
|
||||||
run_boost_test(NUM_RUNS);
|
run_boost_test(NUM_RUNS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,7 +157,7 @@ int main(int argc, char** argv)
|
|||||||
typedef thread_group::value_type value_type;
|
typedef thread_group::value_type value_type;
|
||||||
thread_group tg;
|
thread_group tg;
|
||||||
std::cerr << "custom variant: ";
|
std::cerr << "custom variant: ";
|
||||||
boost::timer::auto_cpu_timer timer;
|
auto_cpu_timer timer;
|
||||||
for (std::size_t i = 0; i < THREADS; ++i)
|
for (std::size_t i = 0; i < THREADS; ++i)
|
||||||
{
|
{
|
||||||
tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
|
tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
|
||||||
@ -171,7 +170,7 @@ int main(int argc, char** argv)
|
|||||||
typedef thread_group::value_type value_type;
|
typedef thread_group::value_type value_type;
|
||||||
thread_group tg;
|
thread_group tg;
|
||||||
std::cerr << "boost variant: ";
|
std::cerr << "boost variant: ";
|
||||||
boost::timer::auto_cpu_timer timer;
|
auto_cpu_timer timer;
|
||||||
for (std::size_t i = 0; i < THREADS; ++i)
|
for (std::size_t i = 0; i < THREADS; ++i)
|
||||||
{
|
{
|
||||||
tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
|
tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
using namespace mapbox;
|
using namespace mapbox;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED: First type in variant must be default constructible to allow default construction of variant
|
// @EXPECTED: First type in variant must be default constructible to allow default construction of variant
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
// Checks that the first type in a variant must be default constructible to
|
// Checks that the first type in a variant must be default constructible to
|
||||||
// make the variant default constructible.
|
// make the variant default constructible.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED: Template parameter type list of variant can not be empty
|
// @EXPECTED: Template parameter type list of variant can not be empty
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
// Empty type list should not work.
|
// Empty type list should not work.
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED:
|
// @EXPECTED:
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED: enable_if
|
// @EXPECTED: enable_if
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
// @EXPECTED:
|
||||||
|
|
||||||
// @EXPECTED: invalid type in T in `is<T>()` for this variant
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#include <variant.hpp>
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED: const int
|
// @EXPECTED: const int
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
struct mutating_visitor
|
struct mutating_visitor
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
// @EXPECTED: Variant can not hold reference types
|
// @EXPECTED: Variant can not hold reference types
|
||||||
|
|
||||||
#include <variant.hpp>
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
158
third_party/variant/test/hashable_test.cpp
vendored
Normal file
158
third_party/variant/test/hashable_test.cpp
vendored
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
|
using namespace mapbox::util;
|
||||||
|
|
||||||
|
void test_singleton()
|
||||||
|
{
|
||||||
|
using V = variant<int>;
|
||||||
|
|
||||||
|
V singleton = 5;
|
||||||
|
|
||||||
|
if (std::hash<V>{}(singleton) != std::hash<int>{}(5))
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_default_hashable()
|
||||||
|
{
|
||||||
|
using V = variant<int, double, std::string>;
|
||||||
|
|
||||||
|
V var;
|
||||||
|
|
||||||
|
// Check int hashes
|
||||||
|
var = 1;
|
||||||
|
|
||||||
|
if (std::hash<V>{}(var) != std::hash<int>{}(1))
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check double hashes
|
||||||
|
var = 23.4;
|
||||||
|
|
||||||
|
if (std::hash<V>{}(var) != std::hash<double>{}(23.4))
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check string hashes
|
||||||
|
var = std::string{"Hello, World!"};
|
||||||
|
|
||||||
|
if (std::hash<V>{}(var) != std::hash<std::string>{}("Hello, World!"))
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Hashable
|
||||||
|
{
|
||||||
|
static const constexpr auto const_hash = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<Hashable>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const Hashable&) const noexcept
|
||||||
|
{
|
||||||
|
return Hashable::const_hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_custom_hasher()
|
||||||
|
{
|
||||||
|
using V = variant<int, Hashable, double>;
|
||||||
|
|
||||||
|
V var;
|
||||||
|
|
||||||
|
var = Hashable{};
|
||||||
|
|
||||||
|
if (std::hash<V>{}(var) != Hashable::const_hash)
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_hashable_in_container()
|
||||||
|
{
|
||||||
|
using V = variant<int, std::string, double>;
|
||||||
|
|
||||||
|
// won't compile if V is not Hashable
|
||||||
|
std::unordered_set<V> vs;
|
||||||
|
|
||||||
|
vs.insert(1);
|
||||||
|
vs.insert(2.3);
|
||||||
|
vs.insert("4");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Empty
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node;
|
||||||
|
|
||||||
|
using Tree = variant<Empty, recursive_wrapper<Node>>;
|
||||||
|
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
Node(Tree left_, Tree right_) : left(std::move(left_)), right(std::move(right_)) {}
|
||||||
|
|
||||||
|
Tree left = Empty{};
|
||||||
|
Tree right = Empty{};
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<Empty>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const Empty&) const noexcept
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<Node>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const Node& n) const noexcept
|
||||||
|
{
|
||||||
|
return 5 + std::hash<Tree>{}(n.left) + std::hash<Tree>{}(n.right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_recursive_hashable()
|
||||||
|
{
|
||||||
|
|
||||||
|
Tree tree = Node{Node{Empty{}, Empty{}}, Empty{}};
|
||||||
|
|
||||||
|
if (std::hash<Tree>{}(tree) != ((5 + (5 + (3 + 3))) + 3))
|
||||||
|
{
|
||||||
|
std::cerr << "Expected variant hash to be the same as hash of its value\n";
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_singleton();
|
||||||
|
test_default_hashable();
|
||||||
|
test_custom_hasher();
|
||||||
|
test_hashable_in_container();
|
||||||
|
test_recursive_hashable();
|
||||||
|
}
|
16
third_party/variant/test/include/auto_cpu_timer.hpp
vendored
Normal file
16
third_party/variant/test/include/auto_cpu_timer.hpp
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct auto_cpu_timer {
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> start;
|
||||||
|
auto_cpu_timer() : start(std::chrono::high_resolution_clock::now()) {
|
||||||
|
}
|
||||||
|
~auto_cpu_timer() {
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
std::chrono::microseconds elapsed =
|
||||||
|
std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||||
|
std::cerr << elapsed.count() << "us" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
127
third_party/variant/test/lambda_overload_test.cpp
vendored
Normal file
127
third_party/variant/test/lambda_overload_test.cpp
vendored
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <mapbox/variant.hpp>
|
||||||
|
#include <mapbox/variant_visitor.hpp>
|
||||||
|
|
||||||
|
#if __cplusplus >= 201402L
|
||||||
|
#define HAS_CPP14_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace mapbox::util;
|
||||||
|
|
||||||
|
template <typename Left, typename Right>
|
||||||
|
using Either = mapbox::util::variant<Left, Right>;
|
||||||
|
|
||||||
|
struct Response
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Error
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_lambda_overloads()
|
||||||
|
{
|
||||||
|
Either<Error, Response> rv;
|
||||||
|
|
||||||
|
rv = Response{};
|
||||||
|
|
||||||
|
auto visitor = make_visitor([](Response) { std::cout << "Response\n"; }, //
|
||||||
|
[](Error) { std::cout << "Error\n"; }); //
|
||||||
|
apply_visitor(visitor, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_lambda_overloads_capture()
|
||||||
|
{
|
||||||
|
Either<Error, Response> rv;
|
||||||
|
|
||||||
|
rv = Error{};
|
||||||
|
|
||||||
|
int ok = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
auto visitor = make_visitor([&](Response) { ok += 1; }, //
|
||||||
|
[&](Error) { err += 1; }); //
|
||||||
|
apply_visitor(visitor, rv);
|
||||||
|
|
||||||
|
std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_singleton_variant()
|
||||||
|
{
|
||||||
|
|
||||||
|
variant<int> singleton;
|
||||||
|
apply_visitor(make_visitor([](int) {}), singleton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_lambda_overloads_sfinae()
|
||||||
|
#ifdef HAS_CPP14_SUPPORT
|
||||||
|
{
|
||||||
|
variant<int, float, std::vector<int>> var;
|
||||||
|
|
||||||
|
auto visitor = make_visitor([](auto range) -> decltype(std::begin(range), void()) {
|
||||||
|
for (auto each : range)
|
||||||
|
std::cout << each << ' '; },
|
||||||
|
[](auto x) -> decltype(std::cout << x, void()) {
|
||||||
|
std::cout << x << std::endl;
|
||||||
|
});
|
||||||
|
|
||||||
|
var = 1;
|
||||||
|
apply_visitor(visitor, var);
|
||||||
|
|
||||||
|
var = 2.f;
|
||||||
|
apply_visitor(visitor, var);
|
||||||
|
|
||||||
|
var = std::vector<int>{4, 5, 6};
|
||||||
|
apply_visitor(visitor, var);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void test_match_singleton()
|
||||||
|
{
|
||||||
|
variant<int> singleton = 5;
|
||||||
|
singleton.match([](int) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_match_overloads()
|
||||||
|
{
|
||||||
|
Either<Error, Response> rv;
|
||||||
|
|
||||||
|
rv = Response{};
|
||||||
|
|
||||||
|
rv.match([](Response) { std::cout << "Response\n"; }, //
|
||||||
|
[](Error) { std::cout << "Error\n"; }); //
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_match_overloads_capture()
|
||||||
|
{
|
||||||
|
Either<Error, Response> rv;
|
||||||
|
|
||||||
|
rv = Error{};
|
||||||
|
|
||||||
|
int ok = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
rv.match([&](Response) { ok += 1; }, //
|
||||||
|
[&](Error) { err += 1; }); //
|
||||||
|
|
||||||
|
std::cout << "Got " << ok << " ok, " << err << " err" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_lambda_overloads();
|
||||||
|
test_singleton_variant();
|
||||||
|
test_lambda_overloads_capture();
|
||||||
|
test_lambda_overloads_sfinae();
|
||||||
|
|
||||||
|
test_match_singleton();
|
||||||
|
test_match_overloads();
|
||||||
|
test_match_overloads_capture();
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef HAS_CPP14_SUPPORT
|
@ -1,4 +1,4 @@
|
|||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/timer/timer.hpp>
|
#include "auto_cpu_timer.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
using namespace mapbox;
|
using namespace mapbox;
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
int total = 0;
|
int total = 0;
|
||||||
{
|
{
|
||||||
boost::timer::auto_cpu_timer t;
|
auto_cpu_timer t;
|
||||||
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
||||||
{
|
{
|
||||||
total += util::apply_visitor(test::calculator(), result);
|
total += util::apply_visitor(test::calculator(), result);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
using namespace mapbox;
|
using namespace mapbox;
|
||||||
|
|
||||||
@ -41,9 +41,12 @@ struct print
|
|||||||
void operator()(line_string const& line) const
|
void operator()(line_string const& line) const
|
||||||
{
|
{
|
||||||
std::cerr << "Line(";
|
std::cerr << "Line(";
|
||||||
|
bool first = true;
|
||||||
for (auto const& pt : line)
|
for (auto const& pt : line)
|
||||||
{
|
{
|
||||||
std::cerr << pt.x << " " << pt.y << ",";
|
if (!first) std::cerr << ",";
|
||||||
|
std::cerr << pt.x << " " << pt.y;
|
||||||
|
if (first) first = false;
|
||||||
}
|
}
|
||||||
std::cerr << ")" << std::endl;
|
std::cerr << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " i-d"
|
#define NAME_EXT " i-d"
|
||||||
using variant_type = mapbox::util::variant<int, double>;
|
using variant_type = mapbox::util::variant<int, double>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " b-i-d"
|
#define NAME_EXT " b-i-d"
|
||||||
using variant_type = mapbox::util::variant<bool, int, double>;
|
using variant_type = mapbox::util::variant<bool, int, double>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " i-d-b"
|
#define NAME_EXT " i-d-b"
|
||||||
using variant_type = mapbox::util::variant<int, double, bool>;
|
using variant_type = mapbox::util::variant<int, double, bool>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " b-i-d-c"
|
#define NAME_EXT " b-i-d-c"
|
||||||
using variant_type = mapbox::util::variant<bool, int, double, char>;
|
using variant_type = mapbox::util::variant<bool, int, double, char>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " b-i-c-d-i"
|
#define NAME_EXT " b-i-c-d-i"
|
||||||
using variant_type = mapbox::util::variant<bool, int, char, double, int>;
|
using variant_type = mapbox::util::variant<bool, int, char, double, int>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
#define NAME_EXT " b-i-i-d-c-u"
|
#define NAME_EXT " b-i-i-d-c-u"
|
||||||
using variant_type = mapbox::util::variant<bool, int, int, double, char, short int>;
|
using variant_type = mapbox::util::variant<bool, int, int, double, char, short int>;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
struct add_visitor
|
struct add_visitor
|
||||||
{
|
{
|
||||||
|
20
third_party/variant/test/t/issue122.cpp
vendored
Normal file
20
third_party/variant/test/t/issue122.cpp
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
#include <mapbox/variant.hpp>
|
||||||
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
|
// https://github.com/mapbox/variant/issues/122
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
template <typename ValueType>
|
||||||
|
X(const ValueType&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Correctly choose appropriate constructor", "[variant]")
|
||||||
|
{
|
||||||
|
mapbox::util::variant<X, int> a{123};
|
||||||
|
decltype(a) b(a);
|
||||||
|
REQUIRE(a.which() == b.which());
|
||||||
|
}
|
14
third_party/variant/test/t/issue21.cpp
vendored
14
third_party/variant/test/t/issue21.cpp
vendored
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
// https://github.com/mapbox/variant/issues/21
|
// https://github.com/mapbox/variant/issues/21
|
||||||
|
|
||||||
@ -11,6 +10,12 @@ static int count;
|
|||||||
struct t1
|
struct t1
|
||||||
{
|
{
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
|
t1(t1 const& rhs)
|
||||||
|
: value(rhs.value)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
}
|
||||||
t1(int v) : value(v)
|
t1(int v) : value(v)
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
@ -37,7 +42,8 @@ TEST_CASE("set() works cleanly even if the constructor throws ", "[variant]")
|
|||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
{
|
{
|
||||||
variant_type v{42};
|
t1 obj{42};
|
||||||
|
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({
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
2
third_party/variant/test/t/optional.cpp
vendored
2
third_party/variant/test/t/optional.cpp
vendored
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "optional.hpp"
|
#include <mapbox/optional.hpp>
|
||||||
|
|
||||||
struct dummy
|
struct dummy
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "recursive_wrapper.hpp"
|
#include <mapbox/recursive_wrapper.hpp>
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
4
third_party/variant/test/t/sizeof.cpp
vendored
4
third_party/variant/test/t/sizeof.cpp
vendored
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
struct some_struct
|
struct some_struct
|
||||||
{
|
{
|
||||||
|
4
third_party/variant/test/t/unary_visitor.cpp
vendored
4
third_party/variant/test/t/unary_visitor.cpp
vendored
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
33
third_party/variant/test/t/variant.cpp
vendored
33
third_party/variant/test/t/variant.cpp
vendored
@ -1,7 +1,7 @@
|
|||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
#include "variant_io.hpp"
|
#include <mapbox/variant_io.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -325,7 +325,7 @@ TEST_CASE("implicit conversion", "[variant][implicit conversion]")
|
|||||||
TEST_CASE("implicit conversion to first type in variant type list", "[variant][implicit conversion]")
|
TEST_CASE("implicit conversion to first type in variant type list", "[variant][implicit conversion]")
|
||||||
{
|
{
|
||||||
using variant_type = mapbox::util::variant<long, char>;
|
using variant_type = mapbox::util::variant<long, char>;
|
||||||
variant_type var = 5.0; // 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>();
|
||||||
@ -543,9 +543,9 @@ TEST_CASE("storing reference wrappers to consts works")
|
|||||||
int a = 1;
|
int a = 1;
|
||||||
variant_type v{std::cref(a)};
|
variant_type v{std::cref(a)};
|
||||||
REQUIRE(v.get<int const>() == 1);
|
REQUIRE(v.get<int const>() == 1);
|
||||||
REQUIRE(v.get<int>() == 1); // this works (see #82)
|
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); // this doesn't work (see #82)
|
REQUIRE(mapbox::util::get<int>(v) == 1);
|
||||||
REQUIRE_THROWS_AS({
|
REQUIRE_THROWS_AS({
|
||||||
v.get<double const>();
|
v.get<double const>();
|
||||||
},
|
},
|
||||||
@ -568,3 +568,26 @@ TEST_CASE("storing reference wrappers to consts works")
|
|||||||
},
|
},
|
||||||
mapbox::util::bad_variant_access&);
|
mapbox::util::bad_variant_access&);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("recursive wrapper")
|
||||||
|
{
|
||||||
|
using variant_type = mapbox::util::variant<mapbox::util::recursive_wrapper<int>>;
|
||||||
|
variant_type v(1);
|
||||||
|
REQUIRE(v.is<int>());
|
||||||
|
REQUIRE(v.get<int>() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("variant : direct_type helper should match T, references (T&) and const references (T const&) to the original type T)")
|
||||||
|
{
|
||||||
|
using value = mapbox::util::variant<bool, std::uint64_t>;
|
||||||
|
|
||||||
|
std::uint64_t u(1234);
|
||||||
|
REQUIRE(value(u).is<std::uint64_t>()); // matches T
|
||||||
|
|
||||||
|
std::uint64_t& ur(u);
|
||||||
|
REQUIRE(value(ur).is<std::uint64_t>()); // matches T&
|
||||||
|
|
||||||
|
std::uint64_t const& ucr(u);
|
||||||
|
REQUIRE(value(ucr).is<std::uint64_t>()); // matches T const&
|
||||||
|
}
|
||||||
|
6
third_party/variant/test/unique_ptr_test.cpp
vendored
6
third_party/variant/test/unique_ptr_test.cpp
vendored
@ -6,9 +6,9 @@
|
|||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/timer/timer.hpp>
|
#include "auto_cpu_timer.hpp"
|
||||||
|
|
||||||
#include "variant.hpp"
|
#include <mapbox/variant.hpp>
|
||||||
|
|
||||||
using namespace mapbox;
|
using namespace mapbox;
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
int total = 0;
|
int total = 0;
|
||||||
{
|
{
|
||||||
boost::timer::auto_cpu_timer t;
|
auto_cpu_timer t;
|
||||||
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
for (std::size_t i = 0; i < NUM_ITER; ++i)
|
||||||
{
|
{
|
||||||
total += util::apply_visitor(test::calculator(), result);
|
total += util::apply_visitor(test::calculator(), result);
|
||||||
|
2
third_party/variant/variant.gyp
vendored
2
third_party/variant/variant.gyp
vendored
@ -27,7 +27,7 @@
|
|||||||
"SUPPORTED_PLATFORMS":["macosx"]
|
"SUPPORTED_PLATFORMS":["macosx"]
|
||||||
},
|
},
|
||||||
"include_dirs": [
|
"include_dirs": [
|
||||||
"./",
|
"./include",
|
||||||
"test/include"
|
"test/include"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user