From 6d66ca689648249fad6d14a738b295d4423121d8 Mon Sep 17 00:00:00 2001 From: Jonathan Reams Date: Tue, 26 Jun 2018 13:43:14 -0400 Subject: SERVER-35818 Add stdx::variant (cherry picked from commit 309e4bc0867988210601454750760e0d00c896ca) --- src/mongo/stdx/variant.h | 90 + src/third_party/variant-1.3.0/.appveyor.yml | 68 + src/third_party/variant-1.3.0/.clang-format | 359 ++++ src/third_party/variant-1.3.0/.gitignore | 33 + src/third_party/variant-1.3.0/.gitmodules | 3 + src/third_party/variant-1.3.0/.travis.yml | 175 ++ src/third_party/variant-1.3.0/LICENSE.md | 23 + src/third_party/variant-1.3.0/README.md | 156 ++ .../cmake/mpark_variant-config.cmake.in | 26 + .../variant-1.3.0/include/mpark/config.hpp | 74 + .../variant-1.3.0/include/mpark/in_place.hpp | 35 + .../variant-1.3.0/include/mpark/lib.hpp | 442 +++++ .../variant-1.3.0/include/mpark/variant.hpp | 1908 ++++++++++++++++++++ .../variant-1.3.0/support/single-header.py | 39 + src/third_party/variant-1.3.0/support/wandbox.cpp | 19 + src/third_party/variant-1.3.0/support/wandbox.py | 106 ++ src/third_party/variant-1.3.0/test/README.md | 49 + src/third_party/variant-1.3.0/test/assign.copy.cpp | 51 + src/third_party/variant-1.3.0/test/assign.fwd.cpp | 133 ++ src/third_party/variant-1.3.0/test/assign.move.cpp | 53 + src/third_party/variant-1.3.0/test/ctor.copy.cpp | 44 + .../variant-1.3.0/test/ctor.default.cpp | 22 + src/third_party/variant-1.3.0/test/ctor.fwd.cpp | 52 + .../variant-1.3.0/test/ctor.in_place.cpp | 78 + src/third_party/variant-1.3.0/test/ctor.move.cpp | 46 + src/third_party/variant-1.3.0/test/dtor.cpp | 26 + src/third_party/variant-1.3.0/test/get.cpp | 141 ++ src/third_party/variant-1.3.0/test/hash.cpp | 31 + src/third_party/variant-1.3.0/test/intro.cpp | 64 + src/third_party/variant-1.3.0/test/json.cpp | 49 + src/third_party/variant-1.3.0/test/libcxx.sh | 29 + src/third_party/variant-1.3.0/test/mod.cpp | 60 + src/third_party/variant-1.3.0/test/relops.cpp | 197 ++ src/third_party/variant-1.3.0/test/swap.cpp | 172 ++ src/third_party/variant-1.3.0/test/util.hpp | 60 + src/third_party/variant-1.3.0/test/visit.cpp | 130 ++ 36 files changed, 5043 insertions(+) create mode 100644 src/mongo/stdx/variant.h create mode 100644 src/third_party/variant-1.3.0/.appveyor.yml create mode 100644 src/third_party/variant-1.3.0/.clang-format create mode 100644 src/third_party/variant-1.3.0/.gitignore create mode 100644 src/third_party/variant-1.3.0/.gitmodules create mode 100644 src/third_party/variant-1.3.0/.travis.yml create mode 100644 src/third_party/variant-1.3.0/LICENSE.md create mode 100644 src/third_party/variant-1.3.0/README.md create mode 100644 src/third_party/variant-1.3.0/cmake/mpark_variant-config.cmake.in create mode 100644 src/third_party/variant-1.3.0/include/mpark/config.hpp create mode 100644 src/third_party/variant-1.3.0/include/mpark/in_place.hpp create mode 100644 src/third_party/variant-1.3.0/include/mpark/lib.hpp create mode 100644 src/third_party/variant-1.3.0/include/mpark/variant.hpp create mode 100755 src/third_party/variant-1.3.0/support/single-header.py create mode 100644 src/third_party/variant-1.3.0/support/wandbox.cpp create mode 100755 src/third_party/variant-1.3.0/support/wandbox.py create mode 100644 src/third_party/variant-1.3.0/test/README.md create mode 100644 src/third_party/variant-1.3.0/test/assign.copy.cpp create mode 100644 src/third_party/variant-1.3.0/test/assign.fwd.cpp create mode 100644 src/third_party/variant-1.3.0/test/assign.move.cpp create mode 100644 src/third_party/variant-1.3.0/test/ctor.copy.cpp create mode 100644 src/third_party/variant-1.3.0/test/ctor.default.cpp create mode 100644 src/third_party/variant-1.3.0/test/ctor.fwd.cpp create mode 100644 src/third_party/variant-1.3.0/test/ctor.in_place.cpp create mode 100644 src/third_party/variant-1.3.0/test/ctor.move.cpp create mode 100644 src/third_party/variant-1.3.0/test/dtor.cpp create mode 100644 src/third_party/variant-1.3.0/test/get.cpp create mode 100644 src/third_party/variant-1.3.0/test/hash.cpp create mode 100644 src/third_party/variant-1.3.0/test/intro.cpp create mode 100644 src/third_party/variant-1.3.0/test/json.cpp create mode 100755 src/third_party/variant-1.3.0/test/libcxx.sh create mode 100644 src/third_party/variant-1.3.0/test/mod.cpp create mode 100644 src/third_party/variant-1.3.0/test/relops.cpp create mode 100644 src/third_party/variant-1.3.0/test/swap.cpp create mode 100644 src/third_party/variant-1.3.0/test/util.hpp create mode 100644 src/third_party/variant-1.3.0/test/visit.cpp diff --git a/src/mongo/stdx/variant.h b/src/mongo/stdx/variant.h new file mode 100644 index 00000000000..92bf6167555 --- /dev/null +++ b/src/mongo/stdx/variant.h @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2018 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#ifndef __cpp_lib_variant +#include "third_party/variant-1.3.0/include/mpark/variant.hpp" +#else +#include +#endif + +namespace mongo { +namespace stdx { +#if __cplusplus < 201703L || !defined(__cpp_lib_variant) +using ::mpark::variant; +using ::mpark::visit; +using ::mpark::holds_alternative; +using ::mpark::get; +using ::mpark::get_if; + +using ::mpark::variant_size; +using ::mpark::variant_size_v; +using ::mpark::variant_alternative; +using ::mpark::variant_alternative_t; + +constexpr auto variant_npos = ::mpark::variant_npos; + +using ::mpark::operator==; +using ::mpark::operator!=; +using ::mpark::operator<; +using ::mpark::operator>; +using ::mpark::operator<=; +using ::mpark::operator>=; + +using ::mpark::monostate; +using ::mpark::bad_variant_access; + +#else +using ::std::variant; +using ::std::visit; +using ::std::holds_alternative; +using ::std::get; +using ::std::get_if; + +using ::std::variant_size; +using ::std::variant_size_v; +using ::std::variant_alternative; +using ::std::variant_alternative_t; + +constexpr auto variant_npos = ::std::variant_npos; + +using ::std::operator==; +using ::std::operator!=; +using ::std::operator<; +using ::std::operator>; +using ::std::operator<=; +using ::std::operator>=; + +using ::std::monostate; +using ::std::bad_variant_access; + +#endif + +} // namespace stdx +} // namespace mongo diff --git a/src/third_party/variant-1.3.0/.appveyor.yml b/src/third_party/variant-1.3.0/.appveyor.yml new file mode 100644 index 00000000000..c0c41e06876 --- /dev/null +++ b/src/third_party/variant-1.3.0/.appveyor.yml @@ -0,0 +1,68 @@ +build: + verbosity: detailed + +clone_depth: 1 + +install: + - cmd: git submodule -q update --init + +environment: + matrix: + - GENERATOR: Visual Studio 14 2015 Win64 + EXCEPTIONS: ON + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - GENERATOR: Visual Studio 14 2015 Win64 + EXCEPTIONS: OFF + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + + # /std:c++14 + - GENERATOR: Visual Studio 15 2017 Win64 + CXXFLAGS: /std:c++14 /permissive- + EXCEPTIONS: ON + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - GENERATOR: Visual Studio 15 2017 Win64 + CXXFLAGS: /std:c++14 /permissive- + EXCEPTIONS: OFF + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + + # /std:c++latest + - GENERATOR: Visual Studio 15 2017 Win64 + CXXFLAGS: /std:c++latest /permissive- + EXCEPTIONS: ON + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - GENERATOR: Visual Studio 15 2017 Win64 + CXXFLAGS: /std:c++latest /permissive- + EXCEPTIONS: OFF + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + + # Clang/LLVM + - GENERATOR: Visual Studio 14 2015 Win64 + TOOLSET: LLVM-vs2014 + EXCEPTIONS: ON + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - GENERATOR: Visual Studio 14 2015 Win64 + TOOLSET: LLVM-vs2014 + EXCEPTIONS: OFF + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + +platform: x64 + +configuration: + - Debug + - Release + +branches: + only: + - master + +build_script: + - mkdir build + - cd build + - ps: | + if (Test-Path env:TOOLSET) { + cmake -G "$env:GENERATOR" -T "$env:TOOLSET" -DMPARK_VARIANT_EXCEPTIONS="$env:EXCEPTIONS" -DMPARK_VARIANT_INCLUDE_TESTS="mpark" .. + } else { + cmake -G "$env:GENERATOR" -DMPARK_VARIANT_EXCEPTIONS="$env:EXCEPTIONS" -DMPARK_VARIANT_INCLUDE_TESTS="mpark" .. + } + - cmake --build . --config %CONFIGURATION% + - ctest -V diff --git a/src/third_party/variant-1.3.0/.clang-format b/src/third_party/variant-1.3.0/.clang-format new file mode 100644 index 00000000000..4d8207f7984 --- /dev/null +++ b/src/third_party/variant-1.3.0/.clang-format @@ -0,0 +1,359 @@ +--- +BasedOnStyle: Google + +# Good: +# +# class TFoo { +# public: +# +# TFoo() = default; +# +# } // TFoo +# +# Bad: +# +# class TFoo { +# public: +# +# TFoo() = default; +# +# } // TFoo +# +AccessModifierOffset: 0 + +### AlignEscapedNewlinesLeft: true + +# Good: +# +# int x = 100; // comment1 +# std::string y = "one hundred"; // comment2 +# +# Bad: +# +# int x = 100; // comment1 +# std::string y = "one hundred"; // comment2 +# +AlignTrailingComments: false + +### AllowAllParametersOfDeclarationOnNextLine: true + +AllowShortIfStatementsOnASingleLine: true + +# Good: +# +# while (flag) +# x = 42; +# +# Bad: +# +# while (flag) x = 42; +# +AllowShortLoopsOnASingleLine: false + +# Good: +# +# const char *text = +# "hello" +# "world"; +# +# Bad: +# +# const char *text = "hello" +# "world"; +# +AlwaysBreakBeforeMultilineStrings: true + +# Good: +# +# template +# void F() {} +# +# Bad: +# +# template void F() {} +# +AlwaysBreakTemplateDeclarations: true + +# Good: +# +# F(first, +# second, +# third, +# fourth, +# fifth, +# sixth, +# seventh, +# eighth); +# +# Bad: +# +# F(first, second, third, fourth, fifth, sixth, +# seventh, eighth); +# +BinPackArguments: false + +# Good: +# +# void F(int first, +# int second, +# int third, +# int fourth, +# int fifth, +# int sixth, +# int seventh, +# int eighth) {} +# +# Bad: +# +# void F(int first, int second, int third, int fourth, int fifth, int sixth, +# int seventh, int eighth) {} +# +BinPackParameters: false + +# Good: +# +# int x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +# bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; +# +# Bad: +# +# int x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +# + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; +# +BreakBeforeBinaryOperators: false + +# Good: +# +# void F() {} +# +# Bad: +# +# void F() +# { +# } +# +BreakBeforeBraces: Attach + +# Good: +# +# class TFoo { +# public: +# +# TFoo() +# : Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(1), +# Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(2) {} +# +# }; // TFoo +# +# Bad: +# +# class TFoo { +# public: +# +# TFoo() +# : Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(1) +# , Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(2) {} +# +# }; // TFoo +# +BreakConstructorInitializersBeforeComma: false + +ColumnLimit: 80 + +# Good: +# +# class TFoo { +# public: +# +# TFoo() +# : First(1), +# Second(2), +# Third(3), +# Fourth(4), +# Fifth(5), +# Sixth(6), +# Seventh(7), +# Eighth(8) {} +# +# }; // TFoo +# +# Bad: +# +# class TFoo { +# public: +# +# TFoo() +# : First(1), Second(2), Third(3), Fourth(4), Fifth(5), Sixth(6), +# Seventh(7), Eighth(8) {} +# +# }; // TFoo +# +ConstructorInitializerAllOnOneLineOrOnePerLine: true + +ConstructorInitializerIndentWidth: 4 + +Cpp11BracedListStyle: true + +DerivePointerBinding: false + +# Good: +# +# int x; +# switch (x) { +# case 0: { +# x = 0; +# break; +# } // case +# case 1: { +# x = 1; +# break; +# } // case +# } // switch +# +# Bad: +# +# int x; +# switch (x) { +# case 0: { +# x = 0; +# break; +# } // case +# case 1: { +# x = 1; +# break; +# } // case +# } // switch +# +IndentCaseLabels: true + +# Good: +# +# std::tuple +# Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(); +# +# Bad: +# +# std::tuple +# Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(); +# +IndentFunctionDeclarationAfterType: false + +IndentWidth: 2 + +MaxEmptyLinesToKeep: 1 + +# Good: +# +# namespace Foo { +# +# class TFoo {}; +# +# } // Foo +# +# Bad: +# +# namespace Foo { +# +# class TFoo {}; +# +# } // Foo +# +NamespaceIndentation: All + +### ObjCSpaceBeforeProtocolList: false + +### PenaltyBreakComment: 60 + +### PenaltyBreakFirstLessLess: 120 + +### PenaltyBreakString: 1000 + +### PenaltyExcessCharacter: 1000000 + +### PenaltyReturnTypeOnItsOwnLine: 200 + +# Good: +# +# int *ptr = nullptr; +# +# Bad: +# +# int* ptr = nullptr; +# +PointerBindsToType: false + +# Good: +# +# if (flag) { +# flag = true; +# } // if +# +# Bad: +# +# if(flag) { +# flag = true; +# } // if +# +SpaceAfterControlStatementKeyword: true + +# Good: +# +# x = 42; +# +# Bad: +# +# x= 42; +# +SpaceBeforeAssignmentOperators: true + +# Good: +# +# F(); +# +# Bad: +# +# F( ); +# +SpaceInEmptyParentheses: false + +# Good: +# +# x = 42; // Comment +# +# Bad: +# +# x = 42; // Comment +# +SpacesBeforeTrailingComments: 2 + +# Good: +# +# bool y = (bool)x; +# +# Bad: +# +# bool y = ( bool )x; +# +SpacesInCStyleCastParentheses: false + +# Good: +# +# if (flag) { +# flag = true; +# } // if +# +# Bad: +# +# if ( flag ) { +# flag = true; +# } // if +# +SpacesInParentheses: false + +Standard: Cpp11 + +TabWidth: 2 + +UseTab: false +... + diff --git a/src/third_party/variant-1.3.0/.gitignore b/src/third_party/variant-1.3.0/.gitignore new file mode 100644 index 00000000000..f294e45c5dc --- /dev/null +++ b/src/third_party/variant-1.3.0/.gitignore @@ -0,0 +1,33 @@ +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# build +/build + +3rdparty/metabench diff --git a/src/third_party/variant-1.3.0/.gitmodules b/src/third_party/variant-1.3.0/.gitmodules new file mode 100644 index 00000000000..85675ac0bc0 --- /dev/null +++ b/src/third_party/variant-1.3.0/.gitmodules @@ -0,0 +1,3 @@ +[submodule "3rdparty/googletest"] + path = 3rdparty/googletest + url = https://github.com/google/googletest.git diff --git a/src/third_party/variant-1.3.0/.travis.yml b/src/third_party/variant-1.3.0/.travis.yml new file mode 100644 index 00000000000..ce5e9df13d6 --- /dev/null +++ b/src/third_party/variant-1.3.0/.travis.yml @@ -0,0 +1,175 @@ +# MPark.Variant +# +# Copyright Michael Park, 2015-2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +language: cpp +sudo: false + +branches: + only: + - master + +git: + depth: 1 + +matrix: + include: + # ubuntu 14.04, gcc-4.8 + - env: VER=4.8 STDS="11;1y" TESTS="mpark" + compiler: gcc + os: linux + addons: { apt: { packages: ["g++-4.8"], sources: ["ubuntu-toolchain-r-test"] } } + + # ubuntu 14.04, gcc-4.9 + - env: VER=4.9 STDS="11;14" TESTS="mpark" + compiler: gcc + os: linux + addons: { apt: { packages: ["g++-4.9"], sources: ["ubuntu-toolchain-r-test"] } } + + # ubuntu 14.04, gcc-5 + - env: VER=5 STDS="11;14;1z" TESTS="mpark" + compiler: gcc + os: linux + addons: { apt: { packages: ["g++-5"], sources: ["ubuntu-toolchain-r-test"] } } + + # ubuntu 14.04, gcc-6 + - env: VER=6 STDS="11;14;1z" TESTS="mpark" + compiler: gcc + os: linux + addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } } + + # ubuntu 14.04, gcc-7 + - env: VER=7 STDS="11;14;17" TESTS="mpark;libc++" + compiler: gcc + os: linux + addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } } + + # ubuntu 14.04, clang-3.5 + - env: VER=3.5 STDS="11;14" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-3.5", "libstdc++-5-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.5"] } } + + # ubuntu 14.04, clang-3.6 + - env: VER=3.6 STDS="11;14" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-3.6", "libstdc++-5-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.6"] } } + + # ubuntu 14.04, clang-3.7 + - env: VER=3.7 STDS="11;14" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-3.7", "libstdc++-5-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.7"] } } + + # ubuntu 14.04, clang-3.8 + - env: VER=3.8 STDS="11;14" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-3.8", "libstdc++-5-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-precise-3.8"] } } + + # ubuntu 14.04, clang-3.9 + - env: VER=3.9 STDS="11;14;1z" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-3.9", "libstdc++-6-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-3.9"] } } + + # ubuntu 14.04, clang-4.0 + - env: VER=4.0 STDS="11;14;1z" TESTS="mpark" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-4.0", "libstdc++-6-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-4.0"] } } + + # ubuntu 14.04, clang-5.0 + - env: VER=5.0 STDS="11;14;17" TESTS="mpark;libc++" + compiler: clang + os: linux + addons: { apt: { packages: ["clang-5.0", "libstdc++-7-dev"], sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"] } } + + # OS X Yosemite 10.10, Apple Clang 6 + - env: STDS="11;14" TESTS="mpark" + compiler: clang + os: osx + osx_image: xcode6.4 + + # OS X El Capitan 10.11, Apple Clang 7 + - env: STDS="11;14;1z" TESTS="mpark" + compiler: clang + os: osx + osx_image: xcode7.3 + + # OS X Sierra 10.12, Apple Clang 8 + - env: STDS="11;14;1z" TESTS="mpark" + compiler: clang + os: osx + osx_image: xcode8.3 + +before_install: + # Set the correct `CC` and `CXX` environment variables. + - | + if [ -n "${VER}" ]; then + export CC="${CC}-${VER}" + export CXX="${CXX}-${VER}" + fi + - ${CXX} --version + # Directory for dependency installation. + - DEPS="${TRAVIS_BUILD_DIR}/deps" + - mkdir -p ${DEPS} + # Install newer cmake. + - | + if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + brew update + brew upgrade cmake + elif [ "${TRAVIS_OS_NAME}" = "linux" ]; then + travis_retry wget --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.sh + bash cmake-3.8.2-Linux-x86_64.sh --skip-license --prefix="${DEPS}" + export PATH="${DEPS}/bin:${PATH}" + fi + - export CXXFLAGS="-Wall -Wextra -Werror -pedantic-errors" + - STDS=(${STDS//;/ }) + - BUILDS=(Debug Release) + - EXS=(ON OFF) + +install: + - | + for STD in "${STDS[@]}"; do + for BUILD in "${BUILDS[@]}"; do + for EX in "${EXS[@]}"; do + BUILD_DIR="build-${STD}-${BUILD}-${EX}" + mkdir "${BUILD_DIR}" + pushd "${BUILD_DIR}" + ( + set -ex + export CXXFLAGS="${CXXFLAGS} -std=c++${STD}" + cmake -DCMAKE_BUILD_TYPE="${BUILD}" \ + -DMPARK_VARIANT_EXCEPTIONS="${EX}" \ + -DMPARK_VARIANT_INCLUDE_TESTS="${TESTS}" .. + ) + popd + done + done + done + +script: + - | + for STD in "${STDS[@]}"; do + for BUILD in "${BUILDS[@]}"; do + for EX in "${EXS[@]}"; do + BUILD_DIR="build-${STD}-${BUILD}-${EX}" + mkdir "${BUILD_DIR}" + pushd "${BUILD_DIR}" + ( + set -ex + cmake --build . -- -k -j 2 + ctest --output-on-failure + ) + popd + done + done + done + +notifications: + email: false diff --git a/src/third_party/variant-1.3.0/LICENSE.md b/src/third_party/variant-1.3.0/LICENSE.md new file mode 100644 index 00000000000..36b7cd93cdf --- /dev/null +++ b/src/third_party/variant-1.3.0/LICENSE.md @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/third_party/variant-1.3.0/README.md b/src/third_party/variant-1.3.0/README.md new file mode 100644 index 00000000000..c58bc855112 --- /dev/null +++ b/src/third_party/variant-1.3.0/README.md @@ -0,0 +1,156 @@ +# MPark.Variant + +> __C++17__ `std::variant` for __C++11__/__14__/__17__ + +[![release][badge.release]][release] +[![header][badge.header]][header] +[![travis][badge.travis]][travis] +[![appveyor][badge.appveyor]][appveyor] +[![license][badge.license]][license] +[![godbolt][badge.godbolt]][godbolt] +[![wandbox][badge.wandbox]][wandbox] + +[badge.release]: https://img.shields.io/github/release/mpark/variant.svg +[badge.header]: https://img.shields.io/badge/single%20header-master-blue.svg +[badge.travis]: https://travis-ci.org/mpark/variant.svg?branch=master +[badge.appveyor]: https://ci.appveyor.com/api/projects/status/github/mpark/variant?branch=master&svg=true +[badge.license]: https://img.shields.io/badge/license-boost-blue.svg +[badge.godbolt]: https://img.shields.io/badge/try%20it-on%20godbolt-222266.svg +[badge.wandbox]: https://img.shields.io/badge/try%20it-on%20wandbox-5cb85c.svg + +[release]: https://github.com/mpark/variant/releases/latest +[header]: https://github.com/mpark/variant/blob/single-header/master/variant.hpp +[travis]: https://travis-ci.org/mpark/variant +[appveyor]: https://ci.appveyor.com/project/mpark/variant +[license]: https://github.com/mpark/variant/blob/master/LICENSE.md +[godbolt]: https://godbolt.org/g/1qYDAK +[wandbox]: https://wandbox.org/permlink/QV3gZ2KQQNwgoFIB + +## Introduction + +__MPark.Variant__ is an implementation of __C++17__ `std::variant` for __C++11__/__14__/__17__. + + - Based on [my implementation of `std::variant` for __libc++__][libcxx-impl] + - Continuously tested against __libc++__'s `std::variant` test suite. + +[libcxx-impl]: https://reviews.llvm.org/rL288547 + +## Documentation + + - [cppreference.com](http://en.cppreference.com/w/cpp/utility/variant) + - [eel.is/c++draft](http://eel.is/c++draft/variant) + +## Integration + +### Single Header + +The [single-header] branch provides a standalone `variant.hpp` +file for each [release](https://github.com/mpark/variant/releases). +Copy it and `#include` away! + +[single-header]: https://github.com/mpark/variant/tree/single-header + +### Submodule + +You can add `mpark/variant` as a submodule to your project. + +```bash +git submodule add https://github.com/mpark/variant.git 3rdparty/variant +``` + +Add the `include` directory to your include path with +`-I3rdparty/variant/include` then `#include` the `variant.hpp` header +with `#include `. + +If you use CMake, you can simply use `add_subdirectory(3rdparty/variant)`: + +```cmake +cmake_minimum_required(VERSION 3.6.3) + +project(HelloWorld CXX) + +add_subdirectory(3rdparty/variant) + +add_executable(hello-world hello_world.cpp) +target_link_libraries(hello-world mpark_variant) +``` + +### Installation / CMake `find_package` + +```bash +git clone https://github.com/mpark/variant.git +mkdir variant/build && cd variant/build +cmake .. +cmake --build . --target install +``` + +This will install `mpark/variant` to the default install-directory for +your platform (`/usr/local` for Unix, `C:\Program Files` for Windows). +You can also install at a custom location via the `CMAKE_INSTALL_PREFIX` +variable, (e.g., `cmake .. -DCMAKE_INSTALL_PREFIX=/opt`). + +The installed `mpark/variant` can then be found by CMake via `find_package`: + +```cmake +cmake_minimum_required(VERSION 3.6.3) + +project(HelloWorld CXX) + +find_package(mpark_variant 1.3.0 REQUIRED) + +add_executable(hello-world hello_world.cpp) +target_link_libraries(hello-world mpark_variant) +``` + +CMake will search for `mpark/variant` in its default set of +installation prefixes. If `mpark/variant` is installed in +a custom location via the `CMAKE_INSTALL_PREFIX` variable, +you'll likely need to use the `CMAKE_PREFIX_PATH` to specify +the location (e.g., `cmake .. -DCMAKE_PREFIX_PATH=/opt`). + +## Requirements + +This library requires a standard conformant __C++11__ compiler. +The following compilers are continously tested: + +| Compiler | Operating System | Version String | +| -------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------ | +| GCC 4.8.5 | Ubuntu 14.04.5 LTS | g++-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 | +| GCC 4.9.4 | Ubuntu 14.04.5 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 | +| GCC 5.4.1 | Ubuntu 14.04.5 LTS | g++-5 (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 | +| GCC 6.3.0 | Ubuntu 14.04.5 LTS | g++-6 (Ubuntu/Linaro 6.3.0-18ubuntu2~14.04) 6.3.0 20170519 | +| GCC 7.2.0 | Ubuntu 14.04.5 LTS | g++-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 | +| Clang 3.5.0 | Ubuntu 14.04.5 LTS | Ubuntu clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0) | +| Clang 3.6.2 | Ubuntu 14.04.5 LTS | Ubuntu clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2) | +| Clang 3.7.1 | Ubuntu 14.04.5 LTS | Ubuntu clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1) | +| Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) | +| Clang 3.9.1 | Ubuntu 14.04.5 LTS | clang version 3.9.1-4ubuntu3~14.04.2 (tags/RELEASE_391/rc2) | +| Clang 4.0.1 | Ubuntu 14.04.5 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) | +| Clang 5.0.0 | Ubuntu 14.04.5 LTS | clang version 5.0.0-svn312333-1~exp1 (branches/release_50) | +| Clang Xcode 6.4 | Darwin Kernel Version 14.5.0 (OS X 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) | +| Clang Xcode 7.3 | Darwin Kernel Version 15.6.0 (OS X 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.31) | +| Clang Xcode 8.3 | Darwin Kernel Version 16.6.0 (OS X 10.12.5) | Apple LLVM version 8.1.0 (clang-802.0.42) | +| Visual Studio 14 2015 | Visual Studio 2015 with Update 3 | MSVC 19.0.24215.1 | Microsoft (R) Build Engine version 14.0.25420.1 | +| Visual Studio 15 2017 | Visual Studio 2017 | MSVC 19.11.25547.0 | Microsoft (R) Build Engine version 15.4.8.50001 | +| Visual Studio 14 2015 (__Clang/LLVM__) | Visual Studio 2015 with Update 3 | Clang 4.0.0 | Microsoft (R) Build Engine version 14.0.25420.1 | + +#### NOTES + - __GCC 4.8__/__4.9__: `constexpr` support is not available for `visit` and relational operators. + - Enabling __libc++__ `std::variant` tests require `-std=c++17` support. + +## CMake Variables + + - __`MPARK_VARIANT_INCLUDE_TESTS`__:`STRING` (__default__: `""`) + + Semicolon-separated list of tests to build. + Possible values are `mpark`, and `libc++`. + + __NOTE__: The __libc++__ `std::variant` tests are built with `-std=c++17`. + +## Unit Tests + +Refer to [test/README.md](test/README.md). + +## License + +Distributed under the [Boost Software License, Version 1.0](LICENSE.md). diff --git a/src/third_party/variant-1.3.0/cmake/mpark_variant-config.cmake.in b/src/third_party/variant-1.3.0/cmake/mpark_variant-config.cmake.in new file mode 100644 index 00000000000..7f5b1c66f98 --- /dev/null +++ b/src/third_party/variant-1.3.0/cmake/mpark_variant-config.cmake.in @@ -0,0 +1,26 @@ +# MPark.Variant +# +# Copyright Michael Park, 2015-2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +# Config file for MPark.Variant +# +# `MPARK_VARIANT_INCLUDE_DIRS` - include directories +# `MPARK_VARIANT_LIBRARIES` - libraries to link against +# +# The following `IMPORTED` target is also defined: +# +# `mpark_variant` + +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/mpark_variant-targets.cmake") + +get_target_property( + MPARK_VARIANT_INCLUDE_DIRS + mpark_variant INTERFACE_INCLUDE_DIRECTORIES) + +set_and_check(MPARK_VARIANT_INCLUDE_DIRS "${MPARK_VARIANT_INCLUDE_DIRS}") +set(MPARK_VARIANT_LIBRARIES mpark_variant) diff --git a/src/third_party/variant-1.3.0/include/mpark/config.hpp b/src/third_party/variant-1.3.0/include/mpark/config.hpp new file mode 100644 index 00000000000..0d6f4adc3b4 --- /dev/null +++ b/src/third_party/variant-1.3.0/include/mpark/config.hpp @@ -0,0 +1,74 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#ifndef MPARK_CONFIG_HPP +#define MPARK_CONFIG_HPP + +// MSVC 2015 Update 3. +#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210) +#error "MPark.Variant requires C++11 support." +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifndef __has_include +#define __has_include(x) 0 +#endif + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if __has_builtin(__builtin_addressof) || \ + (defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER) +#define MPARK_BUILTIN_ADDRESSOF +#endif + +#if __has_builtin(__builtin_unreachable) +#define MPARK_BUILTIN_UNREACHABLE +#endif + +#if __has_builtin(__type_pack_element) +#define MPARK_TYPE_PACK_ELEMENT +#endif + +#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 +#define MPARK_CPP14_CONSTEXPR +#endif + +#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \ + (defined(_MSC_VER) && defined(_CPPUNWIND)) +#define MPARK_EXCEPTIONS +#endif + +#if defined(__cpp_generic_lambdas) || defined(_MSC_VER) +#define MPARK_GENERIC_LAMBDAS +#endif + +#if defined(__cpp_lib_integer_sequence) +#define MPARK_INTEGER_SEQUENCE +#endif + +#if defined(__cpp_return_type_deduction) || defined(_MSC_VER) +#define MPARK_RETURN_TYPE_DEDUCTION +#endif + +#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER) +#define MPARK_TRANSPARENT_OPERATORS +#endif + +#if defined(__cpp_variable_templates) || defined(_MSC_VER) +#define MPARK_VARIABLE_TEMPLATES +#endif + +#if !defined(__GLIBCXX__) || __has_include() // >= libstdc++-5 +#define MPARK_TRIVIALITY_TYPE_TRAITS +#endif + +#endif // MPARK_CONFIG_HPP diff --git a/src/third_party/variant-1.3.0/include/mpark/in_place.hpp b/src/third_party/variant-1.3.0/include/mpark/in_place.hpp new file mode 100644 index 00000000000..56cae131131 --- /dev/null +++ b/src/third_party/variant-1.3.0/include/mpark/in_place.hpp @@ -0,0 +1,35 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#ifndef MPARK_IN_PLACE_HPP +#define MPARK_IN_PLACE_HPP + +#include + +#include "config.hpp" + +namespace mpark { + + struct in_place_t { explicit in_place_t() = default; }; + + template + struct in_place_index_t { explicit in_place_index_t() = default; }; + + template + struct in_place_type_t { explicit in_place_type_t() = default; }; + +#ifdef MPARK_VARIABLE_TEMPLATES + constexpr in_place_t in_place{}; + + template constexpr in_place_index_t in_place_index{}; + + template constexpr in_place_type_t in_place_type{}; +#endif + +} // namespace mpark + +#endif // MPARK_IN_PLACE_HPP diff --git a/src/third_party/variant-1.3.0/include/mpark/lib.hpp b/src/third_party/variant-1.3.0/include/mpark/lib.hpp new file mode 100644 index 00000000000..c3efdd99617 --- /dev/null +++ b/src/third_party/variant-1.3.0/include/mpark/lib.hpp @@ -0,0 +1,442 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#ifndef MPARK_LIB_HPP +#define MPARK_LIB_HPP + +#include +#include +#include +#include + +#include "config.hpp" + +#define RETURN(...) \ + noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \ + return __VA_ARGS__; \ + } + +namespace mpark { + namespace lib { + template + struct identity { using type = T; }; + + inline namespace cpp14 { + template + struct array { + constexpr const T &operator[](std::size_t index) const { + return data[index]; + } + + T data[N == 0 ? 1 : N]; + }; + + template + using add_pointer_t = typename std::add_pointer::type; + + template + using common_type_t = typename std::common_type::type; + + template + using decay_t = typename std::decay::type; + + template + using enable_if_t = typename std::enable_if::type; + + template + using remove_const_t = typename std::remove_const::type; + + template + using remove_reference_t = typename std::remove_reference::type; + + template + inline constexpr T &&forward(remove_reference_t &t) noexcept { + return static_cast(t); + } + + template + inline constexpr T &&forward(remove_reference_t &&t) noexcept { + static_assert(!std::is_lvalue_reference::value, + "can not forward an rvalue as an lvalue"); + return static_cast(t); + } + + template + inline constexpr remove_reference_t &&move(T &&t) noexcept { + return static_cast &&>(t); + } + +#ifdef MPARK_INTEGER_SEQUENCE + using std::integer_sequence; + using std::index_sequence; + using std::make_index_sequence; + using std::index_sequence_for; +#else + template + struct integer_sequence { + using value_type = T; + static constexpr std::size_t size() noexcept { return sizeof...(Is); } + }; + + template + using index_sequence = integer_sequence; + + template + struct make_index_sequence_concat; + + template + struct make_index_sequence_concat, + index_sequence> + : identity> {}; + + template + struct make_index_sequence_impl; + + template + using make_index_sequence = typename make_index_sequence_impl::type; + + template + struct make_index_sequence_impl + : make_index_sequence_concat, + make_index_sequence> {}; + + template <> + struct make_index_sequence_impl<0> : identity> {}; + + template <> + struct make_index_sequence_impl<1> : identity> {}; + + template + using index_sequence_for = make_index_sequence; +#endif + + // +#ifdef MPARK_TRANSPARENT_OPERATORS + using equal_to = std::equal_to<>; +#else + struct equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) == lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using not_equal_to = std::not_equal_to<>; +#else + struct not_equal_to { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) != lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using less = std::less<>; +#else + struct less { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) < lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using greater = std::greater<>; +#else + struct greater { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) > lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using less_equal = std::less_equal<>; +#else + struct less_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) <= lib::forward(rhs)) + }; +#endif + +#ifdef MPARK_TRANSPARENT_OPERATORS + using greater_equal = std::greater_equal<>; +#else + struct greater_equal { + template + inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const + RETURN(lib::forward(lhs) >= lib::forward(rhs)) + }; +#endif + } // namespace cpp14 + + inline namespace cpp17 { + + // + template + using bool_constant = std::integral_constant; + + template + struct voider : identity {}; + + template + using void_t = typename voider::type; + + namespace detail { + namespace swappable { + + using std::swap; + + template + struct is_swappable { + private: + template (), + std::declval()))> + inline static std::true_type test(int); + + template + inline static std::false_type test(...); + + public: + static constexpr bool value = decltype(test(0))::value; + }; + + template ::value> + struct is_nothrow_swappable { + static constexpr bool value = + noexcept(swap(std::declval(), std::declval())); + }; + + template + struct is_nothrow_swappable : std::false_type {}; + + } // namespace swappable + } // namespace detail + + using detail::swappable::is_swappable; + using detail::swappable::is_nothrow_swappable; + + // +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template + inline constexpr auto invoke(F &&f, As &&... as) + RETURN(lib::forward(f)(lib::forward(as)...)) +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + template + inline constexpr auto invoke(T B::*pmv, D &&d) + RETURN(lib::forward(d).*pmv) + + template + inline constexpr auto invoke(Pmv pmv, Ptr &&ptr) + RETURN((*lib::forward(ptr)).*pmv) + + template + inline constexpr auto invoke(T B::*pmf, D &&d, As &&... as) + RETURN((lib::forward(d).*pmf)(lib::forward(as)...)) + + template + inline constexpr auto invoke(Pmf pmf, Ptr &&ptr, As &&... as) + RETURN(((*lib::forward(ptr)).*pmf)(lib::forward(as)...)) + + namespace detail { + + template + struct invoke_result {}; + + template + struct invoke_result(), std::declval()...))>, + F, + Args...> + : identity(), std::declval()...))> {}; + + } // namespace detail + + template + using invoke_result = detail::invoke_result; + + template + using invoke_result_t = typename invoke_result::type; + + namespace detail { + + template + struct is_invocable : std::false_type {}; + + template + struct is_invocable>, F, Args...> + : std::true_type {}; + + template + struct is_invocable_r : std::false_type {}; + + template + struct is_invocable_r>, + R, + F, + Args...> + : std::is_convertible, R> {}; + + } // namespace detail + + template + using is_invocable = detail::is_invocable; + + template + using is_invocable_r = detail::is_invocable_r; + + // +#ifdef MPARK_BUILTIN_ADDRESSOF + template + inline constexpr T *addressof(T &arg) { + return __builtin_addressof(arg); + } +#else + namespace detail { + + namespace has_addressof_impl { + + struct fail; + + template + inline fail operator&(T &&); + + template + inline static constexpr bool impl() { + return (std::is_class::value || std::is_union::value) && + !std::is_same()), fail>::value; + } + + } // namespace has_addressof_impl + + template + using has_addressof = bool_constant()>; + + template + inline constexpr T *addressof(T &arg, std::true_type) { + return std::addressof(arg); + } + + template + inline constexpr T *addressof(T &arg, std::false_type) { + return &arg; + } + + } // namespace detail + + template + inline constexpr T *addressof(T &arg) { + return detail::addressof(arg, detail::has_addressof{}); + } +#endif + + template + inline constexpr T *addressof(const T &&) = delete; + + } // namespace cpp17 + + template + struct remove_all_extents : identity {}; + + template + struct remove_all_extents> : remove_all_extents {}; + + template + using remove_all_extents_t = typename remove_all_extents::type; + + template + using size_constant = std::integral_constant; + + template + struct indexed_type : size_constant, identity {}; + + template + using all = std::is_same, + integer_sequence>; + +#ifdef MPARK_TYPE_PACK_ELEMENT + template + using type_pack_element_t = __type_pack_element; +#else + template + struct type_pack_element_impl { + private: + template + struct set; + + template + struct set> : indexed_type... {}; + + template + inline static std::enable_if impl(indexed_type); + + inline static std::enable_if impl(...); + + public: + using type = decltype(impl(set>{})); + }; + + template + using type_pack_element = typename type_pack_element_impl::type; + + template + using type_pack_element_t = typename type_pack_element::type; +#endif + +#ifdef MPARK_TRIVIALITY_TYPE_TRAITS + using std::is_trivially_copy_constructible; + using std::is_trivially_move_constructible; + using std::is_trivially_copy_assignable; + using std::is_trivially_move_assignable; +#else + template + struct is_trivially_copy_constructible + : bool_constant< + std::is_copy_constructible::value && __has_trivial_copy(T)> {}; + + template + struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {}; + + template + struct is_trivially_copy_assignable + : bool_constant< + std::is_copy_assignable::value && __has_trivial_assign(T)> {}; + + template + struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {}; +#endif + + template + struct dependent_type : T {}; + + template + struct push_back; + + template + using push_back_t = typename push_back::type; + + template + struct push_back, J> { + using type = index_sequence; + }; + + } // namespace lib +} // namespace mpark + +#undef RETURN + +#endif // MPARK_LIB_HPP diff --git a/src/third_party/variant-1.3.0/include/mpark/variant.hpp b/src/third_party/variant-1.3.0/include/mpark/variant.hpp new file mode 100644 index 00000000000..09ad6445bd3 --- /dev/null +++ b/src/third_party/variant-1.3.0/include/mpark/variant.hpp @@ -0,0 +1,1908 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#ifndef MPARK_VARIANT_HPP +#define MPARK_VARIANT_HPP + +/* + variant synopsis + +namespace std { + + // 20.7.2, class template variant + template + class variant { + public: + + // 20.7.2.1, constructors + constexpr variant() noexcept(see below); + variant(const variant&); + variant(variant&&) noexcept(see below); + + template constexpr variant(T&&) noexcept(see below); + + template + constexpr explicit variant(in_place_type_t, Args&&...); + + template + constexpr explicit variant( + in_place_type_t, initializer_list, Args&&...); + + template + constexpr explicit variant(in_place_index_t, Args&&...); + + template + constexpr explicit variant( + in_place_index_t, initializer_list, Args&&...); + + // 20.7.2.2, destructor + ~variant(); + + // 20.7.2.3, assignment + variant& operator=(const variant&); + variant& operator=(variant&&) noexcept(see below); + + template variant& operator=(T&&) noexcept(see below); + + // 20.7.2.4, modifiers + template + T& emplace(Args&&...); + + template + T& emplace(initializer_list, Args&&...); + + template + variant_alternative& emplace(Args&&...); + + template + variant_alternative& emplace(initializer_list, Args&&...); + + // 20.7.2.5, value status + constexpr bool valueless_by_exception() const noexcept; + constexpr size_t index() const noexcept; + + // 20.7.2.6, swap + void swap(variant&) noexcept(see below); + }; + + // 20.7.3, variant helper classes + template struct variant_size; // undefined + + template + constexpr size_t variant_size_v = variant_size::value; + + template struct variant_size; + template struct variant_size; + template struct variant_size; + + template + struct variant_size>; + + template struct variant_alternative; // undefined + + template + using variant_alternative_t = typename variant_alternative::type; + + template struct variant_alternative; + template struct variant_alternative; + template struct variant_alternative; + + template + struct variant_alternative>; + + constexpr size_t variant_npos = -1; + + // 20.7.4, value access + template + constexpr bool holds_alternative(const variant&) noexcept; + + template + constexpr variant_alternative_t>& + get(variant&); + + template + constexpr variant_alternative_t>&& + get(variant&&); + + template + constexpr variant_alternative_t> const& + get(const variant&); + + template + constexpr variant_alternative_t> const&& + get(const variant&&); + + template + constexpr T& get(variant&); + + template + constexpr T&& get(variant&&); + + template + constexpr const T& get(const variant&); + + template + constexpr const T&& get(const variant&&); + + template + constexpr add_pointer_t>> + get_if(variant*) noexcept; + + template + constexpr add_pointer_t>> + get_if(const variant*) noexcept; + + template + constexpr add_pointer_t + get_if(variant*) noexcept; + + template + constexpr add_pointer_t + get_if(const variant*) noexcept; + + // 20.7.5, relational operators + template + constexpr bool operator==(const variant&, const variant&); + + template + constexpr bool operator!=(const variant&, const variant&); + + template + constexpr bool operator<(const variant&, const variant&); + + template + constexpr bool operator>(const variant&, const variant&); + + template + constexpr bool operator<=(const variant&, const variant&); + + template + constexpr bool operator>=(const variant&, const variant&); + + // 20.7.6, visitation + template + constexpr see below visit(Visitor&&, Variants&&...); + + // 20.7.7, class monostate + struct monostate; + + // 20.7.8, monostate relational operators + constexpr bool operator<(monostate, monostate) noexcept; + constexpr bool operator>(monostate, monostate) noexcept; + constexpr bool operator<=(monostate, monostate) noexcept; + constexpr bool operator>=(monostate, monostate) noexcept; + constexpr bool operator==(monostate, monostate) noexcept; + constexpr bool operator!=(monostate, monostate) noexcept; + + // 20.7.9, specialized algorithms + template + void swap(variant&, variant&) noexcept(see below); + + // 20.7.10, class bad_variant_access + class bad_variant_access; + + // 20.7.11, hash support + template struct hash; + template struct hash>; + template <> struct hash; + +} // namespace std + +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.hpp" +#include "in_place.hpp" +#include "lib.hpp" + +namespace mpark { + +#ifdef MPARK_RETURN_TYPE_DEDUCTION + +#define AUTO auto +#define AUTO_RETURN(...) { return __VA_ARGS__; } + +#define AUTO_REFREF auto && +#define AUTO_REFREF_RETURN(...) { return __VA_ARGS__; } + +#define DECLTYPE_AUTO decltype(auto) +#define DECLTYPE_AUTO_RETURN(...) { return __VA_ARGS__; } + +#else + +#define AUTO auto +#define AUTO_RETURN(...) \ + -> lib::decay_t { return __VA_ARGS__; } + +#define AUTO_REFREF auto +#define AUTO_REFREF_RETURN(...) \ + -> decltype((__VA_ARGS__)) { \ + static_assert(std::is_reference::value, ""); \ + return __VA_ARGS__; \ + } + +#define DECLTYPE_AUTO auto +#define DECLTYPE_AUTO_RETURN(...) \ + -> decltype(__VA_ARGS__) { return __VA_ARGS__; } + +#endif + + class bad_variant_access : public std::exception { + public: + virtual const char *what() const noexcept { return "bad_variant_access"; } + }; + + [[noreturn]] inline void throw_bad_variant_access() { +#ifdef MPARK_EXCEPTIONS + throw bad_variant_access{}; +#else + std::terminate(); +#ifdef MPARK_BUILTIN_UNREACHABLE + __builtin_unreachable(); +#endif +#endif + } + + template + class variant; + + template + struct variant_size; + +#ifdef MPARK_VARIABLE_TEMPLATES + template + constexpr std::size_t variant_size_v = variant_size::value; +#endif + + template + struct variant_size : variant_size {}; + + template + struct variant_size : variant_size {}; + + template + struct variant_size : variant_size {}; + + template + struct variant_size> : lib::size_constant {}; + + template + struct variant_alternative; + + template + using variant_alternative_t = typename variant_alternative::type; + + template + struct variant_alternative + : std::add_const> {}; + + template + struct variant_alternative + : std::add_volatile> {}; + + template + struct variant_alternative + : std::add_cv> {}; + + template + struct variant_alternative> { + static_assert(I < sizeof...(Ts), + "Index out of bounds in std::variant_alternative<>"); + using type = lib::type_pack_element_t; + }; + + constexpr std::size_t variant_npos = static_cast(-1); + + namespace detail { + + constexpr std::size_t not_found = static_cast(-1); + constexpr std::size_t ambiguous = static_cast(-2); + +#ifdef MPARK_CPP14_CONSTEXPR + template + inline constexpr std::size_t find_index() { + constexpr lib::array matches = { + {std::is_same::value...} + }; + std::size_t result = not_found; + for (std::size_t i = 0; i < sizeof...(Ts); ++i) { + if (matches[i]) { + if (result != not_found) { + return ambiguous; + } + result = i; + } + } + return result; + } +#else + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t) { + return result; + } + + template + inline constexpr std::size_t find_index_impl(std::size_t result, + std::size_t idx, + bool b, + Bs... bs) { + return b ? (result != not_found ? ambiguous + : find_index_impl(idx, idx + 1, bs...)) + : find_index_impl(result, idx + 1, bs...); + } + + template + inline constexpr std::size_t find_index() { + return find_index_impl(not_found, 0, std::is_same::value...); + } +#endif + + template + using find_index_sfinae_impl = + lib::enable_if_t>; + + template + using find_index_sfinae = find_index_sfinae_impl()>; + + template + struct find_index_checked_impl : lib::size_constant { + static_assert(I != not_found, "the specified type is not found."); + static_assert(I != ambiguous, "the specified type is ambiguous."); + }; + + template + using find_index_checked = find_index_checked_impl()>; + + struct valueless_t {}; + + enum class Trait { TriviallyAvailable, Available, Unavailable }; + + template class IsTriviallyAvailable, + template class IsAvailable> + inline constexpr Trait trait() { + return IsTriviallyAvailable::value + ? Trait::TriviallyAvailable + : IsAvailable::value ? Trait::Available + : Trait::Unavailable; + } + +#ifdef MPARK_CPP14_CONSTEXPR + template + inline constexpr Trait common_trait(Traits... traits) { + Trait result = Trait::TriviallyAvailable; + for (Trait t : {traits...}) { + if (static_cast(t) > static_cast(result)) { + result = t; + } + } + return result; + } +#else + inline constexpr Trait common_trait_impl(Trait result) { return result; } + + template + inline constexpr Trait common_trait_impl(Trait result, + Trait t, + Traits... ts) { + return static_cast(t) > static_cast(result) + ? common_trait_impl(t, ts...) + : common_trait_impl(result, ts...); + } + + template + inline constexpr Trait common_trait(Traits... ts) { + return common_trait_impl(Trait::TriviallyAvailable, ts...); + } +#endif + + template + struct traits { + static constexpr Trait copy_constructible_trait = + common_trait(trait()...); + + static constexpr Trait move_constructible_trait = + common_trait(trait()...); + + static constexpr Trait copy_assignable_trait = + common_trait(copy_constructible_trait, + trait()...); + + static constexpr Trait move_assignable_trait = + common_trait(move_constructible_trait, + trait()...); + + static constexpr Trait destructible_trait = + common_trait(trait()...); + }; + + namespace access { + + struct recursive_union { +#ifdef MPARK_RETURN_TYPE_DEDUCTION + template + inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) { + return lib::forward(v).head_; + } + + template + inline static constexpr auto &&get_alt(V &&v, in_place_index_t) { + return get_alt(lib::forward(v).tail_, in_place_index_t{}); + } +#else + template + struct get_alt_impl { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v).tail_)) + }; + + template + struct get_alt_impl<0, Dummy> { + template + inline constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN(lib::forward(v).head_) + }; + + template + inline static constexpr AUTO_REFREF get_alt(V &&v, in_place_index_t) + AUTO_REFREF_RETURN(get_alt_impl{}(lib::forward(v))) +#endif + }; + + struct base { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) + AUTO_REFREF_RETURN(recursive_union::get_alt( + data(lib::forward(v)), in_place_index_t{})) + }; + + struct variant { + template + inline static constexpr AUTO_REFREF get_alt(V &&v) + AUTO_REFREF_RETURN(base::get_alt(lib::forward(v).impl_)) + }; + + } // namespace access + + namespace visitation { + + struct base { + template + inline static constexpr const T &at(const T &elem) { + return elem; + } + + template + inline static constexpr const lib::remove_all_extents_t &at( + const lib::array &elems, std::size_t i, Is... is) { + return at(elems[i], is...); + } + + template + inline static constexpr int visit_visitor_return_type_check() { + static_assert(lib::all::value...>::value, + "`mpark::visit` requires the visitor to have a single " + "return type."); + return 0; + } + + template + inline static constexpr lib::array< + lib::common_type_t...>, + sizeof...(Fs)> + make_farray(Fs &&... fs) { + using result = lib::array...>, + sizeof...(Fs)>; + return visit_visitor_return_type_check...>(), + result{{lib::forward(fs)...}}; + } + + template + struct dispatcher { + template + struct impl { + inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs) + DECLTYPE_AUTO_RETURN(lib::invoke( + static_cast(f), + access::base::get_alt(static_cast(vs))...)) + }; + }; + + template + inline static constexpr AUTO make_dispatch(lib::index_sequence) + AUTO_RETURN(&dispatcher::template impl::dispatch) + + template + inline static constexpr AUTO make_fdiagonal_impl() + AUTO_RETURN(make_dispatch( + lib::index_sequence::value...>{})) + + template + inline static constexpr AUTO make_fdiagonal_impl( + lib::index_sequence) + AUTO_RETURN(make_farray(make_fdiagonal_impl()...)) + + template + inline static constexpr /* auto * */ auto make_fdiagonal() + -> decltype(make_fdiagonal_impl( + lib::make_index_sequence::size()>{})) { + static_assert(lib::all<(lib::decay_t::size() == + lib::decay_t::size())...>::value, + "all of the variants must be the same size."); + return make_fdiagonal_impl( + lib::make_index_sequence::size()>{}); + } + +#ifdef MPARK_RETURN_TYPE_DEDUCTION + template + inline static constexpr auto make_fmatrix_impl(Is is) { + return make_dispatch(is); + } + + template + inline static constexpr auto make_fmatrix_impl( + Is, lib::index_sequence, Ls... ls) { + return make_farray(make_fmatrix_impl( + lib::push_back_t{}, ls...)...); + } + + template + inline static constexpr auto make_fmatrix() { + return make_fmatrix_impl( + lib::index_sequence<>{}, + lib::make_index_sequence::size()>{}...); + } +#else + template + struct make_fmatrix_impl { + template + struct impl; + + template + struct impl { + inline constexpr AUTO operator()() const + AUTO_RETURN(make_dispatch(Is{})) + }; + + template + struct impl, Ls...> { + inline constexpr AUTO operator()() const + AUTO_RETURN( + make_farray(impl, Ls...>{}()...)) + }; + }; + + template + inline static constexpr AUTO make_fmatrix() + AUTO_RETURN( + typename make_fmatrix_impl::template impl< + lib::index_sequence<>, + lib::make_index_sequence::size()>...>{}()) +#endif + }; // namespace base + + template + using FDiagonal = decltype(base::make_fdiagonal()); + + template + struct fdiagonal { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4268) +#endif + static constexpr FDiagonal value = + base::make_fdiagonal(); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + + template + constexpr FDiagonal fdiagonal::value; + + template + using FMatrix = decltype(base::make_fmatrix()); + + template + struct fmatrix { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4268) +#endif + static constexpr FMatrix value = + base::make_fmatrix(); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + + template + constexpr FMatrix fmatrix::value; + + struct alt { + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(base::at( + fdiagonal(vs)))...>::value, + index)(lib::forward(visitor), + as_base(lib::forward(vs))...)) + + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(base::at( + fmatrix(vs)))...>::value, + vs.index()...)(lib::forward(visitor), + as_base(lib::forward(vs))...)) + }; + + struct variant { + private: + template + struct visit_exhaustive_visitor_check { + static_assert( + lib::is_invocable::value, + "`mpark::visit` requires the visitor to be exhaustive."); + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + inline constexpr DECLTYPE_AUTO operator()(Visitor &&visitor, + Values &&... values) const + DECLTYPE_AUTO_RETURN(lib::invoke(lib::forward(visitor), + lib::forward(values)...)) +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + + template + struct value_visitor { + Visitor &&visitor_; + + template + inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const + DECLTYPE_AUTO_RETURN( + visit_exhaustive_visitor_check< + Visitor, + decltype((lib::forward(alts).value))...>{}( + lib::forward(visitor_), + lib::forward(alts).value...)) + }; + + template + inline static constexpr AUTO make_value_visitor(Visitor &&visitor) + AUTO_RETURN(value_visitor{lib::forward(visitor)}) + + public: + template + inline static constexpr DECLTYPE_AUTO visit_alt_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + alt::visit_alt_at(index, + lib::forward(visitor), + lib::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO visit_alt(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN(alt::visit_alt(lib::forward(visitor), + lib::forward(vs).impl_...)) + + template + inline static constexpr DECLTYPE_AUTO visit_value_at(std::size_t index, + Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt_at(index, + make_value_visitor(lib::forward(visitor)), + lib::forward(vs)...)) + + template + inline static constexpr DECLTYPE_AUTO visit_value(Visitor &&visitor, + Vs &&... vs) + DECLTYPE_AUTO_RETURN( + visit_alt(make_value_visitor(lib::forward(visitor)), + lib::forward(vs)...)) + }; + + } // namespace visitation + + template + struct alt { + using value_type = T; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + template + inline explicit constexpr alt(in_place_t, Args &&... args) + : value(lib::forward(args)...) {} +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + T value; + }; + + template + union recursive_union; + + template + union recursive_union {}; + +#define MPARK_VARIANT_RECURSIVE_UNION(destructible_trait, destructor) \ + template \ + union recursive_union { \ + public: \ + inline explicit constexpr recursive_union(valueless_t) noexcept \ + : dummy_{} {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t<0>, \ + Args &&... args) \ + : head_(in_place_t{}, lib::forward(args)...) {} \ + \ + template \ + inline explicit constexpr recursive_union(in_place_index_t, \ + Args &&... args) \ + : tail_(in_place_index_t{}, lib::forward(args)...) {} \ + \ + recursive_union(const recursive_union &) = default; \ + recursive_union(recursive_union &&) = default; \ + \ + destructor \ + \ + recursive_union &operator=(const recursive_union &) = default; \ + recursive_union &operator=(recursive_union &&) = default; \ + \ + private: \ + char dummy_; \ + alt head_; \ + recursive_union tail_; \ + \ + friend struct access::recursive_union; \ + } + + MPARK_VARIANT_RECURSIVE_UNION(Trait::TriviallyAvailable, + ~recursive_union() = default;); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Available, + ~recursive_union() {}); + MPARK_VARIANT_RECURSIVE_UNION(Trait::Unavailable, + ~recursive_union() = delete;); + +#undef MPARK_VARIANT_RECURSIVE_UNION + + using index_t = unsigned int; + + template + class base { + public: + inline explicit constexpr base(valueless_t tag) noexcept + : data_(tag), index_(static_cast(-1)) {} + + template + inline explicit constexpr base(in_place_index_t, Args &&... args) + : data_(in_place_index_t{}, lib::forward(args)...), + index_(I) {} + + inline constexpr bool valueless_by_exception() const noexcept { + return index_ == static_cast(-1); + } + + inline constexpr std::size_t index() const noexcept { + return valueless_by_exception() ? variant_npos : index_; + } + + protected: + using data_t = recursive_union; + + friend inline constexpr base &as_base(base &b) { return b; } + friend inline constexpr const base &as_base(const base &b) { return b; } + friend inline constexpr base &&as_base(base &&b) { return lib::move(b); } + friend inline constexpr const base &&as_base(const base &&b) { return lib::move(b); } + + friend inline constexpr data_t &data(base &b) { return b.data_; } + friend inline constexpr const data_t &data(const base &b) { return b.data_; } + friend inline constexpr data_t &&data(base &&b) { return lib::move(b).data_; } + friend inline constexpr const data_t &&data(const base &&b) { return lib::move(b).data_; } + + inline static constexpr std::size_t size() { return sizeof...(Ts); } + + data_t data_; + index_t index_; + + friend struct access::base; + friend struct visitation::base; + }; + + struct dtor { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template + inline void operator()(Alt &alt) const noexcept { alt.~Alt(); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + +#if defined(_MSC_VER) && _MSC_VER < 1910 +#define INHERITING_CTOR(type, base) \ + template \ + inline explicit constexpr type(Args &&... args) \ + : base(lib::forward(args)...) {} +#else +#define INHERITING_CTOR(type, base) using base::base; +#endif + + template + class destructor; + +#define MPARK_VARIANT_DESTRUCTOR(destructible_trait, definition, destroy) \ + template \ + class destructor, destructible_trait> \ + : public base { \ + using super = base; \ + \ + public: \ + INHERITING_CTOR(destructor, super) \ + using super::operator=; \ + \ + destructor(const destructor &) = default; \ + destructor(destructor &&) = default; \ + definition \ + destructor &operator=(const destructor &) = default; \ + destructor &operator=(destructor &&) = default; \ + \ + protected: \ + destroy \ + } + + MPARK_VARIANT_DESTRUCTOR( + Trait::TriviallyAvailable, + ~destructor() = default;, + inline void destroy() noexcept { + this->index_ = static_cast(-1); + }); + + MPARK_VARIANT_DESTRUCTOR( + Trait::Available, + ~destructor() { destroy(); }, + inline void destroy() noexcept { + if (!this->valueless_by_exception()) { + visitation::alt::visit_alt(dtor{}, *this); + } + this->index_ = static_cast(-1); + }); + + MPARK_VARIANT_DESTRUCTOR( + Trait::Unavailable, + ~destructor() = delete;, + inline void destroy() noexcept = delete;); + +#undef MPARK_VARIANT_DESTRUCTOR + + template + class constructor : public destructor { + using super = destructor; + + public: + INHERITING_CTOR(constructor, super) + using super::operator=; + + protected: +#ifndef MPARK_GENERIC_LAMBDAS + struct ctor { + template + inline void operator()(LhsAlt &lhs_alt, RhsAlt &&rhs_alt) const { + constructor::construct_alt(lhs_alt, + lib::forward(rhs_alt).value); + } + }; +#endif + + template + inline static T &construct_alt(alt &a, Args &&... args) { + ::new (static_cast(lib::addressof(a))) + alt(in_place_t{}, lib::forward(args)...); + return a.value; + } + + template + inline static void generic_construct(constructor &lhs, Rhs &&rhs) { + lhs.destroy(); + if (!rhs.valueless_by_exception()) { + visitation::alt::visit_alt_at( + rhs.index(), +#ifdef MPARK_GENERIC_LAMBDAS + [](auto &lhs_alt, auto &&rhs_alt) { + constructor::construct_alt( + lhs_alt, lib::forward(rhs_alt).value); + } +#else + ctor{} +#endif + , + lhs, + lib::forward(rhs)); + lhs.index_ = rhs.index_; + } + } + }; + + template + class move_constructor; + +#define MPARK_VARIANT_MOVE_CONSTRUCTOR(move_constructible_trait, definition) \ + template \ + class move_constructor, move_constructible_trait> \ + : public constructor> { \ + using super = constructor>; \ + \ + public: \ + INHERITING_CTOR(move_constructor, super) \ + using super::operator=; \ + \ + move_constructor(const move_constructor &) = default; \ + definition \ + ~move_constructor() = default; \ + move_constructor &operator=(const move_constructor &) = default; \ + move_constructor &operator=(move_constructor &&) = default; \ + } + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::TriviallyAvailable, + move_constructor(move_constructor &&that) = default;); + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Available, + move_constructor(move_constructor &&that) noexcept( + lib::all::value...>::value) + : move_constructor(valueless_t{}) { + this->generic_construct(*this, lib::move(that)); + }); + + MPARK_VARIANT_MOVE_CONSTRUCTOR( + Trait::Unavailable, + move_constructor(move_constructor &&) = delete;); + +#undef MPARK_VARIANT_MOVE_CONSTRUCTOR + + template + class copy_constructor; + +#define MPARK_VARIANT_COPY_CONSTRUCTOR(copy_constructible_trait, definition) \ + template \ + class copy_constructor, copy_constructible_trait> \ + : public move_constructor> { \ + using super = move_constructor>; \ + \ + public: \ + INHERITING_CTOR(copy_constructor, super) \ + using super::operator=; \ + \ + definition \ + copy_constructor(copy_constructor &&) = default; \ + ~copy_constructor() = default; \ + copy_constructor &operator=(const copy_constructor &) = default; \ + copy_constructor &operator=(copy_constructor &&) = default; \ + } + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::TriviallyAvailable, + copy_constructor(const copy_constructor &that) = default;); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Available, + copy_constructor(const copy_constructor &that) + : copy_constructor(valueless_t{}) { + this->generic_construct(*this, that); + }); + + MPARK_VARIANT_COPY_CONSTRUCTOR( + Trait::Unavailable, + copy_constructor(const copy_constructor &) = delete;); + +#undef MPARK_VARIANT_COPY_CONSTRUCTOR + + template + class assignment : public copy_constructor { + using super = copy_constructor; + + public: + INHERITING_CTOR(assignment, super) + using super::operator=; + + template + inline /* auto & */ auto emplace(Args &&... args) + -> decltype(this->construct_alt(access::base::get_alt(*this), + lib::forward(args)...)) { + this->destroy(); + auto &result = this->construct_alt(access::base::get_alt(*this), + lib::forward(args)...); + this->index_ = I; + return result; + } + + protected: +#ifndef MPARK_GENERIC_LAMBDAS + template + struct assigner { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &&that_alt) const { + self->assign_alt(this_alt, lib::forward(that_alt).value); + } + assignment *self; + }; +#endif + + template + inline void assign_alt(alt &a, Arg &&arg) { + if (this->index() == I) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + a.value = lib::forward(arg); +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } else { + struct { + void operator()(std::true_type) const { + this_->emplace(lib::forward(arg_)); + } + void operator()(std::false_type) const { + this_->emplace(T(lib::forward(arg_))); + } + assignment *this_; + Arg &&arg_; + } impl{this, lib::forward(arg)}; + impl(lib::bool_constant< + std::is_nothrow_constructible::value || + !std::is_nothrow_move_constructible::value>{}); + } + } + + template + inline void generic_assign(That &&that) { + if (this->valueless_by_exception() && that.valueless_by_exception()) { + // do nothing. + } else if (that.valueless_by_exception()) { + this->destroy(); + } else { + visitation::alt::visit_alt_at( + that.index(), +#ifdef MPARK_GENERIC_LAMBDAS + [this](auto &this_alt, auto &&that_alt) { + this->assign_alt( + this_alt, lib::forward(that_alt).value); + } +#else + assigner{this} +#endif + , + *this, + lib::forward(that)); + } + } + }; + + template + class move_assignment; + +#define MPARK_VARIANT_MOVE_ASSIGNMENT(move_assignable_trait, definition) \ + template \ + class move_assignment, move_assignable_trait> \ + : public assignment> { \ + using super = assignment>; \ + \ + public: \ + INHERITING_CTOR(move_assignment, super) \ + using super::operator=; \ + \ + move_assignment(const move_assignment &) = default; \ + move_assignment(move_assignment &&) = default; \ + ~move_assignment() = default; \ + move_assignment &operator=(const move_assignment &) = default; \ + definition \ + } + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::TriviallyAvailable, + move_assignment &operator=(move_assignment &&that) = default;); + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Available, + move_assignment & + operator=(move_assignment &&that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value)...>::value) { + this->generic_assign(lib::move(that)); + return *this; + }); + + MPARK_VARIANT_MOVE_ASSIGNMENT( + Trait::Unavailable, + move_assignment &operator=(move_assignment &&) = delete;); + +#undef MPARK_VARIANT_MOVE_ASSIGNMENT + + template + class copy_assignment; + +#define MPARK_VARIANT_COPY_ASSIGNMENT(copy_assignable_trait, definition) \ + template \ + class copy_assignment, copy_assignable_trait> \ + : public move_assignment> { \ + using super = move_assignment>; \ + \ + public: \ + INHERITING_CTOR(copy_assignment, super) \ + using super::operator=; \ + \ + copy_assignment(const copy_assignment &) = default; \ + copy_assignment(copy_assignment &&) = default; \ + ~copy_assignment() = default; \ + definition \ + copy_assignment &operator=(copy_assignment &&) = default; \ + } + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::TriviallyAvailable, + copy_assignment &operator=(const copy_assignment &that) = default;); + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Available, + copy_assignment &operator=(const copy_assignment &that) { + this->generic_assign(that); + return *this; + }); + + MPARK_VARIANT_COPY_ASSIGNMENT( + Trait::Unavailable, + copy_assignment &operator=(const copy_assignment &) = delete;); + +#undef MPARK_VARIANT_COPY_ASSIGNMENT + + template + class impl : public copy_assignment> { + using super = copy_assignment>; + + public: + INHERITING_CTOR(impl, super) + using super::operator=; + + template + inline void assign(Arg &&arg) { + this->assign_alt(access::base::get_alt(*this), + lib::forward(arg)); + } + + inline void swap(impl &that) { + if (this->valueless_by_exception() && that.valueless_by_exception()) { + // do nothing. + } else if (this->index() == that.index()) { + visitation::alt::visit_alt_at(this->index(), +#ifdef MPARK_GENERIC_LAMBDAS + [](auto &this_alt, auto &that_alt) { + using std::swap; + swap(this_alt.value, + that_alt.value); + } +#else + swapper{} +#endif + , + *this, + that); + } else { + impl *lhs = this; + impl *rhs = lib::addressof(that); + if (lhs->move_nothrow() && !rhs->move_nothrow()) { + std::swap(lhs, rhs); + } + impl tmp(lib::move(*rhs)); +#ifdef MPARK_EXCEPTIONS + // EXTENSION: When the move construction of `lhs` into `rhs` throws + // and `tmp` is nothrow move constructible then we move `tmp` back + // into `rhs` and provide the strong exception safety guarantee. + try { + this->generic_construct(*rhs, lib::move(*lhs)); + } catch (...) { + if (tmp.move_nothrow()) { + this->generic_construct(*rhs, lib::move(tmp)); + } + throw; + } +#else + this->generic_construct(*rhs, lib::move(*lhs)); +#endif + this->generic_construct(*lhs, lib::move(tmp)); + } + } + + private: +#ifndef MPARK_GENERIC_LAMBDAS + struct swapper { + template + inline void operator()(ThisAlt &this_alt, ThatAlt &that_alt) const { + using std::swap; + swap(this_alt.value, that_alt.value); + } + }; +#endif + + inline constexpr bool move_nothrow() const { + return this->valueless_by_exception() || + lib::array{ + {std::is_nothrow_move_constructible::value...} + }[this->index()]; + } + }; + + template + struct overload_leaf { + using F = lib::size_constant (*)(T); + operator F() const { return nullptr; } + }; + + template + struct overload_impl { + private: + template + struct impl; + + template + struct impl> : overload_leaf... {}; + + public: + using type = impl>; + }; + + template + using overload = typename overload_impl::type; + + template + using best_match = lib::invoke_result_t, T &&>; + + template + struct is_in_place_index : std::false_type {}; + + template + struct is_in_place_index> : std::true_type {}; + + template + struct is_in_place_type : std::false_type {}; + + template + struct is_in_place_type> : std::true_type {}; + + } // detail + + template + class variant { + static_assert(0 < sizeof...(Ts), + "variant must consist of at least one alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have an array type as an alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have a reference type as an alternative."); + + static_assert(lib::all::value...>::value, + "variant can not have a void type as an alternative."); + + public: + template < + typename Front = lib::type_pack_element_t<0, Ts...>, + lib::enable_if_t::value, int> = 0> + inline constexpr variant() noexcept( + std::is_nothrow_default_constructible::value) + : impl_(in_place_index_t<0>{}) {} + + variant(const variant &) = default; + variant(variant &&) = default; + + template < + typename Arg, + typename Decayed = lib::decay_t, + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + lib::enable_if_t::value, int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline constexpr variant(Arg &&arg) noexcept( + std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(arg)) {} + + template < + std::size_t I, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline explicit constexpr variant( + in_place_index_t, + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline explicit constexpr variant( + in_place_index_t, + std::initializer_list il, + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} + + template < + typename T, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t::value, int> = 0> + inline explicit constexpr variant( + in_place_type_t, + Args &&... args) noexcept(std::is_nothrow_constructible::value) + : impl_(in_place_index_t{}, lib::forward(args)...) {} + + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline explicit constexpr variant( + in_place_type_t, + std::initializer_list il, + Args &&... args) noexcept(std:: + is_nothrow_constructible< + T, + std::initializer_list &, + Args...>::value) + : impl_(in_place_index_t{}, il, lib::forward(args)...) {} + + ~variant() = default; + + variant &operator=(const variant &) = default; + variant &operator=(variant &&) = default; + + template , variant>::value, + int> = 0, + std::size_t I = detail::best_match::value, + typename T = lib::type_pack_element_t, + lib::enable_if_t<(std::is_assignable::value && + std::is_constructible::value), + int> = 0> + inline variant &operator=(Arg &&arg) noexcept( + (std::is_nothrow_assignable::value && + std::is_nothrow_constructible::value)) { + impl_.template assign(lib::forward(arg)); + return *this; + } + + template < + std::size_t I, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); + } + + template < + std::size_t I, + typename Up, + typename... Args, + typename T = lib::type_pack_element_t, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); + } + + template < + typename T, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t::value, int> = 0> + inline T &emplace(Args &&... args) { + return impl_.template emplace(lib::forward(args)...); + } + + template < + typename T, + typename Up, + typename... Args, + std::size_t I = detail::find_index_sfinae::value, + lib::enable_if_t &, + Args...>::value, + int> = 0> + inline T &emplace(std::initializer_list il, Args &&... args) { + return impl_.template emplace(il, lib::forward(args)...); + } + + inline constexpr bool valueless_by_exception() const noexcept { + return impl_.valueless_by_exception(); + } + + inline constexpr std::size_t index() const noexcept { + return impl_.index(); + } + + template , + Dummy>::value && + lib::dependent_type, + Dummy>::value)...>::value, + int> = 0> + inline void swap(variant &that) noexcept( + lib::all<(std::is_nothrow_move_constructible::value && + lib::is_nothrow_swappable::value)...>::value) { + impl_.swap(that.impl_); + } + + private: + detail::impl impl_; + + friend struct detail::access::variant; + friend struct detail::visitation::variant; + }; + + template + inline constexpr bool holds_alternative(const variant &v) noexcept { + return v.index() == I; + } + + template + inline constexpr bool holds_alternative(const variant &v) noexcept { + return holds_alternative::value>(v); + } + + namespace detail { + template + struct generic_get_impl { + constexpr generic_get_impl(int) {} + + constexpr AUTO_REFREF operator()(V &&v) const + AUTO_REFREF_RETURN( + access::variant::get_alt(lib::forward(v)).value) + }; + + template + inline constexpr AUTO_REFREF generic_get(V &&v) + AUTO_REFREF_RETURN(generic_get_impl( + holds_alternative(v) ? 0 : (throw_bad_variant_access(), 0))( + lib::forward(v))) + } // namespace detail + + template + inline constexpr variant_alternative_t> &get( + variant &v) { + return detail::generic_get(v); + } + + template + inline constexpr variant_alternative_t> &&get( + variant &&v) { + return detail::generic_get(lib::move(v)); + } + + template + inline constexpr const variant_alternative_t> &get( + const variant &v) { + return detail::generic_get(v); + } + + template + inline constexpr const variant_alternative_t> &&get( + const variant &&v) { + return detail::generic_get(lib::move(v)); + } + + template + inline constexpr T &get(variant &v) { + return get::value>(v); + } + + template + inline constexpr T &&get(variant &&v) { + return get::value>(lib::move(v)); + } + + template + inline constexpr const T &get(const variant &v) { + return get::value>(v); + } + + template + inline constexpr const T &&get(const variant &&v) { + return get::value>(lib::move(v)); + } + + namespace detail { + + template + inline constexpr /* auto * */ AUTO generic_get_if(V *v) noexcept + AUTO_RETURN(v && holds_alternative(*v) + ? lib::addressof(access::variant::get_alt(*v).value) + : nullptr) + + } // namespace detail + + template + inline constexpr lib::add_pointer_t>> + get_if(variant *v) noexcept { + return detail::generic_get_if(v); + } + + template + inline constexpr lib::add_pointer_t< + const variant_alternative_t>> + get_if(const variant *v) noexcept { + return detail::generic_get_if(v); + } + + template + inline constexpr lib::add_pointer_t + get_if(variant *v) noexcept { + return get_if::value>(v); + } + + template + inline constexpr lib::add_pointer_t + get_if(const variant *v) noexcept { + return get_if::value>(v); + } + + template + inline constexpr bool operator==(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::equal_to; +#ifdef MPARK_CPP14_CONSTEXPR + if (lhs.index() != rhs.index()) return false; + if (lhs.valueless_by_exception()) return true; + return variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs); +#else + return lhs.index() == rhs.index() && + (lhs.valueless_by_exception() || + variant::visit_value_at(lhs.index(), equal_to{}, lhs, rhs)); +#endif + } + + template + inline constexpr bool operator!=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::not_equal_to; +#ifdef MPARK_CPP14_CONSTEXPR + if (lhs.index() != rhs.index()) return true; + if (lhs.valueless_by_exception()) return false; + return variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs); +#else + return lhs.index() != rhs.index() || + (!lhs.valueless_by_exception() && + variant::visit_value_at(lhs.index(), not_equal_to{}, lhs, rhs)); +#endif + } + + template + inline constexpr bool operator<(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::less; +#ifdef MPARK_CPP14_CONSTEXPR + if (rhs.valueless_by_exception()) return false; + if (lhs.valueless_by_exception()) return true; + if (lhs.index() < rhs.index()) return true; + if (lhs.index() > rhs.index()) return false; + return variant::visit_value_at(lhs.index(), less{}, lhs, rhs); +#else + return !rhs.valueless_by_exception() && + (lhs.valueless_by_exception() || lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less{}, lhs, rhs))); +#endif + } + + template + inline constexpr bool operator>(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::greater; +#ifdef MPARK_CPP14_CONSTEXPR + if (lhs.valueless_by_exception()) return false; + if (rhs.valueless_by_exception()) return true; + if (lhs.index() > rhs.index()) return true; + if (lhs.index() < rhs.index()) return false; + return variant::visit_value_at(lhs.index(), greater{}, lhs, rhs); +#else + return !lhs.valueless_by_exception() && + (rhs.valueless_by_exception() || lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), greater{}, lhs, rhs))); +#endif + } + + template + inline constexpr bool operator<=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::less_equal; +#ifdef MPARK_CPP14_CONSTEXPR + if (lhs.valueless_by_exception()) return true; + if (rhs.valueless_by_exception()) return false; + if (lhs.index() < rhs.index()) return true; + if (lhs.index() > rhs.index()) return false; + return variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs); +#else + return lhs.valueless_by_exception() || + (!rhs.valueless_by_exception() && + (lhs.index() < rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at(lhs.index(), less_equal{}, lhs, rhs)))); +#endif + } + + template + inline constexpr bool operator>=(const variant &lhs, + const variant &rhs) { + using detail::visitation::variant; + using lib::greater_equal; +#ifdef MPARK_CPP14_CONSTEXPR + if (rhs.valueless_by_exception()) return true; + if (lhs.valueless_by_exception()) return false; + if (lhs.index() > rhs.index()) return true; + if (lhs.index() < rhs.index()) return false; + return variant::visit_value_at(lhs.index(), greater_equal{}, lhs, rhs); +#else + return rhs.valueless_by_exception() || + (!lhs.valueless_by_exception() && + (lhs.index() > rhs.index() || + (lhs.index() == rhs.index() && + variant::visit_value_at( + lhs.index(), greater_equal{}, lhs, rhs)))); +#endif + } + + struct monostate {}; + + inline constexpr bool operator<(monostate, monostate) noexcept { + return false; + } + + inline constexpr bool operator>(monostate, monostate) noexcept { + return false; + } + + inline constexpr bool operator<=(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator>=(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator==(monostate, monostate) noexcept { + return true; + } + + inline constexpr bool operator!=(monostate, monostate) noexcept { + return false; + } + +#ifdef MPARK_CPP14_CONSTEXPR + namespace detail { + + inline constexpr bool all(std::initializer_list bs) { + for (bool b : bs) { + if (!b) { + return false; + } + } + return true; + } + + } // namespace detail + + template + inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) { + return (detail::all({!vs.valueless_by_exception()...}) + ? (void)0 + : throw_bad_variant_access()), + detail::visitation::variant::visit_value( + lib::forward(visitor), lib::forward(vs)...); + } +#else + namespace detail { + + template + inline constexpr bool all_impl(const lib::array &bs, + std::size_t idx) { + return idx >= N || (bs[idx] && all_impl(bs, idx + 1)); + } + + template + inline constexpr bool all(const lib::array &bs) { + return all_impl(bs, 0); + } + + } // namespace detail + + template + inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs) + DECLTYPE_AUTO_RETURN( + (detail::all( + lib::array{{!vs.valueless_by_exception()...}}) + ? (void)0 + : throw_bad_variant_access()), + detail::visitation::variant::visit_value(lib::forward(visitor), + lib::forward(vs)...)) +#endif + + template + inline auto swap(variant &lhs, + variant &rhs) noexcept(noexcept(lhs.swap(rhs))) + -> decltype(lhs.swap(rhs)) { + lhs.swap(rhs); + } + + namespace detail { + + template + using enabled_type = T; + + namespace hash { + + template + constexpr bool meets_requirements() { + return std::is_copy_constructible::value && + std::is_move_constructible::value && + lib::is_invocable_r::value; + } + + template + constexpr bool is_enabled() { + using H = std::hash; + return meets_requirements() && + std::is_default_constructible::value && + std::is_copy_assignable::value && + std::is_move_assignable::value; + } + + } // namespace hash + + } // namespace detail + +#undef AUTO +#undef AUTO_RETURN + +#undef AUTO_REFREF +#undef AUTO_REFREF_RETURN + +#undef DECLTYPE_AUTO +#undef DECLTYPE_AUTO_RETURN + +} // namespace mpark + +namespace std { + + template + struct hash, + mpark::lib::enable_if_t>()...>::value>>> { + using argument_type = mpark::variant; + using result_type = std::size_t; + + inline result_type operator()(const argument_type &v) const { + using mpark::detail::visitation::variant; + std::size_t result = + v.valueless_by_exception() + ? 299792458 // Random value chosen by the universe upon creation + : variant::visit_alt( +#ifdef MPARK_GENERIC_LAMBDAS + [](const auto &alt) { + using alt_type = mpark::lib::decay_t; + using value_type = mpark::lib::remove_const_t< + typename alt_type::value_type>; + return hash{}(alt.value); + } +#else + hasher{} +#endif + , + v); + return hash_combine(result, hash{}(v.index())); + } + + private: +#ifndef MPARK_GENERIC_LAMBDAS + struct hasher { + template + inline std::size_t operator()(const Alt &alt) const { + using alt_type = mpark::lib::decay_t; + using value_type = + mpark::lib::remove_const_t; + return hash{}(alt.value); + } + }; +#endif + + static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { + return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); + } + }; + + template <> + struct hash { + using argument_type = mpark::monostate; + using result_type = std::size_t; + + inline result_type operator()(const argument_type &) const noexcept { + return 66740831; // return a fundamentally attractive random value. + } + }; + +} // namespace std + +#endif // MPARK_VARIANT_HPP diff --git a/src/third_party/variant-1.3.0/support/single-header.py b/src/third_party/variant-1.3.0/support/single-header.py new file mode 100755 index 00000000000..e6accbeae13 --- /dev/null +++ b/src/third_party/variant-1.3.0/support/single-header.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python + +# MPark.Variant +# +# Copyright Michael Park, 2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +import os.path +import re +import subprocess +import sys + +# Prints a single header version of `include/mpark/variant.hpp` to stdout. + +processed = [] + +def process(header): + result = '' + with open(header, 'r') as f: + for line in f: + p = re.compile('^#include "(.+)"') + m = p.match(line) + if m is None: + result += line + else: + g = m.group(1) + include = os.path.normpath(os.path.join(os.path.dirname(header), g)) + if include not in processed: + result += process(include) + result += '\n' + processed.append(include) + return result + +root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).strip() +result = process(os.path.join(root, 'include/mpark/variant.hpp')) + +sys.stdout.write(result) diff --git a/src/third_party/variant-1.3.0/support/wandbox.cpp b/src/third_party/variant-1.3.0/support/wandbox.cpp new file mode 100644 index 00000000000..1eb8d02bf16 --- /dev/null +++ b/src/third_party/variant-1.3.0/support/wandbox.cpp @@ -0,0 +1,19 @@ +// MPark.Variant +// +// Copyright Michael Park, 2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +#include + +int main() { + std::vector> vs = { 101, "+", 202, "==", 303 }; + for (const auto& v : vs) { + mpark::visit([](const auto& x) { std::cout << x << ' '; }, v); + } +} diff --git a/src/third_party/variant-1.3.0/support/wandbox.py b/src/third_party/variant-1.3.0/support/wandbox.py new file mode 100755 index 00000000000..01c95e6dae0 --- /dev/null +++ b/src/third_party/variant-1.3.0/support/wandbox.py @@ -0,0 +1,106 @@ +#! /usr/bin/env python + +# MPark.Variant +# +# This script uploads a directory to Wandbox (http://melpon.org/wandbox), +# which is an online compiler environment, and prints a permalink to the +# uploaded code. We use this to provide a "Try it online" version of the +# library to make the barrier to entry as low as possible. +# +# This script was adapted from the script proposed in +# https://github.com/melpon/wandbox/issues/153. +# +# To know how to use this script: ./wandbox.py --help +# +# Copyright Louis Dionne 2015 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) +# +# Copyright Michael Park, 2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +import argparse +import fnmatch +import json +import os +import re +import urllib2 + +# Post the given JSON data to Wandbox's API, and return the result +# as a JSON object. +def upload(options): + request = urllib2.Request('http://melpon.org/wandbox/api/compile.json') + request.add_header('Content-Type', 'application/json') + response = urllib2.urlopen(request, json.dumps(options)) + return json.loads(response.read()) + +# Returns a list of the '.hpp' headers in the given directory and in +# subdirectories. +# +# The path must be absolute, and the returned paths are all absolute too. +def headers(path): + return [ + os.path.join(dir, file) + for (dir, _, files) in os.walk(path) + for file in fnmatch.filter(files, "*.hpp") + ] + +def main(): + parser = argparse.ArgumentParser(description= + """Upload a directory to Wandbox (http://melpon.org/wandbox). + + On success, the program prints a permalink to the uploaded + directory on Wandbox and returns 0. On error, it prints the + response from the Wandbox API and returns 1. + + Note that the comments are stripped from all the headers in the + uploaded directory. + """ + ) + parser.add_argument('directory', type=str, help= + """A directory to upload to Wandbox. + + The path may be either absolute or relative to the current directory. + However, the names of the files uploaded to Wandbox will all be + relative to this directory. This way, one can easily specify the + directory to be '/some/project/include', and the uploaded files + will be uploaded as-if they were rooted at '/some/project/include' + """) + parser.add_argument('main', type=str, help= + """The main source file. + + The path may be either absolute or relative to the current directory. + """ + ) + args = parser.parse_args() + directory = os.path.abspath(args.directory) + if not os.path.exists(directory): + raise Exception("'%s' is not a valid directory" % args.directory) + + cpp = os.path.abspath(args.main) + if not os.path.exists(cpp): + raise Exception("'%s' is not a valid file name" % args.main) + + response = upload({ + 'code': open(cpp).read().strip(), + 'codes': [{ + 'file': os.path.relpath(header, directory).replace('\\', '/'), + 'code': open(header).read().strip() + } for header in headers(directory)], + 'options': 'warning,optimize,c++14', + 'compiler': 'clang-4.0.0', + 'save': True, + 'compiler-option-raw': '-I.' + }) + + if response['status'] == '0': + print response['url'] + return 0 + else: + print response + return 1 + +exit(main()) diff --git a/src/third_party/variant-1.3.0/test/README.md b/src/third_party/variant-1.3.0/test/README.md new file mode 100644 index 00000000000..45accac599e --- /dev/null +++ b/src/third_party/variant-1.3.0/test/README.md @@ -0,0 +1,49 @@ +# MPark.Variant + +> __C++17__ `std::variant` for __C++11__/__14__/__17__ + +[![release][badge.release]][release] +[![header][badge.header]][header] +[![travis][badge.travis]][travis] +[![appveyor][badge.appveyor]][appveyor] +[![license][badge.license]][license] +[![godbolt][badge.godbolt]][godbolt] +[![wandbox][badge.wandbox]][wandbox] + +[badge.release]: https://img.shields.io/github/release/mpark/variant.svg +[badge.header]: https://img.shields.io/badge/single%20header-master-blue.svg +[badge.travis]: https://travis-ci.org/mpark/variant.svg?branch=master +[badge.appveyor]: https://ci.appveyor.com/api/projects/status/github/mpark/variant?branch=master&svg=true +[badge.license]: https://img.shields.io/badge/license-boost-blue.svg +[badge.godbolt]: https://img.shields.io/badge/try%20it-on%20godbolt-222266.svg +[badge.wandbox]: https://img.shields.io/badge/try%20it-on%20wandbox-5cb85c.svg + +[release]: https://github.com/mpark/variant/releases/latest +[header]: https://github.com/mpark/variant/blob/single-header/master/variant.hpp +[travis]: https://travis-ci.org/mpark/variant +[appveyor]: https://ci.appveyor.com/project/mpark/variant +[license]: https://github.com/mpark/variant/blob/master/LICENSE.md +[godbolt]: https://godbolt.org/g/1qYDAK +[wandbox]: https://wandbox.org/permlink/QV3gZ2KQQNwgoFIB + +## Test + +This directory contains the tests for __MPark.Variant__. + +## CMake Variables + + - __`MPARK_VARIANT_EXCEPTIONS`__:`BOOL` (__default__: `ON`) + + Build the tests with exceptions support. + +## Build / Run + +Execute the following commands from the top-level directory: + +```bash +mkdir build +cd build +cmake -DMPARK_VARIANT_INCLUDE_TESTS="mpark;libc++" .. +cmake --build . +ctest --output-on-failure +``` diff --git a/src/third_party/variant-1.3.0/test/assign.copy.cpp b/src/third_party/variant-1.3.0/test/assign.copy.cpp new file mode 100644 index 00000000000..3133f554609 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/assign.copy.cpp @@ -0,0 +1,51 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include "util.hpp" + +TEST(Assign_Copy, SameType) { + struct Obj { + constexpr Obj() {} + Obj(const Obj &) noexcept { EXPECT_TRUE(false); } + Obj(Obj &&) = default; + Obj &operator=(const Obj &) noexcept { EXPECT_TRUE(true); return *this; } + Obj &operator=(Obj &&) = delete; + }; + // `v`, `w`. + mpark::variant v, w; + // copy assignment. + v = w; +} + +TEST(Assign_Copy, DiffType) { + struct Obj { + constexpr Obj() {} + Obj(const Obj &) noexcept { EXPECT_TRUE(true); } + Obj(Obj &&) = default; + Obj &operator=(const Obj &) noexcept { EXPECT_TRUE(false); return *this; } + Obj &operator=(Obj &&) = delete; + }; + // `v`, `w`. + mpark::variant v(42), w; + // copy assignment. + v = w; +} + +#ifdef MPARK_EXCEPTIONS +TEST(Assign_Copy, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + mpark::variant w(42); + w = v; + EXPECT_TRUE(w.valueless_by_exception()); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/assign.fwd.cpp b/src/third_party/variant-1.3.0/test/assign.fwd.cpp new file mode 100644 index 00000000000..83547f28091 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/assign.fwd.cpp @@ -0,0 +1,133 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include +#include + +#include + +#include "util.hpp" + +TEST(Assign_Fwd, SameType) { + mpark::variant v(101); + EXPECT_EQ(101, mpark::get(v)); + v = 202; + EXPECT_EQ(202, mpark::get(v)); +} + +TEST(Assign_Fwd, SameTypeFwd) { + mpark::variant v(1.1); + EXPECT_EQ(1, mpark::get(v)); + v = 2.2; + EXPECT_EQ(2, mpark::get(v)); +} + +TEST(Assign_Fwd, DiffType) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + v = "42"; + EXPECT_EQ("42", mpark::get(v)); +} + +TEST(Assign_Fwd, DiffTypeFwd) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + v = "42"; + EXPECT_EQ("42", mpark::get(v)); +} + +TEST(Assign_Fwd, ExactMatch) { + mpark::variant v; + v = std::string("hello"); + EXPECT_EQ("hello", mpark::get(v)); +} + +TEST(Assign_Fwd, BetterMatch) { + mpark::variant v; + // `char` -> `int` is better than `char` -> `double` + v = 'x'; + EXPECT_EQ(static_cast('x'), mpark::get(v)); +} + +TEST(Assign_Fwd, NoMatch) { + struct x {}; + static_assert(!std::is_assignable, x>{}, + "variant v; v = x;"); +} + +TEST(Assign_Fwd, Ambiguous) { + static_assert(!std::is_assignable, int>{}, + "variant v; v = 42;"); +} + +TEST(Assign_Fwd, SameTypeOptimization) { + mpark::variant v("hello world!"); + // Check `v`. + const std::string &x = mpark::get(v); + EXPECT_EQ("hello world!", x); + // Save the "hello world!"'s capacity. + auto capacity = x.capacity(); + // Use `std::string::operator=(const char *)` to assign into `v`. + v = "hello"; + // Check `v`. + const std::string &y = mpark::get(v); + EXPECT_EQ("hello", y); + // Since "hello" is shorter than "hello world!", we should have preserved the + // existing capacity of the string!. + EXPECT_EQ(capacity, y.capacity()); +} + +#ifdef MPARK_EXCEPTIONS +TEST(Assign_Fwd, ThrowOnAssignment) { + mpark::variant v( + mpark::in_place_type_t{}); + // Since `variant` is already in `move_thrower_t`, assignment optimization + // kicks and we simply invoke + // `move_thrower_t &operator=(move_thrower_t &&);` which throws. + EXPECT_THROW(v = move_thrower_t{}, MoveAssignment); + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_EQ(1u, v.index()); + // We can still assign into a variant in an invalid state. + v = 42; + // Check `v`. + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_EQ(42, mpark::get(v)); +} +#endif + +#if 0 +TEST(Assign_Fwd, ThrowOnTemporaryConstruction) { + mpark::variant v(42); + // Since `copy_thrower_t`'s copy constructor always throws, we will fail to + // construct the variant. This results in our variant staying in + // its original state. + copy_thrower_t copy_thrower{}; + EXPECT_THROW(v = copy_thrower, CopyConstruction); + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_EQ(0u, v.index()); + EXPECT_EQ(42, mpark::get(v)); +} + +TEST(Assign_Fwd, ThrowOnVariantConstruction) { + mpark::variant v(42); + // Since `move_thrower_t`'s copy constructor never throws, we successfully + // construct the temporary object by copying `move_thrower_t`. We then + // proceed to move the temporary object into our variant, at which point + // `move_thrower_t`'s move constructor throws. This results in our `variant` + // transitioning into the invalid state. + move_thrower_t move_thrower; + EXPECT_THROW(v = move_thrower, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + // We can still assign into a variant in an invalid state. + v = 42; + // Check `v`. + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_EQ(42, mpark::get(v)); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/assign.move.cpp b/src/third_party/variant-1.3.0/test/assign.move.cpp new file mode 100644 index 00000000000..65057d0a654 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/assign.move.cpp @@ -0,0 +1,53 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include "util.hpp" + +namespace lib = mpark::lib; + +TEST(Assign_Move, SameType) { + struct Obj { + constexpr Obj() {} + Obj(const Obj &) = delete; + Obj(Obj &&) noexcept { EXPECT_TRUE(false); } + Obj &operator=(const Obj &) = delete; + Obj &operator=(Obj &&) noexcept { EXPECT_TRUE(true); return *this; } + }; + // `v`, `w`. + mpark::variant v, w; + // move assignment. + v = lib::move(w); +} + +TEST(Assign_Move, DiffType) { + struct Obj { + constexpr Obj() {} + Obj(const Obj &) = delete; + Obj(Obj &&) noexcept { EXPECT_TRUE(true); } + Obj &operator=(const Obj &) = delete; + Obj &operator=(Obj &&) noexcept { EXPECT_TRUE(false); return *this; } + }; + // `v`, `w`. + mpark::variant v(42), w; + // move assignment. + v = lib::move(w); +} + +#ifdef MPARK_EXCEPTIONS +TEST(Assign_Move, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + mpark::variant w(42); + w = lib::move(v); + EXPECT_TRUE(w.valueless_by_exception()); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/ctor.copy.cpp b/src/third_party/variant-1.3.0/test/ctor.copy.cpp new file mode 100644 index 00000000000..7efcd868323 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/ctor.copy.cpp @@ -0,0 +1,44 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +#include "util.hpp" + +TEST(Ctor_Copy, Value) { + // `v` + mpark::variant v("hello"); + EXPECT_EQ("hello", mpark::get(v)); + // `w` + mpark::variant w(v); + EXPECT_EQ("hello", mpark::get(w)); + // Check `v` + EXPECT_EQ("hello", mpark::get(v)); + + /* constexpr */ { + // `cv` + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // `cw` + constexpr mpark::variant cw(cv); + static_assert(42 == mpark::get(cw), ""); + } +} + +#ifdef MPARK_EXCEPTIONS +TEST(Ctor_Copy, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + mpark::variant w(v); + EXPECT_TRUE(w.valueless_by_exception()); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/ctor.default.cpp b/src/third_party/variant-1.3.0/test/ctor.default.cpp new file mode 100644 index 00000000000..5fb284b22a6 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/ctor.default.cpp @@ -0,0 +1,22 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +TEST(Ctor_Default, Variant) { + mpark::variant v; + EXPECT_EQ(0, mpark::get<0>(v)); + + /* constexpr */ { + constexpr mpark::variant cv{}; + static_assert(0 == mpark::get<0>(cv), ""); + } +} diff --git a/src/third_party/variant-1.3.0/test/ctor.fwd.cpp b/src/third_party/variant-1.3.0/test/ctor.fwd.cpp new file mode 100644 index 00000000000..45f835685d1 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/ctor.fwd.cpp @@ -0,0 +1,52 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +TEST(Ctor_Fwd, Direct) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + } +} + +TEST(Ctor_Fwd, DirectConversion) { + mpark::variant v("42"); + EXPECT_EQ("42", mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv(1.1); + static_assert(1 == mpark::get(cv), ""); + } +} + +TEST(Ctor_Fwd, CopyInitialization) { + mpark::variant v = 42; + EXPECT_EQ(42, mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv = 42; + static_assert(42 == mpark::get(cv), ""); + } +} + +TEST(Ctor_Fwd, CopyInitializationConversion) { + mpark::variant v = "42"; + EXPECT_EQ("42", mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv = 1.1; + static_assert(1 == mpark::get(cv), ""); + } +} diff --git a/src/third_party/variant-1.3.0/test/ctor.in_place.cpp b/src/third_party/variant-1.3.0/test/ctor.in_place.cpp new file mode 100644 index 00000000000..072f3d6a182 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/ctor.in_place.cpp @@ -0,0 +1,78 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +TEST(Ctor_InPlace, IndexDirect) { + mpark::variant v(mpark::in_place_index_t<0>{}, 42); + EXPECT_EQ(42, mpark::get<0>(v)); + + /* constexpr */ { + constexpr mpark::variant cv(mpark::in_place_index_t<0>{}, + 42); + static_assert(42 == mpark::get<0>(cv), ""); + } +} + +TEST(Ctor_InPlace, IndexDirectDuplicate) { + mpark::variant v(mpark::in_place_index_t<0>{}, 42); + EXPECT_EQ(42, mpark::get<0>(v)); + + /* constexpr */ { + constexpr mpark::variant cv(mpark::in_place_index_t<0>{}, 42); + static_assert(42 == mpark::get<0>(cv), ""); + } +} + +TEST(Ctor_InPlace, IndexConversion) { + mpark::variant v(mpark::in_place_index_t<1>{}, "42"); + EXPECT_EQ("42", mpark::get<1>(v)); + + /* constexpr */ { + constexpr mpark::variant cv(mpark::in_place_index_t<0>{}, + 1.1); + static_assert(1 == mpark::get<0>(cv), ""); + } +} + +TEST(Ctor_InPlace, IndexInitializerList) { + mpark::variant v(mpark::in_place_index_t<1>{}, {'4', '2'}); + EXPECT_EQ("42", mpark::get<1>(v)); +} + +TEST(Ctor_InPlace, TypeDirect) { + mpark::variant v(mpark::in_place_type_t{}, + "42"); + EXPECT_EQ("42", mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv( + mpark::in_place_type_t{}, 42); + static_assert(42 == mpark::get(cv), ""); + } +} + +TEST(Ctor_InPlace, TypeConversion) { + mpark::variant v(mpark::in_place_type_t{}, 42.5); + EXPECT_EQ(42, mpark::get(v)); + + /* constexpr */ { + constexpr mpark::variant cv( + mpark::in_place_type_t{}, 42.5); + static_assert(42 == mpark::get(cv), ""); + } +} + +TEST(Ctor_InPlace, TypeInitializerList) { + mpark::variant v(mpark::in_place_type_t{}, + {'4', '2'}); + EXPECT_EQ("42", mpark::get(v)); +} diff --git a/src/third_party/variant-1.3.0/test/ctor.move.cpp b/src/third_party/variant-1.3.0/test/ctor.move.cpp new file mode 100644 index 00000000000..b542b971621 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/ctor.move.cpp @@ -0,0 +1,46 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +#include "util.hpp" + +namespace lib = mpark::lib; + +TEST(Ctor_Move, Value) { + // `v` + mpark::variant v("hello"); + EXPECT_EQ("hello", mpark::get(v)); + // `w` + mpark::variant w(lib::move(v)); + EXPECT_EQ("hello", mpark::get(w)); + // Check `v` + EXPECT_TRUE(mpark::get(v).empty()); + + /* constexpr */ { + // `cv` + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // `cw` + constexpr mpark::variant cw(lib::move(cv)); + static_assert(42 == mpark::get(cw), ""); + } +} + +#ifdef MPARK_EXCEPTIONS +TEST(Ctor_Move, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + mpark::variant w(lib::move(v)); + EXPECT_TRUE(w.valueless_by_exception()); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/dtor.cpp b/src/third_party/variant-1.3.0/test/dtor.cpp new file mode 100644 index 00000000000..6519ebcd724 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/dtor.cpp @@ -0,0 +1,26 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +struct Obj { + Obj(bool &dtor_called) : dtor_called_(dtor_called) {} + ~Obj() { dtor_called_ = true; } + bool &dtor_called_; +}; // Obj + +TEST(Dtor, Value) { + bool dtor_called = false; + // Construct/Destruct `Obj`. + { + mpark::variant v(mpark::in_place_type_t{}, dtor_called); + } + // Check that the destructor was called. + EXPECT_TRUE(dtor_called); +} diff --git a/src/third_party/variant-1.3.0/test/get.cpp b/src/third_party/variant-1.3.0/test/get.cpp new file mode 100644 index 00000000000..82fb23b145a --- /dev/null +++ b/src/third_party/variant-1.3.0/test/get.cpp @@ -0,0 +1,141 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include "util.hpp" + +namespace lib = mpark::lib; + +TEST(Get, HoldsAlternative) { + mpark::variant v(42); + EXPECT_TRUE(mpark::holds_alternative<0>(v)); + EXPECT_FALSE(mpark::holds_alternative<1>(v)); + EXPECT_TRUE(mpark::holds_alternative(v)); + EXPECT_FALSE(mpark::holds_alternative(v)); + + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(mpark::holds_alternative<0>(cv), ""); + static_assert(!mpark::holds_alternative<1>(cv), ""); + static_assert(mpark::holds_alternative(cv), ""); + static_assert(!mpark::holds_alternative(cv), ""); + } +} + +TEST(Get, MutVarMutType) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(LRef, get_qual(mpark::get(v))); + EXPECT_EQ(RRef, get_qual(mpark::get(lib::move(v)))); +} + +TEST(Get, MutVarConstType) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, get_qual(mpark::get(v))); + EXPECT_EQ(ConstRRef, get_qual(mpark::get(lib::move(v)))); +} + +TEST(Get, ConstVarMutType) { + const mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, get_qual(mpark::get(v))); + EXPECT_EQ(ConstRRef, get_qual(mpark::get(lib::move(v)))); + + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // Check qualifier. + static_assert(ConstLRef == get_qual(mpark::get(cv)), ""); + static_assert(ConstRRef == get_qual(mpark::get(lib::move(cv))), ""); + } +} + +TEST(Get, ConstVarConstType) { + const mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, get_qual(mpark::get(v))); + EXPECT_EQ(ConstRRef, get_qual(mpark::get(lib::move(v)))); + + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // Check qualifier. + static_assert(ConstLRef == get_qual(mpark::get(cv)), ""); + static_assert(ConstRRef == get_qual(mpark::get(lib::move(cv))), + ""); + } +} + +#ifdef MPARK_EXCEPTIONS +TEST(Get, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_THROW(mpark::get(v), mpark::bad_variant_access); + EXPECT_THROW(mpark::get(v), mpark::bad_variant_access); +} +#endif + +TEST(GetIf, MutVarMutType) { + mpark::variant v(42); + EXPECT_EQ(42, *mpark::get_if(&v)); + // Check qualifier. + EXPECT_EQ(Ptr, get_qual(mpark::get_if(&v))); +} + +TEST(GetIf, MutVarConstType) { + mpark::variant v(42); + EXPECT_EQ(42, *mpark::get_if(&v)); + // Check qualifier. + EXPECT_EQ(ConstPtr, get_qual(mpark::get_if(&v))); +} + +TEST(GetIf, ConstVarMutType) { + const mpark::variant v(42); + EXPECT_EQ(42, *mpark::get_if(&v)); + // Check qualifier. + EXPECT_EQ(ConstPtr, get_qual(mpark::get_if(&v))); + + /* constexpr */ { + static constexpr mpark::variant cv(42); + static_assert(42 == *mpark::get_if(&cv), ""); + // Check qualifier. + static_assert(ConstPtr == get_qual(mpark::get_if(&cv)), ""); + } +} + +TEST(GetIf, ConstVarConstType) { + const mpark::variant v(42); + EXPECT_EQ(42, *mpark::get_if(&v)); + // Check qualifier. + EXPECT_EQ(ConstPtr, get_qual(mpark::get_if(&v))); + + /* constexpr */ { + static constexpr mpark::variant cv(42); + static_assert(42 == *mpark::get_if(&cv), ""); + // Check qualifier. + static_assert(ConstPtr == get_qual(mpark::get_if(&cv)), ""); + } +} + +#ifdef MPARK_EXCEPTONS +TEST(GetIf, ValuelessByException) { + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_EQ(nullptr, mpark::get_if(&v)); + EXPECT_EQ(nullptr, mpark::get_if(&v)); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/hash.cpp b/src/third_party/variant-1.3.0/test/hash.cpp new file mode 100644 index 00000000000..4b4db44dbdb --- /dev/null +++ b/src/third_party/variant-1.3.0/test/hash.cpp @@ -0,0 +1,31 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +TEST(Hash, Monostate) { + mpark::variant v(mpark::monostate{}); + // Construct hash function objects. + std::hash monostate_hash; + std::hash> variant_hash; + // Check the hash. + EXPECT_NE(monostate_hash(mpark::monostate{}), variant_hash(v)); +} + +TEST(Hash, String) { + mpark::variant v("hello"); + EXPECT_EQ("hello", mpark::get(v)); + // Construct hash function objects. + std::hash string_hash; + std::hash> variant_hash; + // Check the hash. + EXPECT_NE(string_hash("hello"), variant_hash(v)); +} diff --git a/src/third_party/variant-1.3.0/test/intro.cpp b/src/third_party/variant-1.3.0/test/intro.cpp new file mode 100644 index 00000000000..c93a9fab441 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/intro.cpp @@ -0,0 +1,64 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include +#include + +#include + +TEST(Variant, Intro) { + // direct initialization. + mpark::variant v("hello world!"); + + // direct access via reference. + EXPECT_EQ("hello world!", mpark::get(v)); + + // bad access. +#ifdef MPARK_EXCEPTIONS + EXPECT_THROW(mpark::get(v), mpark::bad_variant_access); +#endif + + // copy construction. + mpark::variant w(v); + + // direct access via pointer. + EXPECT_FALSE(mpark::get_if(&w)); + EXPECT_TRUE(mpark::get_if(&w)); + + // diff-type assignment. + v = 42; + + struct unary { + int operator()(int) const { return 0; } + int operator()(const std::string &) const { return 1; } + }; // unary + + // single visitation. + EXPECT_EQ(0, mpark::visit(unary{}, v)); + + // same-type assignment. + w = "hello"; + + EXPECT_NE(v, w); + + // make `w` equal to `v`. + w = 42; + + EXPECT_EQ(v, w); + + struct binary { + int operator()(int, int) const { return 0; } + int operator()(int, const std::string &) const { return 1; } + int operator()(const std::string &, int) const { return 2; } + int operator()(const std::string &, const std::string &) const { return 3; } + }; // binary + + // binary visitation. + EXPECT_EQ(0, mpark::visit(binary{}, v, w)); +} diff --git a/src/third_party/variant-1.3.0/test/json.cpp b/src/third_party/variant-1.3.0/test/json.cpp new file mode 100644 index 00000000000..c265415e0cc --- /dev/null +++ b/src/third_party/variant-1.3.0/test/json.cpp @@ -0,0 +1,49 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include +#include +#include +#include + +#include + +struct JsonIsh { + JsonIsh(bool b) : data(b) {} + JsonIsh(int i) : data(i) {} + JsonIsh(std::string s) : data(std::move(s)) {} + JsonIsh(std::vector v) : data(std::move(v)) {} + + mpark::variant> data; +}; + +TEST(Variant, Bool) { + JsonIsh json_ish = true; + EXPECT_TRUE(mpark::get(json_ish.data)); + json_ish = false; + EXPECT_FALSE(mpark::get(json_ish.data)); +} + +TEST(Variant, Int) { + JsonIsh json_ish = 42; + EXPECT_EQ(42, mpark::get(json_ish.data)); +} + +TEST(Variant, String) { + JsonIsh json_ish = std::string("hello"); + EXPECT_EQ("hello", mpark::get(json_ish.data)); +} + +TEST(Variant, Array) { + JsonIsh json_ish = std::vector{true, 42, std::string("world")}; + const auto &array = mpark::get>(json_ish.data); + EXPECT_TRUE(mpark::get(array[0].data)); + EXPECT_EQ(42, mpark::get(array[1].data)); + EXPECT_EQ("world", mpark::get(array[2].data)); +} diff --git a/src/third_party/variant-1.3.0/test/libcxx.sh b/src/third_party/variant-1.3.0/test/libcxx.sh new file mode 100755 index 00000000000..13ea7ba17ab --- /dev/null +++ b/src/third_party/variant-1.3.0/test/libcxx.sh @@ -0,0 +1,29 @@ +# MPark.Variant +# +# Copyright Michael Park, 2015-2017 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#!/usr/bin/env bash + +set -e + +trap "cd ${MPARK_VARIANT_LIBCXX_SOURCE_DIR} && git checkout ." EXIT + +cat < ${MPARK_VARIANT_LIBCXX_SOURCE_DIR}/include/variant +#define mpark std +#define MPARK_IN_PLACE_HPP +$(cat ${MPARK_VARIANT_SOURCE_DIR}/include/mpark/variant.hpp) +#undef MPARK_IN_PLACE_HPP +#undef mpark +EOF + +${MPARK_VARIANT_LIT} \ + -v \ + --param color_diagnostics \ + --param cxx_under_test="${MPARK_VARIANT_CXX_COMPILER}" \ + --param compile_flags=-I${MPARK_VARIANT_SOURCE_DIR}/include/mpark \ + --param std=c++17 \ + --param libcxx_site_config=${MPARK_VARIANT_LIBCXX_SITE_CONFIG} \ + ${MPARK_VARIANT_LIBCXX_SOURCE_DIR}/test/std/utilities/variant \ diff --git a/src/third_party/variant-1.3.0/test/mod.cpp b/src/third_party/variant-1.3.0/test/mod.cpp new file mode 100644 index 00000000000..41fb1ff8085 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/mod.cpp @@ -0,0 +1,60 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +TEST(Assign_Emplace, IndexDirect) { + mpark::variant v; + v.emplace<1>("42"); + EXPECT_EQ("42", mpark::get<1>(v)); +} + +TEST(Assign_Emplace, IndexDirectDuplicate) { + mpark::variant v; + v.emplace<1>(42); + EXPECT_EQ(42, mpark::get<1>(v)); +} + +TEST(Assign_Emplace, IndexConversion) { + mpark::variant v; + v.emplace<1>("42"); + EXPECT_EQ("42", mpark::get<1>(v)); +} + +TEST(Assign_Emplace, IndexConversionDuplicate) { + mpark::variant v; + v.emplace<1>(1.1); + EXPECT_EQ(1, mpark::get<1>(v)); +} + +TEST(Assign_Emplace, IndexInitializerList) { + mpark::variant v; + v.emplace<1>({'4', '2'}); + EXPECT_EQ("42", mpark::get<1>(v)); +} + +TEST(Assign_Emplace, TypeDirect) { + mpark::variant v; + v.emplace("42"); + EXPECT_EQ("42", mpark::get(v)); +} + +TEST(Assign_Emplace, TypeConversion) { + mpark::variant v; + v.emplace(1.1); + EXPECT_EQ(1, mpark::get(v)); +} + +TEST(Assign_Emplace, TypeInitializerList) { + mpark::variant v; + v.emplace({'4', '2'}); + EXPECT_EQ("42", mpark::get(v)); +} diff --git a/src/third_party/variant-1.3.0/test/relops.cpp b/src/third_party/variant-1.3.0/test/relops.cpp new file mode 100644 index 00000000000..759eb4f0ce3 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/relops.cpp @@ -0,0 +1,197 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include "util.hpp" + +TEST(Rel, SameTypeSameValue) { + mpark::variant v(0), w(0); + // `v` op `w` + EXPECT_TRUE(v == w); + EXPECT_FALSE(v != w); + EXPECT_FALSE(v < w); + EXPECT_FALSE(v > w); + EXPECT_TRUE(v <= w); + EXPECT_TRUE(v >= w); + // `w` op `v` + EXPECT_TRUE(w == v); + EXPECT_FALSE(w != v); + EXPECT_FALSE(w < v); + EXPECT_FALSE(w > v); + EXPECT_TRUE(w <= v); + EXPECT_TRUE(w >= v); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(0), cw(0); + // `cv` op `cw` + static_assert(cv == cw, ""); + static_assert(!(cv != cw), ""); + static_assert(!(cv < cw), ""); + static_assert(!(cv > cw), ""); + static_assert(cv <= cw, ""); + static_assert(cv >= cw, ""); + // `cw` op `cv` + static_assert(cw == cv, ""); + static_assert(!(cw != cv), ""); + static_assert(!(cw < cv), ""); + static_assert(!(cw > cv), ""); + static_assert(cw <= cv, ""); + static_assert(cw >= cv, ""); + } +#endif +} + +TEST(Rel, SameTypeDiffValue) { + mpark::variant v(0), w(1); + // `v` op `w` + EXPECT_FALSE(v == w); + EXPECT_TRUE(v != w); + EXPECT_TRUE(v < w); + EXPECT_FALSE(v > w); + EXPECT_TRUE(v <= w); + EXPECT_FALSE(v >= w); + // `w` op `v` + EXPECT_FALSE(w == v); + EXPECT_TRUE(w != v); + EXPECT_FALSE(w < v); + EXPECT_TRUE(w > v); + EXPECT_FALSE(w <= v); + EXPECT_TRUE(w >= v); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(0), cw(1); + // `cv` op `cw` + static_assert(!(cv == cw), ""); + static_assert(cv != cw, ""); + static_assert(cv < cw, ""); + static_assert(!(cv > cw), ""); + static_assert(cv <= cw, ""); + static_assert(!(cv >= cw), ""); + // `cw` op `cv` + static_assert(!(cw == cv), ""); + static_assert(cw != cv, ""); + static_assert(!(cw < cv), ""); + static_assert(cw > cv, ""); + static_assert(!(cw <= cv), ""); + static_assert(cw >= cv, ""); + } +#endif +} + +TEST(Rel, DiffTypeSameValue) { + mpark::variant v(0), w(0u); + // `v` op `w` + EXPECT_FALSE(v == w); + EXPECT_TRUE(v != w); + EXPECT_TRUE(v < w); + EXPECT_FALSE(v > w); + EXPECT_TRUE(v <= w); + EXPECT_FALSE(v >= w); + // `w` op `v` + EXPECT_FALSE(w == v); + EXPECT_TRUE(w != v); + EXPECT_FALSE(w < v); + EXPECT_TRUE(w > v); + EXPECT_FALSE(w <= v); + EXPECT_TRUE(w >= v); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(0), cw(0u); + // `cv` op `cw` + static_assert(!(cv == cw), ""); + static_assert(cv != cw, ""); + static_assert(cv < cw, ""); + static_assert(!(cv > cw), ""); + static_assert(cv <= cw, ""); + static_assert(!(cv >= cw), ""); + // `cw` op `cv` + static_assert(!(cw == cv), ""); + static_assert(cw != cv, ""); + static_assert(!(cw < cv), ""); + static_assert(cw > cv, ""); + static_assert(!(cw <= cv), ""); + static_assert(cw >= cv, ""); + } +#endif +} + +TEST(Rel, DiffTypeDiffValue) { + mpark::variant v(0), w(1u); + // `v` op `w` + EXPECT_FALSE(v == w); + EXPECT_TRUE(v != w); + EXPECT_TRUE(v < w); + EXPECT_FALSE(v > w); + EXPECT_TRUE(v <= w); + EXPECT_FALSE(v >= w); + // `w` op `v` + EXPECT_FALSE(w == v); + EXPECT_TRUE(w != v); + EXPECT_FALSE(w < v); + EXPECT_TRUE(w > v); + EXPECT_FALSE(w <= v); + EXPECT_TRUE(w >= v); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(0), cw(1u); + // `cv` op `cw` + static_assert(!(cv == cw), ""); + static_assert(cv != cw, ""); + static_assert(cv < cw, ""); + static_assert(!(cv > cw), ""); + static_assert(cv <= cw, ""); + static_assert(!(cv >= cw), ""); + // `cw` op `cv` + static_assert(!(cw == cv), ""); + static_assert(cw != cv, ""); + static_assert(!(cw < cv), ""); + static_assert(cw > cv, ""); + static_assert(!(cw <= cv), ""); + static_assert(cw >= cv, ""); + } +#endif +} + +#ifdef MPARK_EXCEPTIONS +TEST(Rel, OneValuelessByException) { + // `v` normal, `w` corrupted. + mpark::variant v(42), w(42); + EXPECT_THROW(w = move_thrower_t{}, MoveConstruction); + EXPECT_FALSE(v.valueless_by_exception()); + EXPECT_TRUE(w.valueless_by_exception()); + // `v` op `w` + EXPECT_FALSE(v == w); + EXPECT_TRUE(v != w); + EXPECT_FALSE(v < w); + EXPECT_TRUE(v > w); + EXPECT_FALSE(v <= w); + EXPECT_TRUE(v >= w); +} + +TEST(Rel, BothValuelessByException) { + // `v`, `w` both corrupted. + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + mpark::variant w(v); + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_TRUE(w.valueless_by_exception()); + // `v` op `w` + EXPECT_TRUE(v == w); + EXPECT_FALSE(v != w); + EXPECT_FALSE(v < w); + EXPECT_FALSE(v > w); + EXPECT_TRUE(v <= w); + EXPECT_TRUE(v >= w); +} +#endif diff --git a/src/third_party/variant-1.3.0/test/swap.cpp b/src/third_party/variant-1.3.0/test/swap.cpp new file mode 100644 index 00000000000..53ef0c46eb7 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/swap.cpp @@ -0,0 +1,172 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include + +#include + +#include "util.hpp" + +TEST(Swap, Same) { + mpark::variant v("hello"); + mpark::variant w("world"); + // Check `v`. + EXPECT_EQ("hello", mpark::get(v)); + // Check `w`. + EXPECT_EQ("world", mpark::get(w)); + // Swap. + using std::swap; + swap(v, w); + // Check `v`. + EXPECT_EQ("world", mpark::get(v)); + // Check `w`. + EXPECT_EQ("hello", mpark::get(w)); +} + +TEST(Swap, Different) { + mpark::variant v(42); + mpark::variant w("hello"); + // Check `v`. + EXPECT_EQ(42, mpark::get(v)); + // Check `w`. + EXPECT_EQ("hello", mpark::get(w)); + // Swap. + using std::swap; + swap(v, w); + // Check `v`. + EXPECT_EQ("hello", mpark::get(v)); + // Check `w`. + EXPECT_EQ(42, mpark::get(w)); +} + +#ifdef MPARK_EXCEPTIONS +TEST(Swap, OneValuelessByException) { + // `v` normal, `w` corrupted. + mpark::variant v(42), w(42); + EXPECT_THROW(w = move_thrower_t{}, MoveConstruction); + EXPECT_EQ(42, mpark::get(v)); + EXPECT_TRUE(w.valueless_by_exception()); + // Swap. + using std::swap; + swap(v, w); + // Check `v`, `w`. + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_EQ(42, mpark::get(w)); +} + +TEST(Swap, BothValuelessByException) { + // `v`, `w` both corrupted. + mpark::variant v(42); + EXPECT_THROW(v = move_thrower_t{}, MoveConstruction); + mpark::variant w(v); + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_TRUE(w.valueless_by_exception()); + // Swap. + using std::swap; + swap(v, w); + // Check `v`, `w`. + EXPECT_TRUE(v.valueless_by_exception()); + EXPECT_TRUE(w.valueless_by_exception()); +} +#endif + +TEST(Swap, DtorsSame) { + struct Obj { + Obj(size_t *dtor_count) : dtor_count_(dtor_count) {} + Obj(const Obj &) = default; + Obj(Obj &&) = default; + ~Obj() { ++(*dtor_count_); } + Obj &operator=(const Obj &) = default; + Obj &operator=(Obj &&) = default; + size_t *dtor_count_; + }; // Obj + size_t v_count = 0; + size_t w_count = 0; + { + mpark::variant v{&v_count}, w{&w_count}; + using std::swap; + swap(v, w); + // Calls `std::swap(Obj &lhs, Obj &rhs)`, with which we perform: + // ``` + // { + // Obj temp(move(lhs)); + // lhs = move(rhs); + // rhs = move(temp); + // } `++v_count` from `temp::~Obj()`. + // ``` + EXPECT_EQ(1u, v_count); + EXPECT_EQ(0u, w_count); + } + EXPECT_EQ(2u, v_count); + EXPECT_EQ(1u, w_count); +} + +namespace detail { + +struct Obj { + Obj(size_t *dtor_count) : dtor_count_(dtor_count) {} + Obj(const Obj &) = default; + Obj(Obj &&) = default; + ~Obj() { ++(*dtor_count_); } + Obj &operator=(const Obj &) = default; + Obj &operator=(Obj &&) = default; + size_t *dtor_count_; +}; // Obj + +static void swap(Obj &lhs, Obj &rhs) { std::swap(lhs.dtor_count_, rhs.dtor_count_); } + +} // namespace detail + +TEST(Swap, DtorsSameWithSwap) { + size_t v_count = 0; + size_t w_count = 0; + { + mpark::variant v{&v_count}, w{&w_count}; + using std::swap; + swap(v, w); + // Calls `detail::swap(Obj &lhs, Obj &rhs)`, with which doesn't call any destructors. + EXPECT_EQ(0u, v_count); + EXPECT_EQ(0u, w_count); + } + EXPECT_EQ(1u, v_count); + EXPECT_EQ(1u, w_count); +} + +TEST(Swap, DtorsDifferent) { + struct V { + V(size_t *dtor_count) : dtor_count_(dtor_count) {} + V(const V &) = default; + V(V &&) = default; + ~V() { ++(*dtor_count_); } + V &operator=(const V &) = default; + V &operator=(V &&) = default; + size_t *dtor_count_; + }; // V + struct W { + W(size_t *dtor_count) : dtor_count_(dtor_count) {} + W(const W &) = default; + W(W &&) = default; + ~W() { ++(*dtor_count_); } + W &operator=(const W &) = default; + W &operator=(W &&) = default; + size_t *dtor_count_; + }; // W + size_t v_count = 0; + size_t w_count = 0; + { + mpark::variant v{mpark::in_place_type_t{}, &v_count}; + mpark::variant w{mpark::in_place_type_t{}, &w_count}; + using std::swap; + swap(v, w); + EXPECT_EQ(1u, v_count); + EXPECT_EQ(2u, w_count); + } + EXPECT_EQ(2u, v_count); + EXPECT_EQ(3u, w_count); +} diff --git a/src/third_party/variant-1.3.0/test/util.hpp b/src/third_party/variant-1.3.0/test/util.hpp new file mode 100644 index 00000000000..8fc8ffdd1f6 --- /dev/null +++ b/src/third_party/variant-1.3.0/test/util.hpp @@ -0,0 +1,60 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +enum Qual { Ptr, ConstPtr, LRef, ConstLRef, RRef, ConstRRef }; + +struct get_qual_t { + constexpr Qual operator()(int *) const { return Ptr; } + constexpr Qual operator()(const int *) const { return ConstPtr; } + constexpr Qual operator()(int &) const { return LRef; } + constexpr Qual operator()(const int &) const { return ConstLRef; } + constexpr Qual operator()(int &&) const { return RRef; } + constexpr Qual operator()(const int &&) const { return ConstRRef; } +}; + +constexpr get_qual_t get_qual{}; + +#ifdef MPARK_EXCEPTIONS +struct CopyConstruction : std::exception {}; +struct CopyAssignment : std::exception {}; +struct MoveConstruction : std::exception {}; +struct MoveAssignment : std::exception {}; + +struct copy_thrower_t { + constexpr copy_thrower_t() {} + [[noreturn]] copy_thrower_t(const copy_thrower_t &) { + throw CopyConstruction{}; + } + copy_thrower_t(copy_thrower_t &&) = default; + copy_thrower_t &operator=(const copy_thrower_t &) { throw CopyAssignment{}; } + copy_thrower_t &operator=(copy_thrower_t &&) = default; +}; + +bool operator<(const copy_thrower_t &, const copy_thrower_t &) { return false; } +bool operator>(const copy_thrower_t &, const copy_thrower_t &) { return false; } +bool operator<=(const copy_thrower_t &, const copy_thrower_t &) { return true; } +bool operator>=(const copy_thrower_t &, const copy_thrower_t &) { return true; } +bool operator==(const copy_thrower_t &, const copy_thrower_t &) { return true; } +bool operator!=(const copy_thrower_t &, const copy_thrower_t &) { return false; } + +struct move_thrower_t { + constexpr move_thrower_t() {} + move_thrower_t(const move_thrower_t &) = default; + [[noreturn]] move_thrower_t(move_thrower_t &&) { throw MoveConstruction{}; } + move_thrower_t &operator=(const move_thrower_t &) = default; + move_thrower_t &operator=(move_thrower_t &&) { throw MoveAssignment{}; } +}; + +bool operator<(const move_thrower_t &, const move_thrower_t &) { return false; } +bool operator>(const move_thrower_t &, const move_thrower_t &) { return false; } +bool operator<=(const move_thrower_t &, const move_thrower_t &) { return true; } +bool operator>=(const move_thrower_t &, const move_thrower_t &) { return true; } +bool operator==(const move_thrower_t &, const move_thrower_t &) { return true; } +bool operator!=(const move_thrower_t &, const move_thrower_t &) { return false; } +#endif diff --git a/src/third_party/variant-1.3.0/test/visit.cpp b/src/third_party/variant-1.3.0/test/visit.cpp new file mode 100644 index 00000000000..7f7e8c77a3c --- /dev/null +++ b/src/third_party/variant-1.3.0/test/visit.cpp @@ -0,0 +1,130 @@ +// MPark.Variant +// +// Copyright Michael Park, 2015-2017 +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) + +#include + +#include +#include +#include + +#include + +namespace lib = mpark::lib; + +enum Qual { LRef, ConstLRef, RRef, ConstRRef }; + +struct get_qual { + constexpr Qual operator()(int &) const { return LRef; } + constexpr Qual operator()(const int &) const { return ConstLRef; } + constexpr Qual operator()(int &&) const { return RRef; } + constexpr Qual operator()(const int &&) const { return ConstRRef; } +}; // get_qual + +TEST(Visit, MutVarMutType) { + mpark::variant v(42); + // Check `v`. + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(LRef, mpark::visit(get_qual(), v)); + EXPECT_EQ(RRef, mpark::visit(get_qual(), lib::move(v))); +} + +TEST(Visit, MutVarConstType) { + mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, mpark::visit(get_qual(), v)); + EXPECT_EQ(ConstRRef, mpark::visit(get_qual(), lib::move(v))); +} + +TEST(Visit, ConstVarMutType) { + const mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, mpark::visit(get_qual(), v)); + EXPECT_EQ(ConstRRef, mpark::visit(get_qual(), lib::move(v))); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // Check qualifier. + static_assert(ConstLRef == mpark::visit(get_qual(), cv), ""); + static_assert(ConstRRef == mpark::visit(get_qual(), lib::move(cv)), ""); + } +#endif +} + +TEST(Visit, ConstVarConstType) { + const mpark::variant v(42); + EXPECT_EQ(42, mpark::get(v)); + // Check qualifier. + EXPECT_EQ(ConstLRef, mpark::visit(get_qual(), v)); + EXPECT_EQ(ConstRRef, mpark::visit(get_qual(), lib::move(v))); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(42); + static_assert(42 == mpark::get(cv), ""); + // Check qualifier. + static_assert(ConstLRef == mpark::visit(get_qual(), cv), ""); + static_assert(ConstRRef == mpark::visit(get_qual(), lib::move(cv)), ""); + } +#endif +} + +struct concat { + template + std::string operator()(const Args &... args) const { + std::ostringstream strm; + std::initializer_list({(strm << args, 0)...}); + return lib::move(strm).str(); + } +}; + +TEST(Visit, Zero) { EXPECT_EQ("", mpark::visit(concat{})); } + +TEST(Visit_Homogeneous, Double) { + mpark::variant v("hello"), w("world!"); + EXPECT_EQ("helloworld!", mpark::visit(concat{}, v, w)); + +#if !defined(__GNUC__) || __GNUC__ >= 5 + /* constexpr */ { + constexpr mpark::variant cv(101), cw(202), cx(3.3); + struct add_ints { + constexpr int operator()(int lhs, int rhs) const { return lhs + rhs; } + constexpr int operator()(int lhs, double) const { return lhs; } + constexpr int operator()(double, int rhs) const { return rhs; } + constexpr int operator()(double, double) const { return 0; } + }; // add + static_assert(303 == mpark::visit(add_ints{}, cv, cw), ""); + static_assert(202 == mpark::visit(add_ints{}, cw, cx), ""); + static_assert(101 == mpark::visit(add_ints{}, cx, cv), ""); + static_assert(0 == mpark::visit(add_ints{}, cx, cx), ""); + } +#endif +} + +TEST(Visit_Homogeneous, Quintuple) { + mpark::variant v(101), w("+"), x(202), y("="), z(303); + EXPECT_EQ("101+202=303", mpark::visit(concat{}, v, w, x, y, z)); +} + +TEST(Visit_Heterogeneous, Double) { + mpark::variant v("hello"); + mpark::variant w("world!"); + EXPECT_EQ("helloworld!", mpark::visit(concat{}, v, w)); +} + +TEST(Visit_Heterogenous, Quintuple) { + mpark::variant v(101); + mpark::variant w("+"); + mpark::variant x(202); + mpark::variant y('='); + mpark::variant z(303L); + EXPECT_EQ("101+202=303", mpark::visit(concat{}, v, w, x, y, z)); +} -- cgit v1.2.1