├── .appveyor.yml ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── cmake └── eggs.variant-config.cmake.in ├── docs ├── README.md ├── config.md ├── css │ ├── img │ │ ├── bgcode.png │ │ └── favicon.png │ ├── main.css │ └── normalize.css ├── design.md ├── index.md ├── introduction.md ├── logo.png └── reference.Doxyfile ├── include └── eggs │ ├── variant.hpp │ └── variant │ ├── bad_variant_access.hpp │ ├── detail │ ├── apply.hpp │ ├── config │ │ ├── prefix.hpp │ │ └── suffix.hpp │ ├── pack.hpp │ ├── storage.hpp │ ├── utility.hpp │ └── visitor.hpp │ ├── in_place.hpp │ └── variant.hpp └── test ├── CMakeLists.txt ├── README.md ├── apply.cpp ├── assign.conversion.cpp ├── assign.copy.cpp ├── assign.emplace.cpp ├── assign.move.cpp ├── catch.cpp ├── catch.hpp ├── cnstr.conversion.cpp ├── cnstr.copy.cpp ├── cnstr.default.cpp ├── cnstr.emplace.cpp ├── cnstr.move.cpp ├── constexpr.hpp ├── dtor.cpp ├── dtor.hpp ├── elem.get.cpp ├── elem.get_if.cpp ├── hash.cpp ├── helper.cpp ├── in_place.cpp ├── obs.bool.cpp ├── obs.target.cpp ├── obs.target_type.cpp ├── obs.which.cpp ├── rel.equality.cpp ├── rel.order.cpp ├── swap.cpp └── throw.hpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # Eggs.Variant 2 | # 3 | # Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | # file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | platform: x64 9 | 10 | environment: 11 | matrix: 12 | # MSVC 14.0 13 | - GENERATOR: Visual Studio 14 2015 Win64 14 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 15 | 16 | # MSVC 14.1 17 | - GENERATOR: Visual Studio 15 2017 Win64 18 | CXXFLAGS: /std:c++14 /permissive- 19 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 20 | 21 | - GENERATOR: Visual Studio 15 2017 Win64 22 | CXXFLAGS: /std:c++latest /permissive- 23 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 24 | 25 | # LLVM 26 | - GENERATOR: Visual Studio 14 2015 Win64 27 | TOOLSET: LLVM-vs2014 28 | CXXFLAGS: /EHsc 29 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 30 | 31 | # MinGW-w64 32 | - GENERATOR: MinGW Makefiles 33 | CXXFLAGS: -std=c++11 34 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 35 | 36 | - GENERATOR: MinGW Makefiles 37 | CXXFLAGS: -std=c++14 38 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 39 | 40 | - GENERATOR: MinGW Makefiles 41 | CXXFLAGS: -std=c++1z 42 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 43 | 44 | branches: 45 | only: 46 | - master 47 | - develop 48 | 49 | init: 50 | - ps: | 51 | if ($env:GENERATOR -eq "MinGW Makefiles") { 52 | $env:Path = 'C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin;' + $env:Path 53 | # Workaround for CMake not wanting sh.exe on PATH for MinGW Makefiles 54 | $env:Path = $env:Path -replace 'C:\\Program Files\\Git\\usr\\bin;',$null 55 | } 56 | 57 | build_script: 58 | - echo cmake -G "%GENERATOR%" -T "%TOOLSET%" 59 | - ps: | 60 | if ($env:GENERATOR -eq "MinGW Makefiles") { 61 | $env:CXXFLAGS = $env:CXXFLAGS + ' -Wall -Wextra -Werror -pedantic-errors' 62 | 63 | mkdir build-debug 64 | cd build-debug 65 | cmake -G "$env:GENERATOR" -DCMAKE_BUILD_TYPE=Debug .. 66 | cmake --build . -- -j 2 -k 67 | ctest --output-on-failure 68 | 69 | cd .. 70 | mkdir build-release 71 | cd build-release 72 | cmake -G "$env:GENERATOR" -DCMAKE_BUILD_TYPE=Release .. 73 | cmake --build . -- -j 2 -k 74 | ctest --output-on-failure 75 | } else { 76 | $env:CXXFLAGS = $env:CXXFLAGS + ' /W4' 77 | 78 | mkdir build 79 | cd build 80 | if (Test-Path env:TOOLSET) { 81 | cmake -G "$env:GENERATOR" -T "$env:TOOLSET" .. 82 | } else { 83 | cmake -G "$env:GENERATOR" .. 84 | } 85 | cmake --build . --config Debug 86 | ctest --output-on-failure --build-config Debug 87 | cmake --build . --config Release 88 | ctest --output-on-failure --build-config Release 89 | } 90 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Eggs.Variant 2 | # 3 | # Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | # file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | language: cpp 9 | sudo: false 10 | 11 | matrix: 12 | include: 13 | # clang-3.9 14 | - env: VERSION=3.9 CXX_VERSIONS="11;14;1z" 15 | compiler: clang 16 | os: linux 17 | addons: 18 | apt: 19 | packages: 20 | - clang-3.9 21 | - libstdc++-6-dev 22 | sources: 23 | - ubuntu-toolchain-r-test 24 | - llvm-toolchain-trusty-3.9 25 | 26 | # clang-4 27 | - env: VERSION=4.0 CXX_VERSIONS="11;14;1z" 28 | compiler: clang 29 | os: linux 30 | addons: 31 | apt: 32 | packages: 33 | - clang-4.0 34 | - libstdc++-6-dev 35 | sources: 36 | - ubuntu-toolchain-r-test 37 | - llvm-toolchain-trusty-4.0 38 | 39 | # clang-5 40 | - env: VERSION=5.0 CXX_VERSIONS="11;14;17" 41 | compiler: clang 42 | os: linux 43 | addons: 44 | apt: 45 | packages: 46 | - clang-5.0 47 | - libstdc++-7-dev 48 | sources: 49 | - ubuntu-toolchain-r-test 50 | - llvm-toolchain-trusty-5.0 51 | 52 | # gcc-5 53 | - env: VERSION=5 CXX_VERSIONS="11;14;1z" 54 | compiler: gcc 55 | os: linux 56 | addons: 57 | apt: 58 | packages: 59 | - g++-5 60 | sources: 61 | - ubuntu-toolchain-r-test 62 | 63 | # gcc-6 64 | - env: VERSION=6 CXX_VERSIONS="11;14;1z" 65 | compiler: gcc 66 | os: linux 67 | addons: 68 | apt: 69 | packages: 70 | - g++-6 71 | sources: 72 | - ubuntu-toolchain-r-test 73 | 74 | # gcc-7 75 | - env: VERSION=7 CXX_VERSIONS="11;14;17" 76 | compiler: gcc 77 | os: linux 78 | addons: 79 | apt: 80 | packages: 81 | - g++-7 82 | sources: 83 | - ubuntu-toolchain-r-test 84 | 85 | # Xcode 7.3 86 | - env: CXX_VERSIONS="11;14;1z" 87 | compiler: clang 88 | os: osx 89 | osx_image: xcode7.3 90 | 91 | # Xcode 8.3 92 | - env: CXX_VERSIONS="11;14;1z" 93 | compiler: clang 94 | os: osx 95 | osx_image: xcode8.3 96 | 97 | # Xcode 9.1 98 | - env: CXX_VERSIONS="11;14;1z" 99 | compiler: clang 100 | os: osx 101 | osx_image: xcode9.1 102 | 103 | branches: 104 | only: 105 | - master 106 | - develop 107 | 108 | install: 109 | - | 110 | if [ -n "${VERSION}" ]; then 111 | export CC="${CC}-${VERSION}" 112 | export CXX="${CXX}-${VERSION}" 113 | fi 114 | - export CXXFLAGS="-Wall -Wextra -Werror -pedantic-errors" 115 | - CXX_VERSIONS=(${CXX_VERSIONS//;/ }) 116 | - BUILD_TYPES=(Debug Release) 117 | 118 | script: 119 | - | 120 | (( STATUS = 0 )) 121 | for CXX_VERSION in "${CXX_VERSIONS[@]}"; do 122 | for BUILD_TYPE in "${BUILD_TYPES[@]}"; do 123 | BUILD_DIR="build-${CXX_VERSION}-${BUILD_TYPE}" 124 | ( 125 | set -x 126 | mkdir "${BUILD_DIR}" 127 | cd "${BUILD_DIR}" 128 | export CXXFLAGS="${CXXFLAGS} -std=c++${CXX_VERSION}" 129 | set -e 130 | cmake -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" .. 131 | set +e 132 | cmake --build . -- -j 2 -k 133 | ctest --output-on-failure 134 | ) 135 | (( STATUS = STATUS || $? )) 136 | done 137 | done 138 | ( exit ${STATUS} ) 139 | 140 | notifications: 141 | email: false 142 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Eggs.Variant 2 | # 3 | # Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | # file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | cmake_minimum_required(VERSION 3.0) 9 | 10 | project(Eggs.Variant CXX) 11 | 12 | if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 13 | option(WITH_TESTS "Compile with unit tests." ON) 14 | set(HAVE_TESTS ${WITH_TESTS}) 15 | else() 16 | option(EGGS_VARIANT_WITH_TESTS "Compile with unit tests." ON) 17 | set(HAVE_TESTS ${EGGS_VARIANT_WITH_TESTS}) 18 | endif() 19 | 20 | # Build 21 | add_library(_eggs_variant INTERFACE) 22 | target_include_directories(_eggs_variant INTERFACE 23 | $ 24 | $) 25 | set_target_properties(_eggs_variant 26 | PROPERTIES EXPORT_NAME Eggs::Variant) 27 | 28 | add_library(Eggs::Variant ALIAS _eggs_variant) 29 | 30 | # Test 31 | if (HAVE_TESTS) 32 | enable_testing() 33 | add_subdirectory(test) 34 | endif() 35 | 36 | # Install 37 | set(_headers 38 | eggs/variant.hpp 39 | eggs/variant/bad_variant_access.hpp 40 | eggs/variant/in_place.hpp 41 | eggs/variant/variant.hpp 42 | eggs/variant/detail/apply.hpp 43 | eggs/variant/detail/pack.hpp 44 | eggs/variant/detail/storage.hpp 45 | eggs/variant/detail/utility.hpp 46 | eggs/variant/detail/visitor.hpp 47 | eggs/variant/detail/config/prefix.hpp 48 | eggs/variant/detail/config/suffix.hpp) 49 | foreach (_header ${_headers}) 50 | get_filename_component(_directory "${_header}" DIRECTORY) 51 | install(FILES 52 | "${CMAKE_CURRENT_SOURCE_DIR}/include/${_header}" 53 | DESTINATION "include/${_directory}") 54 | endforeach() 55 | 56 | install(TARGETS _eggs_variant EXPORT _targets) 57 | install(EXPORT _targets 58 | DESTINATION lib/cmake/eggs.variant 59 | FILE eggs.variant-targets.cmake) 60 | 61 | include(CMakePackageConfigHelpers) 62 | 63 | configure_file( 64 | cmake/eggs.variant-config.cmake.in 65 | "${CMAKE_CURRENT_BINARY_DIR}/eggs.variant-config.cmake" 66 | @ONLY) 67 | 68 | write_basic_package_version_file( 69 | "${CMAKE_CURRENT_BINARY_DIR}/eggs.variant-config-version.cmake" 70 | VERSION 0.0.0 71 | COMPATIBILITY AnyNewerVersion) 72 | 73 | install( 74 | FILES 75 | "${CMAKE_CURRENT_BINARY_DIR}/eggs.variant-config.cmake" 76 | "${CMAKE_CURRENT_BINARY_DIR}/eggs.variant-config-version.cmake" 77 | DESTINATION lib/cmake/eggs.variant) 78 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/README.md -------------------------------------------------------------------------------- /cmake/eggs.variant-config.cmake.in: -------------------------------------------------------------------------------- 1 | # Eggs.Variant 2 | # 3 | # Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | # file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | # - Config file for Eggs.Variant 9 | # 10 | # EGGS_VARIANT_INCLUDE_DIRS - include directories 11 | # EGGS_VARIANT_LIBRARIES - libraries to link against 12 | # 13 | # The following `IMPORTED` target is also defined: 14 | # 15 | # Eggs::Variant 16 | 17 | get_filename_component( 18 | EGGS_VARIANT_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE) 19 | 20 | include("${EGGS_VARIANT_CMAKE_DIR}/eggs.variant-targets.cmake") 21 | 22 | get_target_property( 23 | _eggs_variant_include_dirs 24 | Eggs::Variant INTERFACE_INCLUDE_DIRECTORIES) 25 | set(EGGS_VARIANT_INCLUDE_DIRS ${_eggs_variant_include_dirs}) 26 | foreach (_eggs_variant_include_dir ${_eggs_variant_include_dirs}) 27 | if (NOT EXISTS "${_eggs_variant_include_dir}") 28 | message(FATAL_ERROR 29 | "Directory ${_eggs_variant_include_dir} referenced by" 30 | " variable \${EGGS_VARIANT_INCLUDE_DIRS} does not exist!") 31 | endif() 32 | endforeach() 33 | 34 | set(EGGS_VARIANT_LIBRARIES Eggs::Variant) 35 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/README.md -------------------------------------------------------------------------------- /docs/config.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/config.md -------------------------------------------------------------------------------- /docs/css/img/bgcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/css/img/bgcode.png -------------------------------------------------------------------------------- /docs/css/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/css/img/favicon.png -------------------------------------------------------------------------------- /docs/css/main.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Muli:400,300); 2 | @import url(https://fonts.googleapis.com/css?family=Share:400,700); 3 | 4 | /* ============================== */ 5 | /* BODY */ 6 | /* ============================== */ 7 | 8 | body { 9 | font-family: 'Muli',arial,sans-serif; 10 | background-color: #FEFEFE; 11 | margin: 0; 12 | padding: 0; 13 | font-size: 0.875em; 14 | color: #616161; 15 | } 16 | 17 | h1, h2, h3, h4, h5, h6 { 18 | margin-bottom: 0.5em; 19 | font-family: 'Share'; 20 | } 21 | 22 | .title { 23 | border-bottom: solid 2px #f5aa10; 24 | } 25 | 26 | #container { 27 | margin: 0 auto; 28 | width: 60%; 29 | min-width: 640px; 30 | overflow: auto; 31 | } 32 | 33 | #main { 34 | width: 100%; 35 | } 36 | 37 | a { 38 | color: #3C6EB4; 39 | cursor: pointer; 40 | text-decoration: none; 41 | } 42 | 43 | a:hover { 44 | text-decoration: underline; 45 | } 46 | 47 | 48 | /* ============================== */ 49 | /* HEADER */ 50 | /* ============================== */ 51 | #head { 52 | overflow: auto; 53 | margin: 40px 0; 54 | } 55 | 56 | #head div.top { 57 | font-size: 2.4em; 58 | margin-right: 80px; 59 | } 60 | 61 | #head div.bottom { 62 | height: 38px; 63 | margin-right: 80px; 64 | } 65 | 66 | #head .logo { 67 | vertical-align: bottom; 68 | } 69 | 70 | #head a.name { 71 | text-decoration: none; 72 | color: #555; 73 | font-weight: bold; 74 | overflow: auto; 75 | } 76 | 77 | #head span.slogan { 78 | color: #CCC; 79 | } 80 | 81 | /* ============================== */ 82 | /* HEADER POST */ 83 | /* ============================== */ 84 | #head_post { 85 | overflow: auto; 86 | margin: 10px 0; 87 | text-align: center; 88 | } 89 | 90 | #head_post a.name { 91 | text-decoration: none; 92 | color: #555; 93 | font-size: 0.9em; 94 | } 95 | 96 | #head_post span.slogan { 97 | color: #CCC; 98 | } 99 | 100 | /* ============================== */ 101 | /* FOOTER */ 102 | /* ============================== */ 103 | #foot { 104 | text-align: right; 105 | font-size: 0.9em; 106 | } 107 | 108 | /* ============================== */ 109 | /* PAGER */ 110 | /* ============================== */ 111 | #pager { 112 | overflow: auto; 113 | } 114 | 115 | #pager a.newer { 116 | float: right; 117 | } 118 | 119 | #pager a.older { 120 | float: left; 121 | } 122 | 123 | /* ============================== */ 124 | /* POST VIEW*/ 125 | /* ============================== */ 126 | post { 127 | margin-bottom: 60px; 128 | clear: both; 129 | overflow: auto; 130 | } 131 | 132 | post header.post { 133 | margin-bottom: 10px; 134 | } 135 | 136 | post header.post h1.title { 137 | font-weight: bold; 138 | margin: 0; 139 | } 140 | 141 | post header.post h1.title a { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | post header.post div.date { 147 | font-size: 0.9em; 148 | font-weight: bold; 149 | text-align: right; 150 | text-transform: uppercase; 151 | color: #999; 152 | } 153 | 154 | post .body { 155 | font-size: 1.2em; 156 | } 157 | 158 | post .console { 159 | background: url("img/console.png") no-repeat scroll 10px center #F1F1F1; 160 | display: block; 161 | line-height: 50px; 162 | margin: 5px 0; 163 | padding-left: 60px; 164 | } 165 | 166 | post img:not(.captcha) { 167 | max-width: 100%; 168 | } 169 | 170 | post blockquote { 171 | font-size: 1em; 172 | width: 80%; 173 | margin-left: 2em; 174 | padding-left: 0.5em; 175 | border-left: 2px solid #C3C3C3; 176 | } 177 | 178 | post footer.post { 179 | clear: both; 180 | margin-top: 20px; 181 | text-align: center; 182 | } 183 | 184 | article pre { 185 | border: 1px dashed #ccc; 186 | padding: 1em; 187 | background: #f4f4f4; 188 | } 189 | 190 | pre, code { 191 | font-family: monospace; 192 | font-size: 1em; 193 | } 194 | 195 | /* ============================== */ 196 | /* BUTTONS */ 197 | /* ============================== */ 198 | .button, form input[type="submit"] { 199 | font-family: 'Share'; 200 | font-size: 12px; 201 | background: #eee; 202 | padding: 5px 20px; 203 | margin: 5px 0; 204 | overflow: hidden; 205 | border: solid 1px #ccc; 206 | color: #2a2a2a; 207 | text-decoration: none; 208 | display: inline-block; 209 | -webkit-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); 210 | -moz-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); 211 | text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.9); 212 | -webkit-transition-duration: 0.3s; 213 | -moz-transition-duration: 0.3s; 214 | transition-duration: 0.3s; 215 | } 216 | 217 | .button:hover, form input[type="submit"]:hover { 218 | text-decoration: none; 219 | background: #f5aa10; 220 | color: #fff; 221 | border-color: #666; 222 | -webkit-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); 223 | -moz-text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9); 224 | text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.8); 225 | -webkit-transition: 0.2s; 226 | -moz-transition: 0.2s; 227 | transition: 0.2s; 228 | } 229 | 230 | /* ============================== */ 231 | /* TABLES */ 232 | /* ============================== */ 233 | table { 234 | border: 1px solid #999; 235 | } 236 | 237 | table th, table td { 238 | background: #f4f4f4; 239 | padding: 5px 15px; 240 | } 241 | 242 | table thead { 243 | border-bottom: 1px solid #999; 244 | } 245 | 246 | table th { 247 | font-weight: bold; 248 | background: #eaeaea; 249 | } 250 | 251 | table td, table th { 252 | border-right: 1px solid #999; 253 | } 254 | 255 | pre.code { 256 | -moz-border-radius: 0 0 0 0 !important; 257 | -webkit-border-radius: 0 0 0 0 !important; 258 | background-color: #F4F4F4 !important; 259 | border: 1px dashed #CCC; 260 | float: none !important; 261 | height: auto !important; 262 | line-height: 1.1em !important; 263 | margin: 1em 0px !important; 264 | outline: 0 !important; 265 | overflow: visible !important; 266 | padding: 1em; 267 | position: static !important; 268 | text-align: left !important; 269 | vertical-align: baseline !important; 270 | width: 100% !important; 271 | box-sizing: content-box !important; 272 | font-family: monospace !important; 273 | font-weight: normal !important; 274 | font-style: normal !important; 275 | font-size: 1em !important; 276 | min-height: inherit !important; 277 | box-sizing: border-box !important; 278 | } 279 | 280 | /* ============================== */ 281 | /* REFERENCE */ 282 | /* ============================== */ 283 | .reference ul { 284 | list-style: none; 285 | } 286 | 287 | .reference ul li { 288 | margin: 14px 0; 289 | } 290 | 291 | .reference ul li ul { 292 | list-style: disc; 293 | } 294 | -------------------------------------------------------------------------------- /docs/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */ 2 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block} 3 | audio,canvas,video{display:inline-block} 4 | audio:not([controls]){display:none;height:0} 5 | [hidden]{display:none} 6 | html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} 7 | a:focus{outline:thin dotted} 8 | a:active,a:hover{outline:0} 9 | h1{font-size:2em} 10 | abbr[title]{border-bottom:1px dotted} 11 | b,strong{font-weight:700} 12 | dfn{font-style:italic} 13 | mark{background:#ff0;color:#000} 14 | code,kbd,pre,samp{font-family:monospace, serif;font-size:1em} 15 | pre{white-space:pre-wrap;word-wrap:break-word} 16 | q{quotes:\201C \201D \2018 \2019} 17 | small{font-size:80%} 18 | sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} 19 | sup{top:-.5em} 20 | sub{bottom:-.25em} 21 | img{border:0} 22 | svg:not(:root){overflow:hidden} 23 | fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} 24 | button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} 25 | button,input{line-height:normal} 26 | button,html input[type=button],/* 1 */ 27 | input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} 28 | button[disabled],input[disabled]{cursor:default} 29 | input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0} 30 | input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} 31 | input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none} 32 | textarea{overflow:auto;vertical-align:top} 33 | table{border-collapse:collapse;border-spacing:0} 34 | body,figure{margin:0} 35 | legend,button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} -------------------------------------------------------------------------------- /docs/design.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/design.md -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/index.md -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/introduction.md -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/docs/logo.png -------------------------------------------------------------------------------- /include/eggs/variant.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_HPP 10 | #define EGGS_VARIANT_HPP 11 | 12 | #include "variant/bad_variant_access.hpp" 13 | #include "variant/variant.hpp" 14 | 15 | #include 16 | 17 | #include "variant/detail/config/prefix.hpp" 18 | 19 | namespace eggs 20 | { 21 | //! using variants::variant; 22 | using variants::variant; 23 | 24 | //! using variants::variant_size; 25 | using variants::variant_size; 26 | #if EGGS_CXX14_HAS_VARIABLE_TEMPLATES 27 | //! using variants::variant_size_v; 28 | using variants::variant_size_v; 29 | #endif 30 | 31 | //! using variants::variant_element; 32 | using variants::variant_element; 33 | //! using variants::variant_element_t; 34 | using variants::variant_element_t; 35 | 36 | //! constexpr std::size_t variant_npos = std::size_t(-1); 37 | EGGS_CXX11_CONSTEXPR std::size_t const variant_npos = std::size_t(-1); 38 | 39 | //! using variants::bad_variant_access; 40 | using variants::bad_variant_access; 41 | 42 | //! using variants::get; 43 | using variants::get; 44 | 45 | //! using variants::get_if; 46 | using variants::get_if; 47 | 48 | //! using variants::apply; 49 | using variants::apply; 50 | } 51 | 52 | #include "variant/detail/config/suffix.hpp" 53 | 54 | #endif /*EGGS_VARIANT_HPP*/ 55 | -------------------------------------------------------------------------------- /include/eggs/variant/bad_variant_access.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/bad_variant_access.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_BAD_VARIANT_ACCESS_HPP 10 | #define EGGS_VARIANT_BAD_VARIANT_ACCESS_HPP 11 | 12 | #include 13 | 14 | #include "detail/config/prefix.hpp" 15 | 16 | namespace eggs { namespace variants 17 | { 18 | /////////////////////////////////////////////////////////////////////////// 19 | //! class bad_variant_access : public std::exception 20 | //! 21 | //! Objects of type `bad_variant_access` are thrown to report attempts to 22 | //! access an inactive member of a `variant` object. 23 | class bad_variant_access 24 | : public std::exception 25 | { 26 | public: 27 | //! bad_variant_access() noexcept; 28 | //! 29 | //! \effects Constructs a `bad_variant_access` object. 30 | bad_variant_access() noexcept 31 | {} 32 | 33 | //! char const* what() const noexcept override; 34 | //! 35 | //! \returns An implementation-defined NTBS. 36 | char const* what() const noexcept /*override*/ 37 | { 38 | return "bad_variant_access"; 39 | } 40 | }; 41 | 42 | namespace detail 43 | { 44 | /////////////////////////////////////////////////////////////////////// 45 | template 46 | EGGS_CXX11_NORETURN inline T throw_bad_variant_access() 47 | { 48 | #if EGGS_CXX98_HAS_EXCEPTIONS 49 | throw bad_variant_access{}; 50 | #else 51 | std::terminate(); 52 | #endif 53 | } 54 | } 55 | }} 56 | 57 | #include "detail/config/suffix.hpp" 58 | 59 | #endif /*EGGS_VARIANT_BAD_VARIANT_ACCESS_HPP*/ 60 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/apply.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/apply.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_DETAIL_APPLY_HPP 10 | #define EGGS_VARIANT_DETAIL_APPLY_HPP 11 | 12 | #include "pack.hpp" 13 | #include "storage.hpp" 14 | #include "utility.hpp" 15 | #include "visitor.hpp" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "config/prefix.hpp" 22 | 23 | namespace eggs { namespace variants { namespace detail 24 | { 25 | /////////////////////////////////////////////////////////////////////////// 26 | template 27 | EGGS_CXX11_CONSTEXPR auto _invoke(F&& f, Ts&&... vs) 28 | noexcept(noexcept(detail::forward(f)(detail::forward(vs)...))) 29 | -> decltype(detail::forward(f)(detail::forward(vs)...)) 30 | { 31 | return detail::forward(f)(detail::forward(vs)...); 32 | } 33 | 34 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 35 | template 36 | EGGS_CXX11_CONSTEXPR auto _invoke(F&& f, T0&& v0, Ts&&... vs) 37 | noexcept(noexcept((v0.*f)(detail::forward(vs)...))) 38 | -> decltype((v0.*f)(detail::forward(vs)...)) 39 | { 40 | return (v0.*f)(detail::forward(vs)...); 41 | } 42 | 43 | template 44 | EGGS_CXX11_CONSTEXPR auto _invoke(F&& f, T0&& v0, Ts&&... vs) 45 | noexcept(noexcept(((*v0).*f)(detail::forward(vs)...))) 46 | -> decltype(((*v0).*f)(detail::forward(vs)...)) 47 | { 48 | return ((*v0).*f)(detail::forward(vs)...); 49 | } 50 | 51 | template 52 | EGGS_CXX11_CONSTEXPR auto _invoke(F&& f, T0&& v0) noexcept 53 | -> decltype(v0.*f) 54 | { 55 | return v0.*f; 56 | } 57 | 58 | template 59 | EGGS_CXX11_CONSTEXPR auto _invoke(F&& f, T0&& v0) noexcept 60 | -> decltype((*v0).*f) 61 | { 62 | return (*v0).*f; 63 | } 64 | #endif 65 | 66 | /////////////////////////////////////////////////////////////////////////// 67 | template 68 | struct _invoke_guard 69 | { 70 | template 71 | EGGS_CXX11_CONSTEXPR R operator()(Ts&&... vs) const 72 | noexcept(noexcept(detail::_invoke(detail::forward(vs)...))) 73 | { 74 | return detail::_invoke(detail::forward(vs)...); 75 | } 76 | }; 77 | 78 | template <> 79 | struct _invoke_guard 80 | { 81 | template 82 | EGGS_CXX14_CONSTEXPR void operator()(Ts&&... vs) const 83 | noexcept(noexcept(detail::_invoke(detail::forward(vs)...))) 84 | { 85 | detail::_invoke(detail::forward(vs)...); 86 | } 87 | }; 88 | 89 | /////////////////////////////////////////////////////////////////////////// 90 | template 91 | struct _result_of; 92 | 93 | template 94 | struct _result_of> 95 | { 96 | using type = decltype(detail::_invoke( 97 | std::declval(), std::declval()...)); 98 | }; 99 | 100 | /////////////////////////////////////////////////////////////////////////// 101 | template > 102 | struct _make_apply_pack; 103 | 104 | template 105 | struct _make_apply_pack> 106 | { 107 | using type = pack...>; 108 | }; 109 | 110 | template 111 | using _apply_pack = typename _make_apply_pack::type; 112 | 113 | /////////////////////////////////////////////////////////////////////////// 114 | template 115 | struct _apply_get 116 | { 117 | using type = decltype(std::declval().get(I{})); 118 | 119 | type EGGS_CXX11_CONSTEXPR operator()(V& v) const 120 | { 121 | return v.get(I{}); 122 | } 123 | }; 124 | 125 | template 126 | struct _apply_get 127 | { 128 | using type = typename std::remove_reference< 129 | decltype(std::declval().get(I{}))>::type; 130 | 131 | EGGS_CXX11_CONSTEXPR type operator()(V& v) const 132 | { 133 | return detail::move(v.get(I{})); 134 | } 135 | }; 136 | 137 | /////////////////////////////////////////////////////////////////////////// 138 | template 139 | struct _apply; 140 | 141 | template < 142 | typename R, typename F, typename ...Ms, typename V 143 | > 144 | struct _apply, pack> 145 | : visitor< 146 | _apply, pack> 147 | , R(F&&, Ms..., V&&) 148 | > 149 | { 150 | template 151 | static EGGS_CXX11_CONSTEXPR R call(F&& f, Ms... ms, V&& v) 152 | { 153 | return _invoke_guard{}( 154 | detail::forward(f), detail::forward(ms)... 155 | , _apply_get{}(v)); 156 | } 157 | }; 158 | 159 | template < 160 | typename R, typename F, typename ...Ms 161 | , typename V0, typename V1, typename ...Vs 162 | > 163 | struct _apply, pack> 164 | : visitor< 165 | _apply, pack> 166 | , R(F&&, Ms..., V0&&, V1&&, Vs&&...) 167 | > 168 | { 169 | template 170 | static EGGS_CXX11_CONSTEXPR R call(F&& f, Ms... ms, V0&& v0, 171 | V1&& v1, Vs&&... vs) 172 | { 173 | using T = typename _apply_get::type; 174 | return _apply, pack>{}( 175 | _apply_pack::type>{}, v1.which() - 1 176 | , detail::forward(f) 177 | , detail::forward(ms)..., _apply_get{}(v0) 178 | , detail::forward(v1), detail::forward(vs)...); 179 | } 180 | }; 181 | 182 | template 183 | EGGS_CXX11_CONSTEXPR R apply(F&& f) 184 | { 185 | return _invoke_guard{}(detail::forward(f)); 186 | } 187 | 188 | template 189 | EGGS_CXX11_CONSTEXPR R apply(F&& f, V&& v, Vs&&... vs) 190 | { 191 | return _apply, pack>{}( 192 | _apply_pack::type>{}, v.which() - 1 193 | , detail::forward(f) 194 | , detail::forward(v), detail::forward(vs)...); 195 | } 196 | 197 | /////////////////////////////////////////////////////////////////////////// 198 | template 199 | struct _apply_result_combine 200 | : std::enable_if< 201 | all_of...>>::value 202 | , R 203 | > 204 | {}; 205 | 206 | template < 207 | typename F, typename Ms, typename V, typename Vs, 208 | typename Is = _apply_pack::type> 209 | > 210 | struct _apply_result_expand; 211 | 212 | template < 213 | typename F, typename ...Ms, typename V, 214 | typename ...Is 215 | > 216 | struct _apply_result_expand< 217 | F, pack, V, pack<> 218 | , pack 219 | > : _apply_result_combine< 220 | typename _result_of< 221 | F, pack::type> 222 | >::type... 223 | > 224 | {}; 225 | 226 | template < 227 | typename F, typename ...Ms, typename V0, typename V1, typename ...Vs, 228 | typename ...Is 229 | > 230 | struct _apply_result_expand< 231 | F, pack, V0, pack 232 | , pack 233 | > : _apply_result_combine< 234 | typename _apply_result_expand< 235 | F, pack::type> 236 | , V1, pack 237 | >::type... 238 | > 239 | {}; 240 | 241 | template 242 | struct apply_result; 243 | 244 | template 245 | struct apply_result> 246 | : _result_of> 247 | {}; 248 | 249 | template 250 | struct apply_result> 251 | : _apply_result_expand, V, pack> 252 | {}; 253 | }}} 254 | 255 | #include "config/suffix.hpp" 256 | 257 | #endif /*EGGS_VARIANT_DETAIL_APPLY_HPP*/ 258 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/config/prefix.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/config/prefix.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | /// no header guards 10 | 11 | #if __cplusplus < 201103L 12 | # if !defined(_MSC_VER) || _MSC_VER < 1900 13 | # error Eggs.Variant requires compiler and library support for the ISO C++ 2011 standard. 14 | # endif 15 | #endif 16 | 17 | /// constexpr support 18 | #ifndef EGGS_CXX11_HAS_CONSTEXPR 19 | # if __cpp_constexpr >= 200704L 20 | # define EGGS_CXX11_HAS_CONSTEXPR 1 21 | # else 22 | # define EGGS_CXX11_HAS_CONSTEXPR 1 23 | # endif 24 | # define EGGS_CXX11_HAS_CONSTEXPR_DEFINED 25 | #endif 26 | 27 | #ifndef EGGS_CXX11_CONSTEXPR 28 | # if EGGS_CXX11_HAS_CONSTEXPR == 0 29 | # define EGGS_CXX11_CONSTEXPR 30 | # else 31 | # define EGGS_CXX11_CONSTEXPR constexpr 32 | # endif 33 | # define EGGS_CXX11_CONSTEXPR_DEFINED 34 | #endif 35 | 36 | #ifndef EGGS_CXX11_STATIC_CONSTEXPR 37 | # if EGGS_CXX11_HAS_CONSTEXPR == 0 38 | # define EGGS_CXX11_STATIC_CONSTEXPR static const 39 | # else 40 | # define EGGS_CXX11_STATIC_CONSTEXPR static constexpr 41 | # endif 42 | # define EGGS_CXX11_STATIC_CONSTEXPR_DEFINED 43 | #endif 44 | 45 | #ifndef EGGS_CXX14_HAS_CONSTEXPR 46 | # if EGGS_CXX11_HAS_CONSTEXPR == 0 47 | # define EGGS_CXX14_HAS_CONSTEXPR 0 48 | # elif __cpp_constexpr >= 201304L 49 | # define EGGS_CXX14_HAS_CONSTEXPR 1 50 | # elif defined(_MSC_VER) 51 | # if _MSC_VER < 1910 52 | # define EGGS_CXX14_HAS_CONSTEXPR 0 53 | # else 54 | # define EGGS_CXX14_HAS_CONSTEXPR 1 55 | # endif 56 | # elif __cplusplus < 201402L 57 | # define EGGS_CXX14_HAS_CONSTEXPR 0 58 | # else 59 | # define EGGS_CXX14_HAS_CONSTEXPR 1 60 | # endif 61 | # define EGGS_CXX14_HAS_CONSTEXPR_DEFINED 62 | #endif 63 | 64 | #ifndef EGGS_CXX14_CONSTEXPR 65 | # if EGGS_CXX14_HAS_CONSTEXPR == 0 66 | # define EGGS_CXX14_CONSTEXPR 67 | # else 68 | # define EGGS_CXX14_CONSTEXPR constexpr 69 | # endif 70 | # define EGGS_CXX14_CONSTEXPR_DEFINED 71 | #endif 72 | 73 | /// RTTI support 74 | #ifndef EGGS_CXX98_HAS_RTTI 75 | # if __cpp_rtti >= 199711L 76 | # define EGGS_CXX98_HAS_RTTI 1 77 | # elif defined(__clang__) 78 | # define EGGS_CXX98_HAS_RTTI __has_feature(cxx_rtti) 79 | # elif defined(__GNUC__) && !defined(__GXX_RTTI) 80 | # define EGGS_CXX98_HAS_RTTI 0 81 | # elif defined(_MSC_VER) && !defined(_CPPRTTI) 82 | # define EGGS_CXX98_HAS_RTTI 0 83 | # else 84 | # define EGGS_CXX98_HAS_RTTI 1 85 | # endif 86 | # define EGGS_CXX98_HAS_RTTI_DEFINED 87 | #endif 88 | 89 | /// RTTI constexpr support 90 | #ifndef EGGS_CXX11_HAS_CONSTEXPR_RTTI 91 | # if EGGS_CXX98_HAS_RTTI == 0 || EGGS_CXX11_HAS_CONSTEXPR == 0 92 | # define EGGS_CXX11_HAS_CONSTEXPR_RTTI 0 93 | # elif defined(_MSC_VER) 94 | # define EGGS_CXX11_HAS_CONSTEXPR_RTTI 0 95 | # else 96 | # define EGGS_CXX11_HAS_CONSTEXPR_RTTI 1 97 | # endif 98 | # define EGGS_CXX11_HAS_CONSTEXPR_RTTI_DEFINED 99 | #endif 100 | 101 | /// exception support 102 | #ifndef EGGS_CXX98_HAS_EXCEPTIONS 103 | # if __cpp_exceptions >= 199711L 104 | # define EGGS_CXX98_HAS_EXCEPTIONS 1 105 | # elif defined(__clang__) 106 | # define EGGS_CXX98_HAS_EXCEPTIONS __has_feature(cxx_exceptions) 107 | # elif defined(__GNUC__) && !defined(__EXCEPTIONS) 108 | # define EGGS_CXX98_HAS_EXCEPTIONS 0 109 | # elif defined(_MSC_VER) && !defined(_CPPUNWIND) 110 | # define EGGS_CXX98_HAS_EXCEPTIONS 0 111 | # else 112 | # define EGGS_CXX98_HAS_EXCEPTIONS 1 113 | # endif 114 | # define EGGS_CXX98_HAS_EXCEPTIONS_DEFINED 115 | #endif 116 | 117 | /// noreturn support 118 | #ifndef EGGS_CXX11_NORETURN 119 | # if defined(__has_cpp_attribute) 120 | # if __has_cpp_attribute(noreturn) 121 | # define EGGS_CXX11_NORETURN [[noreturn]] 122 | # else 123 | # define EGGS_CXX11_NORETURN 124 | # endif 125 | # elif defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) && !defined(__clang__) 126 | # define EGGS_CXX11_NORETURN __attribute__ ((__noreturn__)) 127 | # elif defined(_MSC_VER) && _MSC_VER < 1900 128 | # define EGGS_CXX11_NORETURN __declspec(noreturn) 129 | # else 130 | # define EGGS_CXX11_NORETURN [[noreturn]] 131 | # endif 132 | # define EGGS_CXX11_NORETURN_DEFINED 133 | #endif 134 | 135 | /// sfinae for expressions support 136 | #ifndef EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 137 | # if defined(_MSC_VER) && _MSC_VER < 1910 138 | # define EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 0 139 | # elif defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9)) && !defined(__clang__) 140 | # define EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 0 141 | # else 142 | # define EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 1 143 | # endif 144 | # define EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS_DEFINED 145 | #endif 146 | 147 | /// variable templates support 148 | #ifndef EGGS_CXX14_HAS_VARIABLE_TEMPLATES 149 | # if __cpp_variable_templates >= 201304L 150 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES 1 151 | # elif defined(_MSC_VER) 152 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES 1 153 | # elif __cplusplus < 201402L 154 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES 0 155 | # elif defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__) 156 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES 0 157 | # else 158 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES 1 159 | # endif 160 | # define EGGS_CXX14_HAS_VARIABLE_TEMPLATES_DEFINED 161 | #endif 162 | 163 | /// inline variables support 164 | #ifndef EGGS_CXX17_HAS_INLINE_VARIABLES 165 | # if __cpp_inline_variables >= 201606L 166 | # define EGGS_CXX17_HAS_INLINE_VARIABLES 1 167 | # elif defined(_MSC_VER) 168 | # if _MSC_VER < 1912 || !_HAS_CXX17 169 | # define EGGS_CXX17_HAS_INLINE_VARIABLES 0 170 | # else 171 | # define EGGS_CXX17_HAS_INLINE_VARIABLES 1 172 | # endif 173 | # elif __cplusplus < 201703L 174 | # define EGGS_CXX17_HAS_INLINE_VARIABLES 0 175 | # else 176 | # define EGGS_CXX17_HAS_INLINE_VARIABLES 1 177 | # endif 178 | # define EGGS_CXX17_HAS_INLINE_VARIABLES_DEFINED 179 | #endif 180 | 181 | #ifndef EGGS_CXX17_INLINE 182 | # if EGGS_CXX17_HAS_INLINE_VARIABLES == 0 183 | # define EGGS_CXX17_INLINE 184 | # else 185 | # define EGGS_CXX17_INLINE inline 186 | # endif 187 | # define EGGS_CXX17_INLINE_DEFINED 188 | #endif 189 | 190 | /// std::is_nothrow_* support 191 | #ifndef EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 192 | # if defined(__GLIBCXX__) && !defined(_GLIBCXX_NOEXCEPT) 193 | # define EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 0 194 | # else 195 | # define EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 1 196 | # endif 197 | # define EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS_DEFINED 198 | #endif 199 | 200 | /// std::is_trivially_copyable support 201 | #ifndef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 202 | # if defined(__GLIBCXX__) 203 | # if defined(__has_include) 204 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE __has_include() // 5.0+ 205 | # else 206 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 0 207 | # endif 208 | # elif defined(_MSC_VER) && _MSC_VER < 1910 209 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 0 210 | # else 211 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 1 212 | # endif 213 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE_DEFINED 214 | #endif 215 | 216 | /// std::is_trivially_destructible support 217 | #ifndef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 218 | # if defined(__GLIBCXX__) 219 | # if defined(__has_include) 220 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE __has_include() // 4.8+ 221 | # else 222 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 0 223 | # endif 224 | # else 225 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 1 226 | # endif 227 | # define EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE_DEFINED 228 | #endif 229 | 230 | /// constexpr std::addressof support 231 | #ifndef EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 232 | # if EGGS_CXX11_HAS_CONSTEXPR == 0 233 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 0 234 | # elif __cpp_lib_addressof_constexpr >= 201603L 235 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 1 236 | # elif defined(_MSC_VER) 237 | # if _MSC_VER < 1910 238 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 0 239 | # else 240 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 1 241 | # endif 242 | # elif __cplusplus < 201703L || defined(__GLIBCXX__) 243 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 0 244 | # else 245 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 1 246 | # endif 247 | # define EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF_DEFINED 248 | #endif 249 | 250 | /// std::is_[nothrow_]swappable support 251 | #ifndef EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 252 | # if __cpp_lib_is_swappable >= 201603L 253 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 1 254 | # elif defined(_MSC_VER) 255 | # if _MSC_VER < 1910 || !_HAS_CXX17 256 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 0 257 | # else 258 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 1 259 | # endif 260 | # elif __cplusplus < 201703L || defined(__GLIBCXX__) 261 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 0 262 | # else 263 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 1 264 | # endif 265 | # define EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS_DEFINED 266 | #endif 267 | 268 | #if defined(_MSC_VER) 269 | # pragma warning(push) 270 | /// destructor was implicitly defined as deleted because a base class 271 | /// destructor is inaccessible or deleted 272 | # pragma warning(disable: 4624) 273 | #endif 274 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/config/suffix.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/config/suffix.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | /// no header guards 10 | 11 | /// constexpr support 12 | #ifdef EGGS_CXX11_HAS_CONSTEXPR_DEFINED 13 | # undef EGGS_CXX11_HAS_CONSTEXPR 14 | # undef EGGS_CXX11_HAS_CONSTEXPR_DEFINED 15 | #endif 16 | 17 | #ifdef EGGS_CXX11_CONSTEXPR_DEFINED 18 | # undef EGGS_CXX11_CONSTEXPR 19 | # undef EGGS_CXX11_CONSTEXPR_DEFINED 20 | #endif 21 | 22 | #ifdef EGGS_CXX11_STATIC_CONSTEXPR_DEFINED 23 | # undef EGGS_CXX11_STATIC_CONSTEXPR 24 | # undef EGGS_CXX11_STATIC_CONSTEXPR_DEFINED 25 | #endif 26 | 27 | #ifdef EGGS_CXX14_HAS_CONSTEXPR_DEFINED 28 | # undef EGGS_CXX14_HAS_CONSTEXPR 29 | # undef EGGS_CXX14_HAS_CONSTEXPR_DEFINED 30 | #endif 31 | 32 | #ifdef EGGS_CXX14_CONSTEXPR_DEFINED 33 | # undef EGGS_CXX14_CONSTEXPR 34 | # undef EGGS_CXX14_CONSTEXPR_DEFINED 35 | #endif 36 | 37 | /// RTTI support 38 | #ifdef EGGS_CXX98_HAS_RTTI_DEFINED 39 | # undef EGGS_CXX98_HAS_RTTI 40 | # undef EGGS_CXX98_HAS_RTTI_DEFINED 41 | #endif 42 | 43 | /// RTTI constexpr support 44 | #ifdef EGGS_CXX11_HAS_CONSTEXPR_RTTI_DEFINED 45 | # undef EGGS_CXX11_HAS_CONSTEXPR_RTTI 46 | # undef EGGS_CXX11_HAS_CONSTEXPR_RTTI_DEFINED 47 | #endif 48 | 49 | /// exception support 50 | #ifdef EGGS_CXX98_HAS_EXCEPTIONS_DEFINED 51 | # undef EGGS_CXX98_HAS_EXCEPTIONS 52 | # undef EGGS_CXX98_HAS_EXCEPTIONS_DEFINED 53 | #endif 54 | 55 | /// noreturn support 56 | #ifdef EGGS_CXX11_NORETURN_DEFINED 57 | # undef EGGS_CXX11_NORETURN 58 | # undef EGGS_CXX11_NORETURN_DEFINED 59 | #endif 60 | 61 | /// sfinae for expressions support 62 | #ifdef EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS_DEFINED 63 | # undef EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 64 | # undef EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS_DEFINED 65 | #endif 66 | 67 | /// variable templates support 68 | #ifdef EGGS_CXX14_HAS_VARIABLE_TEMPLATES_DEFINED 69 | # undef EGGS_CXX14_HAS_VARIABLE_TEMPLATES 70 | # undef EGGS_CXX14_HAS_VARIABLE_TEMPLATES_DEFINED 71 | #endif 72 | 73 | /// inline variables support 74 | #ifdef EGGS_CXX17_HAS_INLINE_VARIABLES_DEFINED 75 | # undef EGGS_CXX17_HAS_INLINE_VARIABLES 76 | # undef EGGS_CXX17_HAS_INLINE_VARIABLES_DEFINED 77 | #endif 78 | 79 | #ifdef EGGS_CXX17_INLINE_DEFINED 80 | # undef EGGS_CXX17_INLINE 81 | # undef EGGS_CXX17_INLINE_DEFINED 82 | #endif 83 | 84 | /// std::is_nothrow_* support 85 | #ifdef EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS_DEFINED 86 | # undef EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 87 | # undef EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS_DEFINED 88 | #endif 89 | 90 | /// std::is_trivially_copyable support 91 | #ifdef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE_DEFINED 92 | # undef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 93 | # undef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE_DEFINED 94 | #endif 95 | 96 | /// std::is_trivially_destructible support 97 | #ifdef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE_DEFINED 98 | # undef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 99 | # undef EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE_DEFINED 100 | #endif 101 | 102 | /// constexpr std::addressof support 103 | #ifdef EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF_DEFINED 104 | # undef EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 105 | # undef EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF_DEFINED 106 | #endif 107 | 108 | /// std::is_[nothrow_]swappable support 109 | #ifdef EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS_DEFINED 110 | # undef EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 111 | # undef EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS_DEFINED 112 | #endif 113 | 114 | #if defined(_MSC_VER) 115 | # pragma warning(pop) 116 | #endif 117 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/pack.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/pack.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_DETAIL_PACK_HPP 10 | #define EGGS_VARIANT_DETAIL_PACK_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "config/prefix.hpp" 17 | 18 | namespace eggs { namespace variants { namespace detail 19 | { 20 | struct empty 21 | { 22 | EGGS_CXX11_CONSTEXPR empty() noexcept {} 23 | EGGS_CXX11_CONSTEXPR bool operator==(empty) const { return true; } 24 | EGGS_CXX11_CONSTEXPR bool operator!=(empty) const { return false; } 25 | EGGS_CXX11_CONSTEXPR bool operator<(empty) const { return false; } 26 | EGGS_CXX11_CONSTEXPR bool operator>(empty) const { return false; } 27 | EGGS_CXX11_CONSTEXPR bool operator<=(empty) const { return true; } 28 | EGGS_CXX11_CONSTEXPR bool operator>=(empty) const { return true; } 29 | }; 30 | 31 | template 32 | struct identity 33 | { 34 | using type = T; 35 | }; 36 | 37 | template 38 | struct index 39 | { 40 | EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = I; 41 | }; 42 | 43 | template 44 | struct pack 45 | { 46 | using type = pack; 47 | EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Ts); 48 | }; 49 | 50 | template 51 | struct pack_c 52 | { 53 | using type = pack_c; 54 | EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Vs); 55 | }; 56 | 57 | template 58 | static EGGS_CXX11_CONSTEXPR int swallow_pack(Ts const&...) noexcept 59 | { 60 | return 0; 61 | } 62 | 63 | /////////////////////////////////////////////////////////////////////////// 64 | template 65 | struct _make_index_pack_twice; 66 | 67 | template 68 | struct _make_index_pack_twice< 69 | pack_c 70 | , false 71 | > : pack_c 72 | {}; 73 | 74 | template 75 | struct _make_index_pack_twice< 76 | pack_c 77 | , true 78 | > : pack_c 79 | {}; 80 | 81 | template 82 | struct _make_index_pack 83 | : _make_index_pack_twice< 84 | typename _make_index_pack::type 85 | , N % 2 != 0 86 | > 87 | {}; 88 | 89 | template <> 90 | struct _make_index_pack<1> 91 | : pack_c 92 | {}; 93 | 94 | template <> 95 | struct _make_index_pack<0> 96 | : pack_c 97 | {}; 98 | 99 | template 100 | using make_index_pack = typename _make_index_pack::type; 101 | 102 | template 103 | struct _index_pack; 104 | 105 | template 106 | struct _index_pack> 107 | : _make_index_pack 108 | {}; 109 | 110 | template 111 | using index_pack = typename _index_pack::type; 112 | 113 | /////////////////////////////////////////////////////////////////////////// 114 | template 115 | struct _make_typed_pack; 116 | 117 | template 118 | struct _make_typed_pack> 119 | : pack...> 120 | {}; 121 | 122 | template 123 | struct _typed_index_pack 124 | : _make_typed_pack> 125 | {}; 126 | 127 | template 128 | using typed_index_pack = typename _typed_index_pack::type; 129 | 130 | /////////////////////////////////////////////////////////////////////////// 131 | template 132 | struct all_of; 133 | 134 | template 135 | struct all_of> 136 | : std::integral_constant< 137 | bool 138 | , std::is_same< 139 | pack_c 140 | , pack_c // true... 141 | >::value 142 | > 143 | {}; 144 | 145 | template 146 | using _always_true = std::true_type; 147 | 148 | template 149 | static std::false_type _all_of(...); 150 | 151 | template 152 | static auto _all_of(int) -> _always_true< 153 | typename std::enable_if::type...>; 154 | 155 | template 156 | struct all_of> 157 | : decltype(detail::_all_of(0)) 158 | {}; 159 | 160 | /////////////////////////////////////////////////////////////////////////// 161 | template 162 | struct any_of; 163 | 164 | template 165 | struct any_of> 166 | : std::integral_constant< 167 | bool 168 | , !std::is_same< 169 | pack_c 170 | , pack_c // false... 171 | >::value 172 | > 173 | {}; 174 | 175 | template 176 | using _always_false = std::false_type; 177 | 178 | template 179 | static std::true_type _any_of(...); 180 | 181 | template 182 | static auto _any_of(int) -> _always_false< 183 | typename std::enable_if::type...>; 184 | 185 | template 186 | struct any_of> 187 | : decltype(detail::_any_of(0)) 188 | {}; 189 | 190 | /////////////////////////////////////////////////////////////////////////// 191 | template 192 | struct _indexed {}; 193 | 194 | template > 195 | struct _indexer; 196 | 197 | template 198 | struct _indexer, pack_c> 199 | : _indexed... 200 | {}; 201 | 202 | template 203 | static empty _at_index(...); 204 | 205 | template 206 | static identity _at_index(_indexed const&); 207 | 208 | template 209 | struct at_index 210 | : decltype(detail::_at_index(_indexer{})) 211 | {}; 212 | 213 | template 214 | struct count_of; 215 | 216 | template 217 | struct count_of> 218 | { 219 | EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = 0; 220 | }; 221 | 222 | template 223 | struct count_of> 224 | { 225 | EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = 226 | count_of>::value 227 | + (std::is_same::value ? 1 : 0); 228 | }; 229 | 230 | template 231 | static empty _index_of(...); 232 | 233 | template 234 | static index _index_of(_indexed const&); 235 | 236 | template 237 | struct index_of 238 | #if 0 239 | // most compilers get this wrong in the case of duplicated types 240 | : decltype(detail::_index_of(_indexer{})) 241 | #else 242 | : std::conditional< 243 | count_of::value == 1 244 | , decltype(detail::_index_of(_indexer{})) 245 | , empty 246 | >::type 247 | #endif 248 | {}; 249 | }}} 250 | 251 | #include "config/suffix.hpp" 252 | 253 | #endif /*EGGS_VARIANT_DETAIL_PACK_HPP*/ 254 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/utility.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/utility.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_DETAIL_UTILITY_HPP 10 | #define EGGS_VARIANT_DETAIL_UTILITY_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "config/prefix.hpp" 17 | 18 | namespace eggs { namespace variants { namespace detail 19 | { 20 | template 21 | EGGS_CXX11_CONSTEXPR T&& forward( 22 | typename std::remove_reference::type& t) noexcept 23 | { 24 | return static_cast(t); 25 | } 26 | 27 | template 28 | EGGS_CXX11_CONSTEXPR T&& forward( 29 | typename std::remove_reference::type&& t) noexcept 30 | { 31 | return static_cast(t); 32 | } 33 | 34 | /////////////////////////////////////////////////////////////////////////// 35 | template 36 | EGGS_CXX11_CONSTEXPR typename std::remove_reference::type&& move( 37 | T&& t) noexcept 38 | { 39 | return static_cast::type&&>(t); 40 | } 41 | 42 | /////////////////////////////////////////////////////////////////////////// 43 | #if EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF 44 | using std::addressof; 45 | #else 46 | namespace _addressof 47 | { 48 | struct _fallback {}; 49 | 50 | template 51 | static _fallback operator&(T&&); 52 | 53 | template 54 | struct has_addressof_operator 55 | { 56 | EGGS_CXX11_STATIC_CONSTEXPR bool value = 57 | (std::is_class::value || std::is_union::value) 58 | && !std::is_same()), _fallback>::value; 59 | }; 60 | } 61 | 62 | template 63 | EGGS_CXX11_CONSTEXPR typename std::enable_if< 64 | !_addressof::has_addressof_operator::value 65 | , T* 66 | >::type addressof(T& r) noexcept 67 | { 68 | return &r; 69 | } 70 | 71 | template 72 | typename std::enable_if< 73 | _addressof::has_addressof_operator::value 74 | , T* 75 | >::type addressof(T& r) noexcept 76 | { 77 | return std::addressof(r); 78 | } 79 | #endif 80 | }}} 81 | 82 | #include "config/suffix.hpp" 83 | 84 | #endif /*EGGS_VARIANT_DETAIL_UTILITY_HPP*/ 85 | -------------------------------------------------------------------------------- /include/eggs/variant/detail/visitor.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/detail/visitor.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_DETAIL_VISITOR_HPP 10 | #define EGGS_VARIANT_DETAIL_VISITOR_HPP 11 | 12 | #include "pack.hpp" 13 | #include "utility.hpp" 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "config/prefix.hpp" 25 | 26 | namespace eggs { namespace variants { namespace detail 27 | { 28 | /////////////////////////////////////////////////////////////////////////// 29 | template 30 | struct visitor; 31 | 32 | template 33 | struct visitor 34 | { 35 | template 36 | struct _table 37 | { 38 | static EGGS_CXX17_INLINE EGGS_CXX11_CONSTEXPR 39 | R (*value[pack::size])(Args...) 40 | = {&F::template call...}; 41 | }; 42 | 43 | #if defined(NDEBUG) 44 | static EGGS_CXX11_CONSTEXPR int _assert_in_range( 45 | std::size_t /*index*/, std::size_t /*size*/) 46 | { 47 | return 0; 48 | } 49 | #else 50 | static int _assert_in_range_failure(std::size_t index, std::size_t size) 51 | { 52 | assert(index < size && "discriminator out of range"); 53 | return 0; 54 | } 55 | 56 | static EGGS_CXX11_CONSTEXPR int _assert_in_range( 57 | std::size_t index, std::size_t size) 58 | { 59 | return index < size ? 0 : _assert_in_range_failure(index, size); 60 | } 61 | #endif 62 | 63 | template 64 | EGGS_CXX11_CONSTEXPR R operator()(pack, std::size_t which, 65 | Args&&... args) const 66 | { 67 | return _assert_in_range(which, sizeof...(Ts)), 68 | _table::value[which](detail::forward(args)...); 69 | } 70 | 71 | EGGS_CXX11_NORETURN R operator()(pack<>, std::size_t, Args&&...) const 72 | { 73 | std::terminate(); 74 | } 75 | }; 76 | 77 | #if !EGGS_CXX17_HAS_INLINE_VARIABLES 78 | template 79 | template 80 | EGGS_CXX11_CONSTEXPR R (*visitor::_table:: 81 | value[pack::size])(Args...); 82 | #endif 83 | 84 | /////////////////////////////////////////////////////////////////////////// 85 | struct copy_construct 86 | : visitor 87 | { 88 | template 89 | static void call(void* ptr, void const* other) 90 | { 91 | ::new (ptr) T(*static_cast(other)); 92 | } 93 | }; 94 | 95 | struct move_construct 96 | : visitor 97 | { 98 | template 99 | static void call(void* ptr, void* other) 100 | { 101 | ::new (ptr) T(detail::move(*static_cast(other))); 102 | } 103 | }; 104 | 105 | struct copy_assign 106 | : visitor 107 | { 108 | template 109 | static void call(void* ptr, void const* other) 110 | { 111 | *static_cast(ptr) = *static_cast(other); 112 | } 113 | }; 114 | 115 | struct move_assign 116 | : visitor 117 | { 118 | template 119 | static void call(void* ptr, void* other) 120 | { 121 | *static_cast(ptr) = detail::move(*static_cast(other)); 122 | } 123 | }; 124 | 125 | struct destroy 126 | : visitor 127 | { 128 | template 129 | static void call(void* ptr) 130 | { 131 | static_cast(ptr)->~T(); 132 | (void)ptr; // silence bogus unreferenced formal parameter warning 133 | } 134 | }; 135 | 136 | struct swap 137 | : visitor 138 | { 139 | template 140 | static void call(void* ptr, void* other) 141 | { 142 | using std::swap; 143 | swap(*static_cast(ptr), *static_cast(other)); 144 | } 145 | }; 146 | 147 | #if EGGS_CXX98_HAS_RTTI 148 | struct type_id 149 | : visitor 150 | { 151 | template 152 | static EGGS_CXX11_CONSTEXPR std::type_info const& call() 153 | { 154 | return typeid(T); 155 | } 156 | }; 157 | #endif 158 | 159 | template 160 | struct equal_to 161 | : visitor, bool(Union const&, Union const&)> 162 | { 163 | template 164 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 165 | { 166 | return lhs.get(I{}) == rhs.get(I{}); 167 | } 168 | }; 169 | 170 | template 171 | struct not_equal_to 172 | : visitor, bool(Union const&, Union const&)> 173 | { 174 | template 175 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 176 | { 177 | return lhs.get(I{}) != rhs.get(I{}); 178 | } 179 | }; 180 | 181 | template 182 | struct less 183 | : visitor, bool(Union const&, Union const&)> 184 | { 185 | template 186 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 187 | { 188 | return lhs.get(I{}) < rhs.get(I{}); 189 | } 190 | }; 191 | 192 | template 193 | struct greater 194 | : visitor, bool(Union const&, Union const&)> 195 | { 196 | template 197 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 198 | { 199 | return lhs.get(I{}) > rhs.get(I{}); 200 | } 201 | }; 202 | 203 | template 204 | struct less_equal 205 | : visitor, bool(Union const&, Union const&)> 206 | { 207 | template 208 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 209 | { 210 | return lhs.get(I{}) <= rhs.get(I{}); 211 | } 212 | }; 213 | 214 | template 215 | struct greater_equal 216 | : visitor, bool(Union const&, Union const&)> 217 | { 218 | template 219 | static EGGS_CXX11_CONSTEXPR bool call(Union const& lhs, Union const& rhs) 220 | { 221 | return lhs.get(I{}) >= rhs.get(I{}); 222 | } 223 | }; 224 | 225 | struct hash 226 | : visitor 227 | { 228 | template 229 | static std::size_t call(void const* ptr) 230 | { 231 | std::hash::type> h; 232 | return h(*static_cast(ptr)); 233 | } 234 | }; 235 | 236 | template 237 | struct target 238 | : visitor, T*(Union&)> 239 | { 240 | static EGGS_CXX11_CONSTEXPR T* _impl(T* ptr) 241 | { 242 | return ptr; 243 | } 244 | 245 | static EGGS_CXX11_CONSTEXPR T* _impl(void const*) 246 | { 247 | return nullptr; 248 | } 249 | 250 | template 251 | static EGGS_CXX11_CONSTEXPR T* call(Union& u) 252 | { 253 | return target::_impl(detail::addressof(u.get(I{}))); 254 | } 255 | }; 256 | }}} 257 | 258 | #include "config/suffix.hpp" 259 | 260 | #endif /*EGGS_VARIANT_DETAIL_VISITOR_HPP*/ 261 | -------------------------------------------------------------------------------- /include/eggs/variant/in_place.hpp: -------------------------------------------------------------------------------- 1 | //! \file eggs/variant/in_place.hpp 2 | // Eggs.Variant 3 | // 4 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 5 | // 6 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #ifndef EGGS_VARIANT_IN_PLACE_HPP 10 | #define EGGS_VARIANT_IN_PLACE_HPP 11 | 12 | #include 13 | #include 14 | 15 | #include "detail/config/prefix.hpp" 16 | 17 | namespace eggs { namespace variants 18 | { 19 | namespace detail 20 | { 21 | template 22 | struct in_place_index_tag {}; 23 | 24 | template 25 | struct in_place_type_tag {}; 26 | } 27 | 28 | /////////////////////////////////////////////////////////////////////////// 29 | //! The template aliases `in_place_index_t` and `in_place_type_t` are used 30 | //! as unique types to disambiguate constructor and function overloading. 31 | //! Specifically, `variant` has a constructor with 32 | //! `in_place_type_t`as the first parameter, followed by a parameter 33 | //! pack; this indicates that `T` should be constructed in-place (as if 34 | //! by a call to a placement new expression) with the forwarded pack 35 | //! expansion as arguments for the initialization of `T`. 36 | 37 | //! template 38 | //! using in_place_index_t = void(*)(unspecified); 39 | template 40 | using in_place_index_t = void(*)(detail::in_place_index_tag); 41 | 42 | //! template 43 | //! using in_place_type_t = void(*)(unspecified); 44 | template 45 | using in_place_type_t = void(*)(detail::in_place_type_tag); 46 | 47 | //! template 48 | //! void in_place(unspecified); 49 | template 50 | inline void in_place(detail::in_place_index_tag = {}) {} 51 | 52 | //! template 53 | //! void in_place(unspecified); 54 | template 55 | inline void in_place(detail::in_place_type_tag = {}) {} 56 | 57 | /////////////////////////////////////////////////////////////////////////// 58 | namespace detail 59 | { 60 | template 61 | struct is_inplace_tag 62 | : std::false_type 63 | {}; 64 | 65 | template 66 | struct is_inplace_tag> 67 | : std::true_type 68 | {}; 69 | 70 | template 71 | struct is_inplace_tag> 72 | : std::true_type 73 | {}; 74 | } 75 | }} 76 | 77 | #include "detail/config/suffix.hpp" 78 | 79 | #endif /*EGGS_VARIANT_IN_PLACE_HPP*/ 80 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Eggs.Variant 2 | # 3 | # Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | # file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | add_library(Catch2 OBJECT catch.cpp) 9 | 10 | set(_tests 11 | apply 12 | assign.conversion 13 | assign.copy 14 | assign.emplace 15 | assign.move 16 | cnstr.conversion 17 | cnstr.copy 18 | cnstr.default 19 | cnstr.emplace 20 | cnstr.move 21 | dtor 22 | elem.get 23 | elem.get_if 24 | hash 25 | helper 26 | in_place 27 | obs.bool 28 | obs.target 29 | obs.target_type 30 | obs.which 31 | rel.equality 32 | rel.order 33 | swap) 34 | foreach (_test ${_tests}) 35 | add_executable(test.${_test} ${_test}.cpp $) 36 | target_link_libraries(test.${_test} Eggs::Variant) 37 | 38 | add_test(NAME test.${_test} COMMAND test.${_test}) 39 | endforeach() 40 | 41 | # Test for leaked configuration macros 42 | set(_contents "// This file is auto-generated by CMake to test for multiple definition errors.\n") 43 | 44 | set(_config_macros 45 | cxx11_has_constexpr 46 | cxx11_constexpr 47 | cxx11_static_constexpr 48 | cxx14_has_constexpr 49 | cxx14_constexpr 50 | cxx98_has_rtti 51 | cxx11_has_constexpr_rtti 52 | cxx98_has_exceptions 53 | cxx11_noreturn 54 | cxx11_has_sfinae_for_expressions 55 | cxx14_has_variable_templates 56 | cxx17_has_inline_variables 57 | cxx17_inline 58 | cxx17_std_has_constexpr_addressof 59 | cxx11_std_has_is_nothrow_traits 60 | cxx17_std_has_swappable_traits 61 | cxx11_std_has_is_trivially_copyable 62 | cxx11_std_has_is_trivially_destructible) 63 | foreach (_config_macro ${_config_macros}) 64 | string(TOUPPER "${_config_macro}" _config_macro) 65 | set(_contents_prefix "${_contents_prefix}#if defined(EGGS_${_config_macro})\n") 66 | set(_contents_prefix "${_contents_prefix}# define ${_config_macro}_DEFINED\n") 67 | set(_contents_prefix "${_contents_prefix}#endif\n") 68 | set(_contents_suffix "${_contents_suffix}#if !defined(${_config_macro}_DEFINED)\n") 69 | set(_contents_suffix "${_contents_suffix}#if defined(EGGS_${_config_macro}) || defined(EGGS_${_config_macro}_DEFINED)\n") 70 | set(_contents_suffix "${_contents_suffix}# error EGGS_${_config_macro} leaked\n") 71 | set(_contents_suffix "${_contents_suffix}# endif\n") 72 | set(_contents_suffix "${_contents_suffix}#endif\n") 73 | endforeach() 74 | 75 | set(_source "${CMAKE_CURRENT_BINARY_DIR}/leaked_config_macros.cpp") 76 | set(_contents "${_contents_prefix}#include \n${_contents_suffix}") 77 | file(WRITE "${_source}" "${_contents}int main() {}\n") 78 | 79 | add_executable(test.leaked_config_macros "${_source}") 80 | target_link_libraries(test.leaked_config_macros Eggs::Variant) 81 | add_test(NAME test.leaked_config_macros COMMAND test.leaked_config_macros) 82 | 83 | # Test for multiple definition errors 84 | set(_contents "// This file is auto-generated by CMake to test for multiple definition errors.\n") 85 | 86 | file(GLOB_RECURSE _headers 87 | RELATIVE "${PROJECT_SOURCE_DIR}/include" 88 | "${PROJECT_SOURCE_DIR}/include/*.hpp") 89 | foreach (_header ${_headers}) 90 | set(_contents "${_contents}#include <${_header}>\n") 91 | endforeach() 92 | 93 | set(_source_one "${CMAKE_CURRENT_BINARY_DIR}/multiple_definitions.one.cpp") 94 | file(WRITE "${_source_one}" "${_contents}int main() {}\n") 95 | 96 | set(_source_two "${CMAKE_CURRENT_BINARY_DIR}/multiple_definitions.two.cpp") 97 | file(WRITE "${_source_two}" "${_contents}") 98 | 99 | add_executable(test.multiple_definitions "${_source_one}" "${_source_two}") 100 | target_link_libraries(test.multiple_definitions Eggs::Variant) 101 | add_test(NAME test.multiple_definitions COMMAND test.multiple_definitions) 102 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eggs-cpp/variant/f801e971d054341430cb91d79aa0bb4d0bf24330/test/README.md -------------------------------------------------------------------------------- /test/apply.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using eggs::variants::detail::move; 16 | 17 | #include "catch.hpp" 18 | #include "constexpr.hpp" 19 | 20 | struct fun 21 | { 22 | std::size_t nonconst_lvalue, const_lvalue, rvalue; 23 | 24 | fun() : nonconst_lvalue{0}, const_lvalue{0}, rvalue{0} {} 25 | 26 | std::string operator()() 27 | { 28 | return ""; 29 | } 30 | 31 | template 32 | static std::string to_string(T const& t) 33 | { 34 | std::ostringstream oss; 35 | oss << t; 36 | return oss.str(); 37 | } 38 | 39 | template 40 | static std::string to_string(T const& t, U const& u) 41 | { 42 | std::ostringstream oss; 43 | oss << t << ',' << u; 44 | return oss.str(); 45 | } 46 | 47 | template 48 | std::string operator()(T& t) 49 | { 50 | ++nonconst_lvalue; 51 | return to_string(t); 52 | } 53 | 54 | template 55 | std::string operator()(T& t, U& u) 56 | { 57 | ++nonconst_lvalue; 58 | return to_string(t, u); 59 | } 60 | 61 | template 62 | std::string operator()(T const& t) 63 | { 64 | ++const_lvalue; 65 | return to_string(t); 66 | } 67 | 68 | template 69 | std::string operator()(T const& t, U const& u) 70 | { 71 | ++const_lvalue; 72 | return to_string(t, u); 73 | } 74 | 75 | template 76 | std::string operator()(T&& t) 77 | { 78 | ++rvalue; 79 | return to_string(t); 80 | } 81 | 82 | template 83 | std::string operator()(T&& t, U&& u) 84 | { 85 | ++rvalue; 86 | return to_string(t, u); 87 | } 88 | }; 89 | 90 | #if EGGS_CXX11_HAS_CONSTEXPR 91 | struct constexpr_fun 92 | { 93 | constexpr std::size_t operator()() const 94 | { 95 | return 0u; 96 | } 97 | 98 | template 99 | constexpr std::size_t operator()(T const&) const 100 | { 101 | return sizeof(T); 102 | } 103 | 104 | template 105 | constexpr std::size_t operator()(T const&, U const&) const 106 | { 107 | return sizeof(T) + sizeof(U); 108 | } 109 | }; 110 | #endif 111 | 112 | struct variant_like 113 | : eggs::variant 114 | { 115 | variant_like(int value) 116 | : variant(value) 117 | {} 118 | 119 | variant_like(std::string const& value) 120 | : variant(value) 121 | {} 122 | }; 123 | 124 | TEST_CASE("apply(F&&, variant&)", "[variant.apply]") 125 | { 126 | eggs::variant v(42); 127 | 128 | REQUIRE(v.which() == 0u); 129 | REQUIRE(*v.target() == 42); 130 | 131 | fun f; 132 | std::string ret = eggs::variants::apply(f, v); 133 | 134 | CHECK(f.nonconst_lvalue == 1u); 135 | CHECK(ret == "42"); 136 | 137 | #if EGGS_CXX98_HAS_EXCEPTIONS 138 | // throws 139 | { 140 | eggs::variant empty; 141 | 142 | REQUIRE(empty.which() == eggs::variant_npos); 143 | 144 | CHECK_THROWS_AS( 145 | eggs::variants::apply(fun{}, empty) 146 | , eggs::variants::bad_variant_access); 147 | } 148 | #endif 149 | 150 | #if EGGS_CXX14_HAS_CONSTEXPR 151 | // constexpr 152 | { 153 | struct test { static constexpr int call() 154 | { 155 | eggs::variant v(Constexpr(42)); 156 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, v); 157 | return 0; 158 | }}; 159 | constexpr int c = test::call(); 160 | } 161 | #endif 162 | 163 | // variant-like 164 | { 165 | variant_like v(42); 166 | 167 | REQUIRE(v.which() == 0u); 168 | REQUIRE(*v.target() == 42); 169 | 170 | fun f; 171 | std::string ret = eggs::variants::apply(f, v); 172 | 173 | CHECK(f.nonconst_lvalue == 1u); 174 | CHECK(ret == "42"); 175 | } 176 | } 177 | 178 | TEST_CASE("apply(F&&, variant const&)", "[variant.apply]") 179 | { 180 | eggs::variant const v(42); 181 | 182 | REQUIRE(v.which() == 0u); 183 | REQUIRE(*v.target() == 42); 184 | 185 | fun f; 186 | std::string ret = eggs::variants::apply(f, v); 187 | 188 | CHECK(f.const_lvalue == 1u); 189 | CHECK(ret == "42"); 190 | 191 | #if EGGS_CXX98_HAS_EXCEPTIONS 192 | // throws 193 | { 194 | eggs::variant const empty; 195 | 196 | REQUIRE(empty.which() == eggs::variant_npos); 197 | 198 | CHECK_THROWS_AS( 199 | eggs::variants::apply(fun{}, empty) 200 | , eggs::variants::bad_variant_access); 201 | } 202 | #endif 203 | 204 | #if EGGS_CXX11_HAS_CONSTEXPR 205 | // constexpr 206 | { 207 | constexpr eggs::variant v(Constexpr(42)); 208 | constexpr std::size_t ar = eggs::variants::apply(constexpr_fun{}, v); 209 | } 210 | #endif 211 | 212 | // variant-like 213 | { 214 | variant_like const v(42); 215 | 216 | REQUIRE(v.which() == 0u); 217 | REQUIRE(*v.target() == 42); 218 | 219 | fun f; 220 | std::string ret = eggs::variants::apply(f, v); 221 | 222 | CHECK(f.const_lvalue == 1u); 223 | CHECK(ret == "42"); 224 | } 225 | } 226 | 227 | TEST_CASE("apply(F&&, variant&&)", "[variant.apply]") 228 | { 229 | eggs::variant v(42); 230 | 231 | REQUIRE(v.which() == 0u); 232 | REQUIRE(*v.target() == 42); 233 | 234 | fun f; 235 | std::string ret = eggs::variants::apply(f, ::move(v)); 236 | 237 | CHECK(f.rvalue == 1u); 238 | CHECK(ret == "42"); 239 | 240 | #if EGGS_CXX98_HAS_EXCEPTIONS 241 | // throws 242 | { 243 | eggs::variant empty; 244 | 245 | REQUIRE(empty.which() == eggs::variant_npos); 246 | 247 | CHECK_THROWS_AS( 248 | eggs::variants::apply(fun{}, ::move(empty)) 249 | , eggs::variants::bad_variant_access); 250 | } 251 | #endif 252 | 253 | #if EGGS_CXX14_HAS_CONSTEXPR 254 | // constexpr 255 | { 256 | struct test { static constexpr int call() 257 | { 258 | eggs::variant v(Constexpr(42)); 259 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, ::move(v)); 260 | return 0; 261 | }}; 262 | constexpr int c = test::call(); 263 | } 264 | #endif 265 | 266 | // variant-like 267 | { 268 | variant_like v(42); 269 | 270 | REQUIRE(v.which() == 0u); 271 | REQUIRE(*v.target() == 42); 272 | 273 | fun f; 274 | std::string ret = eggs::variants::apply(f, ::move(v)); 275 | 276 | CHECK(f.rvalue == 1u); 277 | CHECK(ret == "42"); 278 | } 279 | } 280 | 281 | #if EGGS_CXX98_HAS_EXCEPTIONS 282 | TEST_CASE("apply(F&&, variant<>&)", "[variant.apply]") 283 | { 284 | eggs::variant<> v; 285 | 286 | REQUIRE(v.which() == eggs::variant_npos); 287 | 288 | CHECK_THROWS_AS( 289 | eggs::variants::apply(fun{}, v) 290 | , eggs::variants::bad_variant_access); 291 | } 292 | 293 | TEST_CASE("apply(F&&, variant<> const&)", "[variant.apply]") 294 | { 295 | eggs::variant<> const v; 296 | 297 | REQUIRE(v.which() == eggs::variant_npos); 298 | 299 | CHECK_THROWS_AS( 300 | eggs::variants::apply(fun{}, ::move(v)) 301 | , eggs::variants::bad_variant_access); 302 | } 303 | 304 | TEST_CASE("apply(F&&, variant<>&&)", "[variant.apply]") 305 | { 306 | eggs::variant<> v; 307 | 308 | REQUIRE(v.which() == eggs::variant_npos); 309 | 310 | CHECK_THROWS_AS( 311 | eggs::variants::apply(fun{}, ::move(v)) 312 | , eggs::variants::bad_variant_access); 313 | } 314 | #endif 315 | 316 | TEST_CASE("apply(F&&, variant&)", "[variant.apply]") 317 | { 318 | eggs::variant v(42); 319 | 320 | REQUIRE(v.which() == 0u); 321 | REQUIRE(*v.target() == 42); 322 | 323 | fun f; 324 | std::string ret = eggs::variants::apply(f, v); 325 | 326 | CHECK(f.nonconst_lvalue == 1u); 327 | CHECK(ret == "42"); 328 | 329 | #if EGGS_CXX14_HAS_CONSTEXPR 330 | // constexpr 331 | { 332 | struct test { static constexpr int call() 333 | { 334 | eggs::variant v(Constexpr(42)); 335 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, v); 336 | return 0; 337 | }}; 338 | constexpr int c = test::call(); 339 | } 340 | #endif 341 | } 342 | 343 | TEST_CASE("apply(F&&, variant const&)", "[variant.apply]") 344 | { 345 | eggs::variant const v(42); 346 | 347 | REQUIRE(v.which() == 0u); 348 | REQUIRE(*v.target() == 42); 349 | 350 | fun f; 351 | std::string ret = eggs::variants::apply(f, v); 352 | 353 | CHECK(f.const_lvalue == 1u); 354 | CHECK(ret == "42"); 355 | 356 | #if EGGS_CXX11_HAS_CONSTEXPR 357 | // constexpr 358 | { 359 | constexpr eggs::variant v(Constexpr(42)); 360 | constexpr std::size_t ar = eggs::variants::apply(constexpr_fun{}, v); 361 | } 362 | #endif 363 | } 364 | 365 | TEST_CASE("apply(F&&, variant&&)", "[variant.apply]") 366 | { 367 | eggs::variant v(42); 368 | 369 | REQUIRE(v.which() == 0u); 370 | REQUIRE(*v.target() == 42); 371 | 372 | fun f; 373 | std::string ret = eggs::variants::apply(f, ::move(v)); 374 | 375 | CHECK(f.rvalue == 1u); 376 | CHECK(ret == "42"); 377 | 378 | #if EGGS_CXX14_HAS_CONSTEXPR 379 | // constexpr 380 | { 381 | struct test { static constexpr int call() 382 | { 383 | eggs::variant v(Constexpr(42)); 384 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, ::move(v)); 385 | return 0; 386 | }}; 387 | constexpr int c = test::call(); 388 | } 389 | #endif 390 | } 391 | 392 | TEST_CASE("apply(F&&)", "[variant.apply]") 393 | { 394 | fun f; 395 | std::string ret = eggs::variants::apply(f); 396 | 397 | CHECK(ret == ""); 398 | 399 | #if EGGS_CXX11_HAS_CONSTEXPR 400 | // constexpr 401 | { 402 | constexpr std::size_t ar = eggs::variants::apply(constexpr_fun{}); 403 | } 404 | #endif 405 | } 406 | 407 | TEST_CASE("apply(F&&)", "[variant.apply]") 408 | { 409 | fun f; 410 | std::string ret = eggs::variants::apply(f); 411 | 412 | CHECK(ret == ""); 413 | 414 | #if EGGS_CXX11_HAS_CONSTEXPR 415 | // constexpr 416 | { 417 | constexpr std::size_t ar = eggs::variants::apply(constexpr_fun{}); 418 | } 419 | #endif 420 | } 421 | 422 | TEST_CASE("apply(F&&, variant&, variant&)", "[variant.apply]") 423 | { 424 | eggs::variant v1(42); 425 | 426 | REQUIRE(v1.which() == 0u); 427 | REQUIRE(*v1.target() == 42); 428 | 429 | eggs::variant v2(std::string{"43"}); 430 | 431 | REQUIRE(v2.which() == 0u); 432 | REQUIRE(*v2.target() == "43"); 433 | 434 | fun f; 435 | std::string ret = eggs::variants::apply(f, v1, v2); 436 | 437 | CHECK(f.nonconst_lvalue == 1u); 438 | CHECK(ret == "42,43"); 439 | 440 | #if EGGS_CXX14_HAS_CONSTEXPR 441 | // constexpr 442 | { 443 | struct test { static constexpr int call() 444 | { 445 | eggs::variant v1(Constexpr(42)); 446 | eggs::variant v2(43); 447 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, v1, v2); 448 | return 0; 449 | }}; 450 | constexpr int c = test::call(); 451 | } 452 | #endif 453 | } 454 | 455 | TEST_CASE("apply(F&&, variant const&, variant const&)", "[variant.apply]") 456 | { 457 | eggs::variant const v1(42); 458 | 459 | REQUIRE(v1.which() == 0u); 460 | REQUIRE(*v1.target() == 42); 461 | 462 | eggs::variant const v2(std::string{"43"}); 463 | 464 | REQUIRE(v2.which() == 0u); 465 | REQUIRE(*v2.target() == "43"); 466 | 467 | fun f; 468 | std::string ret = eggs::variants::apply(f, v1, v2); 469 | 470 | CHECK(f.const_lvalue == 1u); 471 | CHECK(ret == "42,43"); 472 | 473 | #if EGGS_CXX11_HAS_CONSTEXPR 474 | // constexpr 475 | { 476 | constexpr eggs::variant v1(Constexpr(42)); 477 | constexpr eggs::variant v2(43); 478 | constexpr std::size_t ar = eggs::variants::apply(constexpr_fun{}, v1, v2); 479 | } 480 | #endif 481 | } 482 | 483 | TEST_CASE("apply(F&&, variant&&, variant&&)", "[variant.apply]") 484 | { 485 | eggs::variant v1(42); 486 | 487 | REQUIRE(v1.which() == 0u); 488 | REQUIRE(*v1.target() == 42); 489 | 490 | eggs::variant v2(std::string{"43"}); 491 | 492 | REQUIRE(v2.which() == 0u); 493 | REQUIRE(*v2.target() == "43"); 494 | 495 | fun f; 496 | std::string ret = eggs::variants::apply(f, ::move(v1), ::move(v2)); 497 | 498 | CHECK(f.rvalue == 1u); 499 | CHECK(ret == "42,43"); 500 | 501 | #if EGGS_CXX14_HAS_CONSTEXPR 502 | // constexpr 503 | { 504 | struct test { static constexpr int call() 505 | { 506 | eggs::variant v1(Constexpr(42)); 507 | eggs::variant v2(43); 508 | std::size_t ar = eggs::variants::apply(constexpr_fun{}, ::move(v1), ::move(v2)); 509 | return 0; 510 | }}; 511 | constexpr int c = test::call(); 512 | } 513 | #endif 514 | } 515 | -------------------------------------------------------------------------------- /test/assign.conversion.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "catch.hpp" 15 | #include "constexpr.hpp" 16 | #include "dtor.hpp" 17 | #include "throw.hpp" 18 | 19 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 20 | struct WeirdAssignment 21 | { 22 | WeirdAssignment(long) {} 23 | 24 | WeirdAssignment& operator=(WeirdAssignment const&) = default; 25 | WeirdAssignment& operator=(long) = delete; 26 | }; 27 | 28 | struct WeirdConstructor 29 | { 30 | WeirdConstructor(int) {} 31 | explicit WeirdConstructor(long) = delete; 32 | }; 33 | #endif 34 | 35 | TEST_CASE("variant::operator=(T&&)", "[variant.assign]") 36 | { 37 | // empty target 38 | { 39 | eggs::variant v; 40 | 41 | REQUIRE(bool(v) == false); 42 | REQUIRE(v.which() == eggs::variant_npos); 43 | 44 | v = 42; 45 | 46 | CHECK(bool(v) == true); 47 | CHECK(v.which() == 0u); 48 | REQUIRE(v.target() != nullptr); 49 | CHECK(*v.target() == 42); 50 | 51 | #if EGGS_CXX98_HAS_RTTI 52 | CHECK(v.target_type() == typeid(int)); 53 | #endif 54 | 55 | #if EGGS_CXX14_HAS_CONSTEXPR 56 | // constexpr 57 | { 58 | struct test { static constexpr int call() 59 | { 60 | eggs::variant v; 61 | v = ConstexprTrivial(42); 62 | return 0; 63 | }}; 64 | constexpr int c = test::call(); 65 | } 66 | #endif 67 | } 68 | 69 | // same target 70 | { 71 | eggs::variant v(43); 72 | 73 | REQUIRE(bool(v) == true); 74 | REQUIRE(v.which() == 0u); 75 | REQUIRE(*v.target() == 43); 76 | 77 | v = 42; 78 | 79 | CHECK(bool(v) == true); 80 | CHECK(v.which() == 0u); 81 | REQUIRE(v.target() != nullptr); 82 | CHECK(*v.target() == 42); 83 | 84 | #if EGGS_CXX98_HAS_RTTI 85 | CHECK(v.target_type() == typeid(int)); 86 | #endif 87 | 88 | // dtor 89 | { 90 | eggs::variant v(eggs::variants::in_place); 91 | 92 | REQUIRE(v.which() == 1u); 93 | REQUIRE(Dtor::calls == 0u); 94 | 95 | v = Dtor(); 96 | 97 | CHECK(v.which() == 1u); 98 | CHECK(Dtor::calls == 1u); 99 | } 100 | Dtor::calls = 0u; 101 | 102 | #if EGGS_CXX14_HAS_CONSTEXPR 103 | // constexpr 104 | { 105 | struct test { static constexpr int call() 106 | { 107 | eggs::variant v(ConstexprTrivial(43)); 108 | v = ConstexprTrivial(42); 109 | return 0; 110 | }}; 111 | constexpr int c = test::call(); 112 | } 113 | #endif 114 | } 115 | 116 | // different target 117 | { 118 | eggs::variant v(std::string("")); 119 | 120 | REQUIRE(bool(v) == true); 121 | REQUIRE(v.which() == 1u); 122 | REQUIRE(*v.target() == ""); 123 | 124 | v = 42; 125 | 126 | CHECK(bool(v) == true); 127 | CHECK(v.which() == 0u); 128 | REQUIRE(v.target() != nullptr); 129 | CHECK(*v.target() == 42); 130 | 131 | #if EGGS_CXX98_HAS_RTTI 132 | CHECK(v.target_type() == typeid(int)); 133 | #endif 134 | 135 | // dtor 136 | { 137 | eggs::variant v(eggs::variants::in_place); 138 | 139 | REQUIRE(v.which() == 1u); 140 | REQUIRE(Dtor::calls == 0u); 141 | 142 | v = 42; 143 | 144 | CHECK(v.which() == 0u); 145 | CHECK(Dtor::calls == 1u); 146 | } 147 | Dtor::calls = 0u; 148 | 149 | #if EGGS_CXX98_HAS_EXCEPTIONS 150 | // exception-safety 151 | { 152 | eggs::variant v; 153 | v.emplace<0>(); 154 | 155 | REQUIRE(bool(v) == true); 156 | REQUIRE(v.which() == 0u); 157 | REQUIRE(Dtor::calls == 0u); 158 | 159 | CHECK_THROWS(v = Throw{}); 160 | 161 | CHECK(bool(v) == false); 162 | CHECK(v.which() == eggs::variant_npos); 163 | CHECK(Dtor::calls == 1u); 164 | } 165 | Dtor::calls = 0u; 166 | #endif 167 | 168 | #if EGGS_CXX14_HAS_CONSTEXPR 169 | // constexpr 170 | { 171 | struct test { static constexpr int call() 172 | { 173 | eggs::variant v(43); 174 | v = ConstexprTrivial(42); 175 | return 0; 176 | }}; 177 | constexpr int c = test::call(); 178 | } 179 | #endif 180 | } 181 | 182 | // implicit conversion 183 | { 184 | eggs::variant v; 185 | 186 | REQUIRE(bool(v) == false); 187 | REQUIRE(v.which() == eggs::variant_npos); 188 | 189 | v = "42"; 190 | 191 | CHECK(bool(v) == true); 192 | CHECK(v.which() == 1u); 193 | REQUIRE(v.target() != nullptr); 194 | CHECK(*v.target() == "42"); 195 | 196 | #if EGGS_CXX98_HAS_RTTI 197 | CHECK(v.target_type() == typeid(std::string)); 198 | #endif 199 | } 200 | 201 | // sfinae 202 | { 203 | CHECK( 204 | !std::is_assignable< 205 | eggs::variant&, std::string 206 | >::value); 207 | CHECK( 208 | !std::is_assignable< 209 | eggs::variant&, int 210 | >::value); 211 | CHECK( 212 | !std::is_assignable< 213 | eggs::variant&, int 214 | >::value); 215 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 216 | # if !defined(_MSC_FULL_VER) || _MSC_FULL_VER >= 191025206 217 | CHECK( 218 | !std::is_assignable< 219 | eggs::variant&, long 220 | >::value); 221 | # endif 222 | CHECK( 223 | !std::is_assignable< 224 | eggs::variant&, long 225 | >::value); 226 | #endif 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /test/assign.copy.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using eggs::variants::detail::move; 16 | 17 | #include "catch.hpp" 18 | #include "constexpr.hpp" 19 | #include "dtor.hpp" 20 | #include "throw.hpp" 21 | 22 | struct Maleficent 23 | { 24 | int x; 25 | 26 | Maleficent(int i) : x(i) {} 27 | template 28 | Maleficent(T&&) : x(-1) {} 29 | ~Maleficent() {} // not trivially copyable 30 | }; 31 | 32 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 33 | struct MovableOnly 34 | { 35 | MovableOnly() {}; 36 | MovableOnly(MovableOnly&&) {}; 37 | MovableOnly& operator=(MovableOnly&&) { return *this; } 38 | }; 39 | 40 | struct NonCopyAssignable 41 | { 42 | NonCopyAssignable() {} 43 | NonCopyAssignable(NonCopyAssignable const&) {}; // not trivially copyable 44 | NonCopyAssignable& operator=(NonCopyAssignable const&) = delete; 45 | }; 46 | 47 | struct NonCopyConstructible 48 | { 49 | NonCopyConstructible() {} 50 | NonCopyConstructible(NonCopyConstructible const&) = delete; 51 | NonCopyConstructible& operator=(NonCopyConstructible const&) { return *this; }; // not trivially copyable 52 | }; 53 | 54 | struct NonCopyAssignableTrivial 55 | { 56 | NonCopyAssignableTrivial() {} 57 | NonCopyAssignableTrivial(NonCopyAssignableTrivial const&) = default; 58 | NonCopyAssignableTrivial& operator=(NonCopyAssignableTrivial const&) = delete; 59 | }; 60 | 61 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 62 | namespace eggs { namespace variants { namespace detail 63 | { 64 | template <> struct is_trivially_copyable : std::true_type {}; 65 | template <> struct is_trivially_destructible : std::true_type {}; 66 | }}} 67 | # endif 68 | #endif 69 | 70 | TEST_CASE("variant::operator=(variant const&)", "[variant.assign]") 71 | { 72 | // empty source 73 | { 74 | eggs::variant const v1; 75 | 76 | REQUIRE(bool(v1) == false); 77 | REQUIRE(v1.which() == eggs::variant_npos); 78 | 79 | eggs::variant v2(42); 80 | 81 | REQUIRE(bool(v2) == true); 82 | REQUIRE(v2.which() == 0u); 83 | REQUIRE(*v2.target() == 42); 84 | 85 | v2 = v1; 86 | 87 | CHECK(bool(v2) == false); 88 | CHECK(v2.which() == v1.which()); 89 | 90 | // dtor 91 | { 92 | eggs::variant const v1; 93 | eggs::variant v2(eggs::variants::in_place); 94 | 95 | REQUIRE(v1.which() == eggs::variant_npos); 96 | REQUIRE(v2.which() == 1u); 97 | REQUIRE(Dtor::calls == 0u); 98 | 99 | v2 = v1; 100 | 101 | CHECK(v2.which() == eggs::variant_npos); 102 | CHECK(Dtor::calls == 1u); 103 | } 104 | Dtor::calls = 0u; 105 | 106 | #if EGGS_CXX14_HAS_CONSTEXPR 107 | // constexpr 108 | { 109 | struct test { static constexpr int call() 110 | { 111 | eggs::variant const v1; 112 | eggs::variant v2(ConstexprTrivial(42)); 113 | v2 = v1; 114 | return 0; 115 | }}; 116 | constexpr int c = test::call(); 117 | } 118 | #endif 119 | } 120 | 121 | // empty target 122 | { 123 | eggs::variant const v1(42); 124 | 125 | REQUIRE(bool(v1) == true); 126 | REQUIRE(v1.which() == 0u); 127 | REQUIRE(*v1.target() == 42); 128 | 129 | eggs::variant v2; 130 | 131 | REQUIRE(bool(v2) == false); 132 | REQUIRE(v2.which() == eggs::variant_npos); 133 | 134 | v2 = v1; 135 | 136 | CHECK(bool(v2) == true); 137 | CHECK(v2.which() == v1.which()); 138 | REQUIRE(v1.target() != nullptr); 139 | CHECK(*v1.target() == 42); 140 | REQUIRE(v2.target() != nullptr); 141 | CHECK(*v2.target() == 42); 142 | 143 | #if EGGS_CXX14_HAS_CONSTEXPR 144 | // constexpr 145 | { 146 | struct test { static constexpr int call() 147 | { 148 | eggs::variant const v1(ConstexprTrivial(42)); 149 | eggs::variant v2; 150 | v2 = v1; 151 | return 0; 152 | }}; 153 | constexpr int c = test::call(); 154 | } 155 | #endif 156 | } 157 | 158 | // same target 159 | { 160 | eggs::variant const v1(42); 161 | 162 | REQUIRE(bool(v1) == true); 163 | REQUIRE(v1.which() == 0u); 164 | REQUIRE(*v1.target() == 42); 165 | 166 | eggs::variant v2(43); 167 | 168 | REQUIRE(bool(v2) == true); 169 | REQUIRE(v2.which() == v1.which()); 170 | REQUIRE(*v2.target() == 43); 171 | 172 | v2 = v1; 173 | 174 | CHECK(bool(v2) == true); 175 | CHECK(v2.which() == v1.which()); 176 | REQUIRE(v1.target() != nullptr); 177 | CHECK(*v1.target() == 42); 178 | REQUIRE(v2.target() != nullptr); 179 | CHECK(*v2.target() == 42); 180 | 181 | // dtor 182 | { 183 | eggs::variant const v1(eggs::variants::in_place); 184 | eggs::variant v2(eggs::variants::in_place); 185 | 186 | REQUIRE(v1.which() == 1u); 187 | REQUIRE(v2.which() == 1u); 188 | REQUIRE(Dtor::calls == 0u); 189 | 190 | v2 = v1; 191 | 192 | CHECK(v2.which() == 1u); 193 | CHECK(Dtor::calls == 0u); 194 | } 195 | Dtor::calls = 0u; 196 | 197 | #if EGGS_CXX14_HAS_CONSTEXPR 198 | // constexpr 199 | { 200 | struct test { static constexpr int call() 201 | { 202 | eggs::variant const v1(ConstexprTrivial(42)); 203 | eggs::variant v2(ConstexprTrivial(43)); 204 | v2 = v1; 205 | return 0; 206 | }}; 207 | constexpr int c = test::call(); 208 | } 209 | #endif 210 | } 211 | 212 | // different target 213 | { 214 | eggs::variant const v1(42); 215 | 216 | REQUIRE(bool(v1) == true); 217 | REQUIRE(v1.which() == 0u); 218 | REQUIRE(*v1.target() == 42); 219 | 220 | eggs::variant v2(std::string("")); 221 | 222 | REQUIRE(bool(v2) == true); 223 | REQUIRE(v2.which() == 1u); 224 | REQUIRE(*v2.target() == ""); 225 | 226 | v2 = v1; 227 | 228 | CHECK(bool(v2) == true); 229 | CHECK(v2.which() == v1.which()); 230 | REQUIRE(v1.target() != nullptr); 231 | CHECK(*v1.target() == 42); 232 | REQUIRE(v2.target() != nullptr); 233 | CHECK(*v2.target() == 42); 234 | 235 | // dtor 236 | { 237 | eggs::variant const v1(42); 238 | eggs::variant v2(eggs::variants::in_place); 239 | 240 | REQUIRE(v1.which() == 0u); 241 | REQUIRE(v2.which() == 1u); 242 | REQUIRE(Dtor::calls == 0u); 243 | 244 | v2 = v1; 245 | 246 | CHECK(v2.which() == 0u); 247 | CHECK(Dtor::calls == 1u); 248 | } 249 | Dtor::calls = 0u; 250 | 251 | #if EGGS_CXX98_HAS_EXCEPTIONS 252 | // exception-safety 253 | { 254 | eggs::variant const v1(eggs::variants::in_place); 255 | 256 | REQUIRE(bool(v1) == true); 257 | REQUIRE(v1.which() == 1u); 258 | 259 | eggs::variant v2; 260 | v2.emplace<0>(); 261 | 262 | REQUIRE(bool(v2) == true); 263 | REQUIRE(v2.which() == 0u); 264 | REQUIRE(Dtor::calls == 0u); 265 | 266 | CHECK_THROWS(v2 = v1); 267 | 268 | CHECK(bool(v1) == true); 269 | CHECK(bool(v2) == false); 270 | CHECK(v1.which() == 1u); 271 | CHECK(v2.which() == eggs::variant_npos); 272 | CHECK(Dtor::calls == 1u); 273 | } 274 | Dtor::calls = 0u; 275 | #endif 276 | 277 | #if EGGS_CXX14_HAS_CONSTEXPR 278 | // constexpr 279 | { 280 | struct test { static constexpr int call() 281 | { 282 | eggs::variant const v1(ConstexprTrivial(42)); 283 | eggs::variant v2(43); 284 | v2 = v1; 285 | return 0; 286 | }}; 287 | constexpr int c = test::call(); 288 | } 289 | #endif 290 | } 291 | 292 | // trivially_copyable 293 | { 294 | eggs::variant const v1(42); 295 | 296 | #if EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 297 | CHECK(std::is_trivially_copyable::value == true); 298 | #endif 299 | 300 | REQUIRE(bool(v1) == true); 301 | REQUIRE(v1.which() == 0u); 302 | REQUIRE(*v1.target() == 42); 303 | 304 | eggs::variant v2(42.f); 305 | 306 | REQUIRE(bool(v2) == true); 307 | REQUIRE(v2.which() == 1u); 308 | REQUIRE(*v2.target() == 42.f); 309 | 310 | v2 = v1; 311 | 312 | CHECK(bool(v2) == true); 313 | CHECK(v2.which() == v1.which()); 314 | REQUIRE(v1.target() != nullptr); 315 | CHECK(*v1.target() == 42); 316 | REQUIRE(v2.target() != nullptr); 317 | CHECK(*v2.target() == 42); 318 | } 319 | 320 | // sfinae 321 | { 322 | eggs::variant v1(42); 323 | 324 | REQUIRE(bool(v1) == true); 325 | REQUIRE(v1.which() == 0u); 326 | REQUIRE(v1.target()->x == 42); 327 | 328 | eggs::variant v2; 329 | 330 | REQUIRE(bool(v2) == false); 331 | REQUIRE(v2.which() == eggs::variant_npos); 332 | 333 | v2 = v1; 334 | 335 | CHECK(bool(v2) == true); 336 | CHECK(v2.which() == v1.which()); 337 | REQUIRE(v1.target() != nullptr); 338 | CHECK(v1.target()->x == 42); 339 | REQUIRE(v2.target() != nullptr); 340 | CHECK(v2.target()->x == 42); 341 | 342 | eggs::variant const& vc1 = v1; 343 | eggs::variant v3; 344 | 345 | REQUIRE(bool(v3) == false); 346 | REQUIRE(v3.which() == eggs::variant_npos); 347 | 348 | v3 = ::move(vc1); 349 | 350 | CHECK(bool(v3) == true); 351 | CHECK(v3.which() == v1.which()); 352 | REQUIRE(v1.target() != nullptr); 353 | CHECK(v1.target()->x == 42); 354 | REQUIRE(v3.target() != nullptr); 355 | CHECK(v3.target()->x == 42); 356 | 357 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 358 | CHECK( 359 | !std::is_copy_assignable< 360 | eggs::variant 361 | >::value); 362 | CHECK( 363 | !std::is_copy_assignable< 364 | eggs::variant 365 | >::value); 366 | CHECK( 367 | !std::is_copy_assignable< 368 | eggs::variant 369 | >::value); 370 | CHECK( 371 | !std::is_copy_assignable< 372 | eggs::variant 373 | >::value); 374 | #endif 375 | } 376 | } 377 | 378 | TEST_CASE("variant<>::operator=(variant<> const&)", "[variant.assign]") 379 | { 380 | eggs::variant<> const v1; 381 | 382 | REQUIRE(bool(v1) == false); 383 | REQUIRE(v1.which() == eggs::variant_npos); 384 | 385 | eggs::variant<> v2; 386 | 387 | REQUIRE(bool(v2) == false); 388 | REQUIRE(v2.which() == eggs::variant_npos); 389 | 390 | v2 = v1; 391 | 392 | CHECK(bool(v2) == false); 393 | CHECK(v2.which() == v1.which()); 394 | 395 | #if EGGS_CXX14_HAS_CONSTEXPR 396 | // constexpr 397 | { 398 | struct test { static constexpr int call() 399 | { 400 | eggs::variant<> const v1; 401 | eggs::variant<> v2; 402 | v2 = v1; 403 | return 0; 404 | }}; 405 | constexpr int c = test::call(); 406 | } 407 | #endif 408 | } 409 | -------------------------------------------------------------------------------- /test/assign.move.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using eggs::variants::detail::move; 16 | 17 | #include "catch.hpp" 18 | #include "constexpr.hpp" 19 | #include "dtor.hpp" 20 | #include "throw.hpp" 21 | 22 | struct MovableOnly 23 | { 24 | std::string x; 25 | 26 | MovableOnly() : x() {} 27 | MovableOnly(std::string const& s) : x(s) {} 28 | MovableOnly(MovableOnly&& rhs) : x(::move(rhs.x)) {}; 29 | MovableOnly& operator=(MovableOnly&& rhs) { x = ::move(rhs.x); return *this; }; 30 | }; 31 | 32 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 33 | template 34 | struct NoThrowMoveAssignable 35 | { 36 | NoThrowMoveAssignable() {} 37 | NoThrowMoveAssignable(NoThrowMoveAssignable&&) noexcept {} 38 | NoThrowMoveAssignable& operator=(NoThrowMoveAssignable&&) noexcept(NoThrow) { return *this; }; 39 | }; 40 | 41 | template 42 | struct NoThrowMoveConstructible 43 | { 44 | NoThrowMoveConstructible() {} 45 | NoThrowMoveConstructible(NoThrowMoveConstructible&&) noexcept(NoThrow) {} 46 | NoThrowMoveConstructible& operator=(NoThrowMoveConstructible&&) noexcept { return *this; }; 47 | }; 48 | #endif 49 | 50 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 51 | struct NonCopyAssignable 52 | { 53 | NonCopyAssignable() {} 54 | NonCopyAssignable(NonCopyAssignable const&) {}; // not trivially copyable 55 | NonCopyAssignable& operator=(NonCopyAssignable const&) = delete; 56 | }; 57 | 58 | struct NonCopyConstructible 59 | { 60 | NonCopyConstructible() {} 61 | NonCopyConstructible(NonCopyConstructible const&) = delete; 62 | NonCopyConstructible& operator=(NonCopyConstructible const&) { return *this; }; // not trivially copyable 63 | }; 64 | 65 | struct NonCopyAssignableTrivial 66 | { 67 | NonCopyAssignableTrivial() {} 68 | NonCopyAssignableTrivial(NonCopyAssignableTrivial const&) = default; 69 | NonCopyAssignableTrivial& operator=(NonCopyAssignableTrivial const&) = delete; 70 | }; 71 | 72 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 73 | namespace eggs { namespace variants { namespace detail 74 | { 75 | template <> struct is_trivially_copyable : std::true_type {}; 76 | template <> struct is_trivially_destructible : std::true_type {}; 77 | }}} 78 | # endif 79 | #endif 80 | 81 | TEST_CASE("variant::operator=(variant&&)", "[variant.assign]") 82 | { 83 | // empty source 84 | { 85 | eggs::variant v1; 86 | 87 | REQUIRE(bool(v1) == false); 88 | REQUIRE(v1.which() == eggs::variant_npos); 89 | 90 | eggs::variant v2(42); 91 | 92 | REQUIRE(bool(v2) == true); 93 | REQUIRE(v2.which() == 0u); 94 | REQUIRE(*v2.target() == 42); 95 | 96 | v2 = ::move(v1); 97 | 98 | CHECK(bool(v1) == false); 99 | CHECK(bool(v2) == false); 100 | CHECK(v2.which() == v1.which()); 101 | 102 | // dtor 103 | { 104 | eggs::variant v1; 105 | eggs::variant v2(eggs::variants::in_place); 106 | 107 | REQUIRE(v1.which() == eggs::variant_npos); 108 | REQUIRE(v2.which() == 1u); 109 | REQUIRE(Dtor::calls == 0u); 110 | 111 | v2 = ::move(v1); 112 | 113 | CHECK(v2.which() == eggs::variant_npos); 114 | CHECK(Dtor::calls == 1u); 115 | } 116 | Dtor::calls = 0u; 117 | 118 | #if EGGS_CXX14_HAS_CONSTEXPR 119 | // constexpr 120 | { 121 | struct test { static constexpr int call() 122 | { 123 | eggs::variant v1; 124 | eggs::variant v2(ConstexprTrivial(42)); 125 | v2 = ::move(v1); 126 | return 0; 127 | }}; 128 | constexpr int c = test::call(); 129 | } 130 | #endif 131 | } 132 | 133 | // empty target 134 | { 135 | eggs::variant v1(42); 136 | 137 | REQUIRE(bool(v1) == true); 138 | REQUIRE(v1.which() == 0u); 139 | REQUIRE(*v1.target() == 42); 140 | 141 | eggs::variant v2; 142 | 143 | REQUIRE(bool(v2) == false); 144 | REQUIRE(v2.which() == eggs::variant_npos); 145 | 146 | v2 = ::move(v1); 147 | 148 | CHECK(bool(v1) == true); 149 | CHECK(bool(v2) == true); 150 | CHECK(v2.which() == v1.which()); 151 | REQUIRE(v2.target() != nullptr); 152 | CHECK(*v2.target() == 42); 153 | 154 | #if EGGS_CXX14_HAS_CONSTEXPR 155 | // constexpr 156 | { 157 | struct test { static constexpr int call() 158 | { 159 | eggs::variant v1(ConstexprTrivial(42)); 160 | eggs::variant v2; 161 | v2 = ::move(v1); 162 | return 0; 163 | }}; 164 | constexpr int c = test::call(); 165 | } 166 | #endif 167 | } 168 | 169 | // same target 170 | { 171 | eggs::variant v1(42); 172 | 173 | REQUIRE(bool(v1) == true); 174 | REQUIRE(v1.which() == 0u); 175 | REQUIRE(*v1.target() == 42); 176 | 177 | eggs::variant v2(43); 178 | 179 | REQUIRE(bool(v2) == true); 180 | REQUIRE(v2.which() == v1.which()); 181 | REQUIRE(*v2.target() == 43); 182 | 183 | v2 = ::move(v1); 184 | 185 | CHECK(bool(v1) == true); 186 | CHECK(bool(v2) == true); 187 | CHECK(v2.which() == v1.which()); 188 | REQUIRE(v2.target() != nullptr); 189 | CHECK(*v2.target() == 42); 190 | 191 | // dtor 192 | { 193 | eggs::variant v1(eggs::variants::in_place); 194 | eggs::variant v2(eggs::variants::in_place); 195 | 196 | REQUIRE(v1.which() == 1u); 197 | REQUIRE(v2.which() == 1u); 198 | REQUIRE(Dtor::calls == 0u); 199 | 200 | v2 = ::move(v1); 201 | 202 | CHECK(v2.which() == 1u); 203 | CHECK(Dtor::calls == 0u); 204 | } 205 | Dtor::calls = 0u; 206 | 207 | #if EGGS_CXX14_HAS_CONSTEXPR 208 | // constexpr 209 | { 210 | struct test { static constexpr int call() 211 | { 212 | eggs::variant v1(ConstexprTrivial(42)); 213 | eggs::variant v2(ConstexprTrivial(43)); 214 | v2 = ::move(v1); 215 | return 0; 216 | }}; 217 | constexpr int c = test::call(); 218 | } 219 | #endif 220 | } 221 | 222 | // different target 223 | { 224 | eggs::variant v1(42); 225 | 226 | REQUIRE(bool(v1) == true); 227 | REQUIRE(v1.which() == 0u); 228 | REQUIRE(*v1.target() == 42); 229 | 230 | eggs::variant v2(MovableOnly("")); 231 | 232 | REQUIRE(bool(v2) == true); 233 | REQUIRE(v2.which() == 1u); 234 | REQUIRE(v2.target()->x == ""); 235 | 236 | v2 = ::move(v1); 237 | 238 | CHECK(bool(v1) == true); 239 | CHECK(bool(v2) == true); 240 | CHECK(v2.which() == v1.which()); 241 | REQUIRE(v2.target() != nullptr); 242 | CHECK(*v2.target() == 42); 243 | 244 | // dtor 245 | { 246 | eggs::variant v1(42); 247 | eggs::variant v2(eggs::variants::in_place); 248 | 249 | REQUIRE(v1.which() == 0u); 250 | REQUIRE(v2.which() == 1u); 251 | REQUIRE(Dtor::calls == 0u); 252 | 253 | v2 = ::move(v1); 254 | 255 | CHECK(v2.which() == 0u); 256 | CHECK(Dtor::calls == 1u); 257 | } 258 | Dtor::calls = 0u; 259 | 260 | #if EGGS_CXX98_HAS_EXCEPTIONS 261 | // exception-safety 262 | { 263 | eggs::variant v1; 264 | v1.emplace<1>(); 265 | 266 | REQUIRE(bool(v1) == true); 267 | REQUIRE(v1.which() == 1u); 268 | 269 | eggs::variant v2; 270 | v2.emplace<0>(); 271 | 272 | REQUIRE(bool(v2) == true); 273 | REQUIRE(v2.which() == 0u); 274 | REQUIRE(Dtor::calls == 0u); 275 | 276 | CHECK_THROWS(v2 = ::move(v1)); 277 | 278 | CHECK(bool(v1) == true); 279 | CHECK(bool(v2) == false); 280 | CHECK(v1.which() == 1u); 281 | CHECK(v2.which() == eggs::variant_npos); 282 | CHECK(Dtor::calls == 1u); 283 | } 284 | Dtor::calls = 0u; 285 | #endif 286 | 287 | #if EGGS_CXX14_HAS_CONSTEXPR 288 | // constexpr 289 | { 290 | struct test { static constexpr int call() 291 | { 292 | eggs::variant v1(ConstexprTrivial(42)); 293 | eggs::variant v2(43); 294 | v2 = ::move(v1); 295 | return 0; 296 | }}; 297 | constexpr int c = test::call(); 298 | } 299 | #endif 300 | } 301 | 302 | // list-initialization 303 | { 304 | eggs::variant v; 305 | 306 | REQUIRE(bool(v) == false); 307 | REQUIRE(v.which() == eggs::variant_npos); 308 | 309 | v = {}; 310 | 311 | CHECK(bool(v) == false); 312 | CHECK(v.which() == eggs::variant_npos); 313 | CHECK(v.target() == nullptr); 314 | 315 | #if EGGS_CXX98_HAS_RTTI 316 | CHECK(v.target_type() == typeid(void)); 317 | #endif 318 | } 319 | 320 | // trivially_copyable 321 | { 322 | eggs::variant v1(42); 323 | 324 | #if EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 325 | CHECK(std::is_trivially_copyable::value == true); 326 | #endif 327 | 328 | REQUIRE(bool(v1) == true); 329 | REQUIRE(v1.which() == 0u); 330 | REQUIRE(*v1.target() == 42); 331 | 332 | eggs::variant v2(42.f); 333 | 334 | REQUIRE(bool(v2) == true); 335 | REQUIRE(v2.which() == 1u); 336 | REQUIRE(*v2.target() == 42.f); 337 | 338 | v2 = ::move(v1); 339 | 340 | CHECK(bool(v1) == true); 341 | CHECK(bool(v2) == true); 342 | CHECK(v2.which() == v1.which()); 343 | REQUIRE(v1.target() != nullptr); 344 | CHECK(*v1.target() == 42); 345 | REQUIRE(v2.target() != nullptr); 346 | CHECK(*v2.target() == 42); 347 | } 348 | 349 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 350 | // noexcept 351 | { 352 | REQUIRE( 353 | std::is_move_assignable< 354 | eggs::variant> 355 | >::value); 356 | CHECK( 357 | std::is_nothrow_move_assignable< 358 | eggs::variant> 359 | >::value); 360 | 361 | REQUIRE( 362 | std::is_move_assignable< 363 | eggs::variant> 364 | >::value); 365 | CHECK( 366 | !std::is_nothrow_move_assignable< 367 | eggs::variant> 368 | >::value); 369 | 370 | REQUIRE( 371 | std::is_move_assignable< 372 | eggs::variant> 373 | >::value); 374 | CHECK( 375 | std::is_nothrow_move_assignable< 376 | eggs::variant> 377 | >::value); 378 | 379 | REQUIRE( 380 | std::is_move_assignable< 381 | eggs::variant> 382 | >::value); 383 | CHECK( 384 | !std::is_nothrow_move_assignable< 385 | eggs::variant> 386 | >::value); 387 | } 388 | #endif 389 | 390 | // sfinae 391 | { 392 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 393 | CHECK( 394 | !std::is_move_assignable< 395 | eggs::variant 396 | >::value); 397 | CHECK( 398 | !std::is_move_assignable< 399 | eggs::variant 400 | >::value); 401 | CHECK( 402 | !std::is_move_assignable< 403 | eggs::variant 404 | >::value); 405 | #endif 406 | } 407 | } 408 | 409 | TEST_CASE("variant<>::operator=(variant<>&&)", "[variant.assign]") 410 | { 411 | eggs::variant<> v1; 412 | 413 | REQUIRE(bool(v1) == false); 414 | REQUIRE(v1.which() == eggs::variant_npos); 415 | 416 | eggs::variant<> v2; 417 | 418 | REQUIRE(bool(v2) == false); 419 | REQUIRE(v2.which() == eggs::variant_npos); 420 | 421 | v2 = ::move(v1); 422 | 423 | CHECK(bool(v1) == false); 424 | CHECK(bool(v2) == false); 425 | CHECK(v2.which() == v1.which()); 426 | 427 | CHECK(noexcept(v2 = ::move(v1)) == true); 428 | 429 | // list-initialization 430 | { 431 | eggs::variant<> v; 432 | 433 | REQUIRE(bool(v) == false); 434 | REQUIRE(v.which() == eggs::variant_npos); 435 | 436 | v = {}; 437 | 438 | CHECK(bool(v) == false); 439 | CHECK(v.which() == eggs::variant_npos); 440 | CHECK(v.target() == nullptr); 441 | 442 | #if EGGS_CXX98_HAS_RTTI 443 | CHECK(v.target_type() == typeid(void)); 444 | #endif 445 | } 446 | 447 | #if EGGS_CXX14_HAS_CONSTEXPR 448 | // constexpr 449 | { 450 | struct test { static constexpr int call() 451 | { 452 | eggs::variant<> v1; 453 | eggs::variant<> v2; 454 | v2 = ::move(v1); 455 | return 0; 456 | }}; 457 | constexpr int c = test::call(); 458 | } 459 | #endif 460 | } 461 | -------------------------------------------------------------------------------- /test/catch.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #define CATCH_CONFIG_MAIN 9 | #include "catch.hpp" 10 | -------------------------------------------------------------------------------- /test/cnstr.conversion.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "catch.hpp" 16 | #include "constexpr.hpp" 17 | 18 | template 19 | struct Explicit 20 | { 21 | T x; 22 | 23 | template < 24 | typename U 25 | , typename Enable = typename std::enable_if< 26 | std::is_constructible::value 27 | >::type 28 | > 29 | explicit Explicit(U&& x) : x(std::forward(x)) {} 30 | }; 31 | 32 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 33 | struct AnyConstructible 34 | { 35 | template 36 | AnyConstructible(T&&){} 37 | }; 38 | 39 | struct NoneConstructible 40 | { 41 | NoneConstructible() = delete; 42 | }; 43 | 44 | struct WeirdConstructor 45 | { 46 | WeirdConstructor(int) {} 47 | explicit WeirdConstructor(long) = delete; 48 | }; 49 | #endif 50 | 51 | TEST_CASE("variant::variant(T&&)", "[variant.cnstr]") 52 | { 53 | eggs::variant v(42); 54 | 55 | CHECK(bool(v) == true); 56 | CHECK(v.which() == 0u); 57 | REQUIRE(v.target() != nullptr); 58 | CHECK(*v.target() == 42); 59 | 60 | #if EGGS_CXX98_HAS_RTTI 61 | CHECK(v.target_type() == typeid(int)); 62 | #endif 63 | 64 | #if EGGS_CXX11_HAS_CONSTEXPR 65 | // constexpr 66 | { 67 | constexpr eggs::variant v(Constexpr(42)); 68 | 69 | # if EGGS_CXX14_HAS_CONSTEXPR 70 | struct test { static constexpr int call() 71 | { 72 | eggs::variant v(Constexpr(42)); 73 | v.target()->x = 43; 74 | return 0; 75 | }}; 76 | constexpr int c = test::call(); 77 | # endif 78 | } 79 | #endif 80 | 81 | // conversion 82 | { 83 | eggs::variant v("42"); 84 | 85 | CHECK(bool(v) == true); 86 | CHECK(v.which() == 1u); 87 | REQUIRE(v.target() != nullptr); 88 | CHECK(*v.target() == "42"); 89 | 90 | #if EGGS_CXX98_HAS_RTTI 91 | CHECK(v.target_type() == typeid(std::string)); 92 | #endif 93 | 94 | // implicit conversion 95 | { 96 | eggs::variant v = "42"; 97 | 98 | CHECK(bool(v) == true); 99 | CHECK(v.which() == 1u); 100 | REQUIRE(v.target() != nullptr); 101 | CHECK(*v.target() == "42"); 102 | 103 | #if EGGS_CXX98_HAS_RTTI 104 | CHECK(v.target_type() == typeid(std::string)); 105 | #endif 106 | } 107 | 108 | // explicit conversion 109 | { 110 | eggs::variant> v("42"); 111 | 112 | CHECK(bool(v) == true); 113 | CHECK(v.which() == 1u); 114 | REQUIRE(v.target>() != nullptr); 115 | CHECK(v.target>()->x == "42"); 116 | 117 | #if EGGS_CXX98_HAS_RTTI 118 | CHECK(v.target_type() == typeid(Explicit)); 119 | #endif 120 | } 121 | } 122 | 123 | // sfinae 124 | { 125 | CHECK( 126 | !std::is_constructible< 127 | eggs::variant, std::string 128 | >::value); 129 | CHECK( 130 | !std::is_constructible< 131 | eggs::variant, int 132 | >::value); 133 | CHECK( 134 | !std::is_constructible< 135 | eggs::variant, int 136 | >::value); 137 | CHECK( 138 | !std::is_constructible< 139 | eggs::variant, Explicit>, int 140 | >::value); 141 | CHECK( 142 | !std::is_constructible< 143 | eggs::variant, Explicit>, int 144 | >::value); 145 | CHECK( 146 | !std::is_constructible< 147 | eggs::variant>, int 148 | >::value); 149 | CHECK( 150 | !std::is_constructible< 151 | eggs::variant>, long 152 | >::value); 153 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 154 | CHECK( 155 | !std::is_constructible< 156 | eggs::variant, 157 | eggs::variants::in_place_index_t<0> 158 | >::value); 159 | CHECK( 160 | !std::is_constructible< 161 | eggs::variant, 162 | eggs::variants::in_place_type_t 163 | >::value); 164 | CHECK( 165 | !std::is_constructible< 166 | eggs::variant>, 167 | eggs::variants::in_place_index_t<0> 168 | >::value); 169 | CHECK( 170 | !std::is_constructible< 171 | eggs::variant>, 172 | eggs::variants::in_place_type_t 173 | >::value); 174 | CHECK( 175 | !std::is_constructible< 176 | eggs::variant, long 177 | >::value); 178 | #endif 179 | 180 | CHECK( 181 | !std::is_convertible< 182 | int, eggs::variant> 183 | >::value); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /test/cnstr.copy.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using eggs::variants::detail::move; 16 | 17 | #include "catch.hpp" 18 | #include "constexpr.hpp" 19 | 20 | struct Maleficent 21 | { 22 | int x; 23 | 24 | Maleficent(int i) : x(i) {} 25 | template 26 | Maleficent(T&&) : x(-1) {} 27 | ~Maleficent() {} // not trivially copyable 28 | }; 29 | 30 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 31 | struct MovableOnly 32 | { 33 | MovableOnly() {}; 34 | MovableOnly(MovableOnly&&) {}; 35 | MovableOnly& operator=(MovableOnly&&) { return *this; } 36 | }; 37 | 38 | struct NonCopyConstructible 39 | { 40 | NonCopyConstructible() {} 41 | NonCopyConstructible(NonCopyConstructible const&) = delete; 42 | NonCopyConstructible& operator=(NonCopyConstructible const&) { return *this; }; // not trivially copyable 43 | }; 44 | 45 | struct NonCopyConstructibleTrivial 46 | { 47 | NonCopyConstructibleTrivial() {} 48 | NonCopyConstructibleTrivial(NonCopyConstructibleTrivial const&) = delete; 49 | NonCopyConstructibleTrivial& operator=(NonCopyConstructibleTrivial const&) = default; 50 | }; 51 | 52 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 53 | namespace eggs { namespace variants { namespace detail 54 | { 55 | template <> struct is_trivially_copyable : std::true_type {}; 56 | template <> struct is_trivially_destructible : std::true_type {}; 57 | }}} 58 | # endif 59 | #endif 60 | 61 | TEST_CASE("variant::variant(variant const&)", "[variant.cnstr]") 62 | { 63 | eggs::variant const v1(42); 64 | 65 | REQUIRE(bool(v1) == true); 66 | REQUIRE(v1.which() == 0u); 67 | REQUIRE(*v1.target() == 42); 68 | 69 | eggs::variant v2(v1); 70 | 71 | CHECK(bool(v2) == true); 72 | CHECK(v2.which() == v1.which()); 73 | REQUIRE(v1.target() != nullptr); 74 | CHECK(*v1.target() == 42); 75 | REQUIRE(v2.target() != nullptr); 76 | CHECK(*v2.target() == 42); 77 | 78 | // trivially_copyable 79 | { 80 | eggs::variant const v1(42); 81 | 82 | REQUIRE(bool(v1) == true); 83 | REQUIRE(v1.which() == 0u); 84 | REQUIRE(*v1.target() == 42); 85 | 86 | #if EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 87 | CHECK(std::is_trivially_copyable::value == true); 88 | #endif 89 | 90 | eggs::variant v2(v1); 91 | 92 | CHECK(bool(v2) == true); 93 | CHECK(v2.which() == v1.which()); 94 | REQUIRE(v1.target() != nullptr); 95 | CHECK(*v1.target() == 42); 96 | REQUIRE(v2.target() != nullptr); 97 | CHECK(*v2.target() == 42); 98 | } 99 | 100 | #if EGGS_CXX11_HAS_CONSTEXPR 101 | // constexpr 102 | { 103 | constexpr eggs::variant v1(ConstexprTrivial(42)); 104 | constexpr eggs::variant v2(v1); 105 | } 106 | #endif 107 | 108 | // sfinae 109 | { 110 | eggs::variant v1(42); 111 | 112 | REQUIRE(bool(v1) == true); 113 | REQUIRE(v1.which() == 0u); 114 | REQUIRE(v1.target()->x == 42); 115 | 116 | eggs::variant v2(v1); 117 | 118 | CHECK(bool(v2) == true); 119 | CHECK(v2.which() == v1.which()); 120 | REQUIRE(v1.target() != nullptr); 121 | CHECK(v1.target()->x == 42); 122 | REQUIRE(v2.target() != nullptr); 123 | CHECK(v2.target()->x == 42); 124 | 125 | eggs::variant const& vc1 = v1; 126 | eggs::variant v3(::move(vc1)); 127 | 128 | CHECK(bool(v3) == true); 129 | CHECK(v3.which() == v1.which()); 130 | REQUIRE(v1.target() != nullptr); 131 | CHECK(v1.target()->x == 42); 132 | REQUIRE(v3.target() != nullptr); 133 | CHECK(v3.target()->x == 42); 134 | 135 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 136 | CHECK( 137 | !std::is_copy_constructible< 138 | eggs::variant 139 | >::value); 140 | CHECK( 141 | !std::is_copy_constructible< 142 | eggs::variant 143 | >::value); 144 | CHECK( 145 | !std::is_copy_constructible< 146 | eggs::variant 147 | >::value); 148 | #endif 149 | } 150 | } 151 | 152 | TEST_CASE("variant<>::variant(variant<> const&)", "[variant.cnstr]") 153 | { 154 | eggs::variant<> const v1; 155 | 156 | REQUIRE(bool(v1) == false); 157 | REQUIRE(v1.which() == eggs::variant_npos); 158 | 159 | eggs::variant<> v2(v1); 160 | 161 | CHECK(bool(v2) == false); 162 | CHECK(v2.which() == v1.which()); 163 | 164 | #if EGGS_CXX11_HAS_CONSTEXPR 165 | // constexpr 166 | { 167 | constexpr eggs::variant<> v1; 168 | constexpr eggs::variant<> v2(v1); 169 | } 170 | #endif 171 | } 172 | -------------------------------------------------------------------------------- /test/cnstr.default.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "catch.hpp" 14 | #include "constexpr.hpp" 15 | 16 | TEST_CASE("variant::variant()", "[variant.cnstr]") 17 | { 18 | eggs::variant v; 19 | 20 | CHECK(bool(v) == false); 21 | CHECK(v.which() == eggs::variant_npos); 22 | CHECK(v.target() == nullptr); 23 | 24 | #if EGGS_CXX98_HAS_RTTI 25 | CHECK(v.target_type() == typeid(void)); 26 | #endif 27 | 28 | CHECK(noexcept(eggs::variant()) == true); 29 | 30 | #if EGGS_CXX11_HAS_CONSTEXPR 31 | // constexpr 32 | { 33 | constexpr eggs::variant v; 34 | } 35 | #endif 36 | } 37 | 38 | TEST_CASE("variant<>::variant()", "[variant.cnstr]") 39 | { 40 | eggs::variant<> v; 41 | 42 | CHECK(bool(v) == false); 43 | CHECK(v.which() == eggs::variant_npos); 44 | CHECK(v.target() == nullptr); 45 | 46 | #if EGGS_CXX98_HAS_RTTI 47 | CHECK(v.target_type() == typeid(void)); 48 | #endif 49 | 50 | CHECK(noexcept(eggs::variant<>()) == true); 51 | 52 | #if EGGS_CXX11_HAS_CONSTEXPR 53 | // constexpr 54 | { 55 | constexpr eggs::variant<> v; 56 | } 57 | #endif 58 | } 59 | -------------------------------------------------------------------------------- /test/cnstr.emplace.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "catch.hpp" 15 | #include "constexpr.hpp" 16 | 17 | TEST_CASE("variant::variant(in_place, Args&&...)", "[variant.cnstr]") 18 | { 19 | eggs::variant v(eggs::variants::in_place<0>, 42); 20 | 21 | CHECK(bool(v) == true); 22 | CHECK(v.which() == 0u); 23 | REQUIRE(v.target() != nullptr); 24 | CHECK(*v.target() == 42); 25 | 26 | #if EGGS_CXX98_HAS_RTTI 27 | CHECK(v.target_type() == typeid(int)); 28 | #endif 29 | 30 | #if EGGS_CXX11_HAS_CONSTEXPR 31 | // constexpr 32 | { 33 | constexpr eggs::variant v(eggs::variants::in_place<1>, 42); 34 | 35 | # if EGGS_CXX14_HAS_CONSTEXPR 36 | struct test { static constexpr int call() 37 | { 38 | eggs::variant v(eggs::variants::in_place<1>, 42); 39 | v.target()->x = 43; 40 | return 0; 41 | }}; 42 | constexpr int c = test::call(); 43 | # endif 44 | } 45 | #endif 46 | 47 | // sfinae 48 | { 49 | CHECK( 50 | !std::is_constructible< 51 | eggs::variant, 52 | eggs::variants::in_place_index_t<0>, std::string 53 | >::value); 54 | CHECK( 55 | !std::is_constructible< 56 | eggs::variant, 57 | eggs::variants::in_place_index_t<1> 58 | >::value); 59 | } 60 | } 61 | 62 | TEST_CASE("variant::variant(in_place, Args&&...)", "[variant.cnstr]") 63 | { 64 | eggs::variant v(eggs::variants::in_place<0>, 42); 65 | 66 | CHECK(bool(v) == true); 67 | CHECK(v.which() == 0u); 68 | REQUIRE(v.target() != nullptr); 69 | 70 | #if EGGS_CXX98_HAS_RTTI 71 | CHECK(v.target_type() == typeid(int)); 72 | #endif 73 | } 74 | 75 | TEST_CASE("variant::variant(in_place, std::initializer_list, Args&&...)", "[variant.cnstr]") 76 | { 77 | eggs::variant v(eggs::variants::in_place<1>, {'4', '2'}); 78 | 79 | CHECK(bool(v) == true); 80 | CHECK(v.which() == 1u); 81 | REQUIRE(v.target() != nullptr); 82 | CHECK(*v.target() == "42"); 83 | 84 | #if EGGS_CXX98_HAS_RTTI 85 | CHECK(v.target_type() == typeid(std::string)); 86 | #endif 87 | 88 | #if EGGS_CXX14_HAS_CONSTEXPR 89 | // constexpr 90 | { 91 | constexpr eggs::variant v(eggs::variants::in_place<1>, {4, 2}); 92 | 93 | # if EGGS_CXX14_HAS_CONSTEXPR 94 | struct test { static constexpr int call() 95 | { 96 | eggs::variant v(eggs::variants::in_place<1>, {4, 2}); 97 | v.target()->x = 5; 98 | return 0; 99 | }}; 100 | constexpr int c = test::call(); 101 | # endif 102 | } 103 | #endif 104 | 105 | // sfinae 106 | { 107 | CHECK( 108 | !std::is_constructible< 109 | eggs::variant, 110 | eggs::variants::in_place_index_t<0>, std::initializer_list 111 | >::value); 112 | CHECK( 113 | !std::is_constructible< 114 | eggs::variant, 115 | eggs::variants::in_place_index_t<1>, std::initializer_list 116 | >::value); 117 | } 118 | } 119 | 120 | TEST_CASE("variant::variant(in_place, std::initializer_list, Args&&...)", "[variant.cnstr]") 121 | { 122 | eggs::variant v(eggs::variants::in_place<1>, {'4', '2'}); 123 | 124 | CHECK(bool(v) == true); 125 | CHECK(v.which() == 1u); 126 | REQUIRE(v.target() != nullptr); 127 | 128 | #if EGGS_CXX98_HAS_RTTI 129 | CHECK(v.target_type() == typeid(std::string)); 130 | #endif 131 | } 132 | 133 | TEST_CASE("variant::variant(in_place, Args&&...)", "[variant.cnstr]") 134 | { 135 | eggs::variant v(eggs::variants::in_place, 42); 136 | 137 | CHECK(bool(v) == true); 138 | CHECK(v.which() == 0u); 139 | REQUIRE(v.target() != nullptr); 140 | CHECK(*v.target() == 42); 141 | 142 | #if EGGS_CXX98_HAS_RTTI 143 | CHECK(v.target_type() == typeid(int)); 144 | #endif 145 | 146 | #if EGGS_CXX11_HAS_CONSTEXPR 147 | // constexpr 148 | { 149 | constexpr eggs::variant v(eggs::variants::in_place, 42); 150 | 151 | # if EGGS_CXX14_HAS_CONSTEXPR 152 | struct test { static constexpr int call() 153 | { 154 | eggs::variant v(eggs::variants::in_place, 42); 155 | v.target()->x = 43; 156 | return 0; 157 | }}; 158 | constexpr int c = test::call(); 159 | # endif 160 | } 161 | #endif 162 | 163 | // sfinae 164 | { 165 | CHECK( 166 | !std::is_constructible< 167 | eggs::variant, 168 | eggs::variants::in_place_type_t, std::string 169 | >::value); 170 | CHECK( 171 | !std::is_constructible< 172 | eggs::variant, 173 | eggs::variants::in_place_type_t 174 | >::value); 175 | CHECK( 176 | !std::is_constructible< 177 | eggs::variant, 178 | eggs::variants::in_place_type_t 179 | >::value); 180 | } 181 | } 182 | 183 | TEST_CASE("variant::variant(in_place, std::initializer_list, Args&&...)", "[variant.cnstr]") 184 | { 185 | eggs::variant v(eggs::variants::in_place, {'4', '2'}); 186 | 187 | CHECK(bool(v) == true); 188 | CHECK(v.which() == 1u); 189 | REQUIRE(v.target() != nullptr); 190 | CHECK(*v.target() == "42"); 191 | 192 | #if EGGS_CXX98_HAS_RTTI 193 | CHECK(v.target_type() == typeid(std::string)); 194 | #endif 195 | 196 | #if EGGS_CXX14_HAS_CONSTEXPR 197 | // constexpr 198 | { 199 | constexpr eggs::variant v(eggs::variants::in_place, {4, 2}); 200 | 201 | # if EGGS_CXX14_HAS_CONSTEXPR 202 | struct test { static constexpr int call() 203 | { 204 | eggs::variant v(eggs::variants::in_place, {4, 2}); 205 | v.target()->x = 5; 206 | return 0; 207 | }}; 208 | constexpr int c = test::call(); 209 | # endif 210 | } 211 | #endif 212 | 213 | // sfinae 214 | { 215 | CHECK( 216 | !std::is_constructible< 217 | eggs::variant, 218 | eggs::variants::in_place_type_t, std::initializer_list 219 | >::value); 220 | CHECK( 221 | !std::is_constructible< 222 | eggs::variant, 223 | eggs::variants::in_place_type_t, std::initializer_list 224 | >::value); 225 | CHECK( 226 | !std::is_constructible< 227 | eggs::variant, 228 | eggs::variants::in_place_type_t, std::initializer_list 229 | >::value); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /test/cnstr.move.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | using eggs::variants::detail::move; 16 | 17 | #include "catch.hpp" 18 | #include "constexpr.hpp" 19 | 20 | struct MovableOnly 21 | { 22 | std::string x; 23 | 24 | MovableOnly() : x() {} 25 | MovableOnly(std::string const& s) : x(s) {} 26 | MovableOnly(MovableOnly&& rhs) : x(::move(rhs.x)) {}; 27 | MovableOnly& operator=(MovableOnly&& rhs) { x = ::move(rhs.x); return *this; }; 28 | }; 29 | 30 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 31 | template 32 | struct NoThrowMoveConstructible 33 | { 34 | NoThrowMoveConstructible() {} 35 | NoThrowMoveConstructible(NoThrowMoveConstructible&&) noexcept(NoThrow) {} 36 | }; 37 | #endif 38 | 39 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 40 | struct NonCopyConstructible 41 | { 42 | NonCopyConstructible() {} 43 | NonCopyConstructible(NonCopyConstructible const&) = delete; 44 | NonCopyConstructible& operator=(NonCopyConstructible const&) { return *this; }; // not trivially copyable 45 | }; 46 | 47 | struct NonCopyConstructibleTrivial 48 | { 49 | NonCopyConstructibleTrivial() {} 50 | NonCopyConstructibleTrivial(NonCopyConstructibleTrivial const&) = delete; 51 | NonCopyConstructibleTrivial& operator=(NonCopyConstructibleTrivial const&) = default; 52 | }; 53 | 54 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 55 | namespace eggs { namespace variants { namespace detail 56 | { 57 | template <> struct is_trivially_copyable : std::true_type {}; 58 | template <> struct is_trivially_destructible : std::true_type {}; 59 | }}} 60 | # endif 61 | #endif 62 | 63 | TEST_CASE("variant::variant(variant&&)", "[variant.cnstr]") 64 | { 65 | eggs::variant v1(42); 66 | 67 | REQUIRE(bool(v1) == true); 68 | REQUIRE(v1.which() == 0u); 69 | REQUIRE(*v1.target() == 42); 70 | 71 | eggs::variant v2(::move(v1)); 72 | 73 | CHECK(bool(v1) == true); 74 | CHECK(bool(v2) == true); 75 | CHECK(v2.which() == v1.which()); 76 | REQUIRE(v1.target() != nullptr); 77 | CHECK(*v1.target() == 42); 78 | 79 | // list-initialization 80 | { 81 | eggs::variant v = {}; 82 | 83 | CHECK(bool(v) == false); 84 | CHECK(v.which() == eggs::variant_npos); 85 | CHECK(v.target() == nullptr); 86 | 87 | #if EGGS_CXX98_HAS_RTTI 88 | CHECK(v.target_type() == typeid(void)); 89 | #endif 90 | } 91 | 92 | // trivially_copyable 93 | { 94 | eggs::variant v1(42); 95 | 96 | REQUIRE(bool(v1) == true); 97 | REQUIRE(v1.which() == 0u); 98 | REQUIRE(*v1.target() == 42); 99 | 100 | #if EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE 101 | CHECK(std::is_trivially_copyable::value == true); 102 | #endif 103 | 104 | eggs::variant v2(::move(v1)); 105 | 106 | CHECK(bool(v1) == true); 107 | CHECK(bool(v2) == true); 108 | CHECK(v2.which() == v1.which()); 109 | REQUIRE(v1.target() != nullptr); 110 | CHECK(*v1.target() == 42); 111 | REQUIRE(v2.target() != nullptr); 112 | CHECK(*v2.target() == 42); 113 | } 114 | 115 | #if EGGS_CXX14_HAS_CONSTEXPR 116 | // constexpr 117 | { 118 | struct test { static constexpr int call() 119 | { 120 | eggs::variant v1(ConstexprTrivial(42)); 121 | eggs::variant v2(::move(v1)); 122 | return 0; 123 | }}; 124 | constexpr int c = test::call(); 125 | } 126 | #endif 127 | 128 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 129 | // noexcept 130 | { 131 | REQUIRE( 132 | std::is_move_constructible< 133 | eggs::variant> 134 | >::value); 135 | CHECK( 136 | std::is_nothrow_move_constructible< 137 | eggs::variant> 138 | >::value); 139 | 140 | REQUIRE( 141 | std::is_move_constructible< 142 | eggs::variant> 143 | >::value); 144 | CHECK( 145 | !std::is_nothrow_move_constructible< 146 | eggs::variant> 147 | >::value); 148 | } 149 | #endif 150 | 151 | // sfinae 152 | { 153 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 154 | CHECK( 155 | !std::is_move_constructible< 156 | eggs::variant 157 | >::value); 158 | CHECK( 159 | !std::is_move_constructible< 160 | eggs::variant 161 | >::value); 162 | #endif 163 | } 164 | } 165 | 166 | TEST_CASE("variant<>::variant(variant<>&&)", "[variant.cnstr]") 167 | { 168 | eggs::variant<> v1; 169 | 170 | REQUIRE(bool(v1) == false); 171 | REQUIRE(v1.which() == eggs::variant_npos); 172 | 173 | eggs::variant<> v2(::move(v1)); 174 | 175 | CHECK(bool(v1) == false); 176 | CHECK(bool(v2) == false); 177 | CHECK(v2.which() == v1.which()); 178 | 179 | CHECK(noexcept(eggs::variant<>(::move(v1))) == true); 180 | 181 | // list-initialization 182 | { 183 | eggs::variant<> v = {}; 184 | 185 | CHECK(bool(v) == false); 186 | CHECK(v.which() == eggs::variant_npos); 187 | CHECK(v.target() == nullptr); 188 | 189 | #if EGGS_CXX98_HAS_RTTI 190 | CHECK(v.target_type() == typeid(void)); 191 | #endif 192 | } 193 | 194 | #if EGGS_CXX14_HAS_CONSTEXPR 195 | // constexpr 196 | { 197 | struct test { static constexpr int call() 198 | { 199 | eggs::variant<> v1; 200 | eggs::variant<> v2(::move(v1)); 201 | return 0; 202 | }}; 203 | constexpr int c = test::call(); 204 | } 205 | #endif 206 | } 207 | -------------------------------------------------------------------------------- /test/constexpr.hpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #ifndef EGGS_VARIANT_TEST_CONSTEXPR_HPP 9 | #define EGGS_VARIANT_TEST_CONSTEXPR_HPP 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #if EGGS_CXX11_HAS_CONSTEXPR 17 | struct Constexpr 18 | { 19 | int x; 20 | 21 | constexpr Constexpr() : x(0) {} 22 | constexpr Constexpr(int i) : x(i) {} 23 | # if EGGS_CXX14_HAS_CONSTEXPR 24 | constexpr Constexpr(std::initializer_list is) : x(*is.begin()) {} 25 | # endif 26 | 27 | constexpr Constexpr(Constexpr const& rhs) : x(rhs.x) {} // not trivially copyable 28 | 29 | constexpr bool operator==(Constexpr rhs) const { return x == rhs.x; } 30 | constexpr bool operator!=(Constexpr rhs) const { return x != rhs.x; } 31 | constexpr bool operator<(Constexpr rhs) const { return x < rhs.x; } 32 | constexpr bool operator>(Constexpr rhs) const { return x > rhs.x; } 33 | constexpr bool operator<=(Constexpr rhs) const { return x <= rhs.x; } 34 | constexpr bool operator>=(Constexpr rhs) const { return x >= rhs.x; } 35 | }; 36 | 37 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 38 | namespace eggs { namespace variants { namespace detail 39 | { 40 | template <> struct is_trivially_destructible : std::true_type {}; 41 | }}} 42 | # endif 43 | 44 | struct ConstexprTrivial 45 | { 46 | constexpr ConstexprTrivial() {} 47 | constexpr ConstexprTrivial(int) {} 48 | # if EGGS_CXX14_HAS_CONSTEXPR 49 | constexpr ConstexprTrivial(std::initializer_list) {} 50 | # endif 51 | }; 52 | 53 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 54 | namespace eggs { namespace variants { namespace detail 55 | { 56 | template <> struct is_trivially_copyable : std::true_type {}; 57 | template <> struct is_trivially_destructible : std::true_type {}; 58 | }}} 59 | # endif 60 | #endif 61 | 62 | #endif /*EGGS_VARIANT_TEST_CONSTEXPR_HPP*/ 63 | -------------------------------------------------------------------------------- /test/dtor.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "catch.hpp" 14 | #include "dtor.hpp" 15 | 16 | struct Y 17 | { 18 | Y() {} 19 | Y(Y const&) {}; 20 | ~Y() = default; 21 | }; 22 | 23 | TEST_CASE("variant::~variant()", "[variant.dtor]") 24 | { 25 | { 26 | { 27 | eggs::variant v; 28 | v.emplace<1>(); 29 | 30 | REQUIRE(Dtor::calls == 0u); 31 | } 32 | CHECK(Dtor::calls == 1u); 33 | } 34 | Dtor::calls = 0u; 35 | 36 | // trivially_destructible 37 | { 38 | eggs::variant v1; 39 | eggs::variant v2; 40 | 41 | #if EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 42 | CHECK(std::is_trivially_destructible::value == true); 43 | CHECK(std::is_trivially_destructible::value == true); 44 | #endif 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/dtor.hpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #ifndef EGGS_VARIANT_TEST_DTOR_HPP 9 | #define EGGS_VARIANT_TEST_DTOR_HPP 10 | 11 | #include 12 | 13 | struct Dtor 14 | { 15 | static std::size_t calls; 16 | Dtor() {} 17 | ~Dtor() { ++calls; } 18 | }; 19 | 20 | std::size_t Dtor::calls = 0u; 21 | 22 | void swap(Dtor&, Dtor&) {} 23 | 24 | #endif /*EGGS_VARIANT_TEST_DTOR_HPP*/ 25 | -------------------------------------------------------------------------------- /test/elem.get.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | using eggs::variants::detail::move; 15 | 16 | #include "catch.hpp" 17 | #include "constexpr.hpp" 18 | 19 | TEST_CASE("get(variant&)", "[variant.elem]") 20 | { 21 | eggs::variant v(42); 22 | 23 | REQUIRE(v.which() == 0u); 24 | REQUIRE(*v.target() == 42); 25 | 26 | int& ref = eggs::variants::get<0>(v); 27 | 28 | CHECK(ref == 42); 29 | 30 | #if EGGS_CXX98_HAS_EXCEPTIONS 31 | // throws 32 | { 33 | CHECK_THROWS_AS( 34 | eggs::variants::get<1>(v) 35 | , eggs::variants::bad_variant_access); 36 | } 37 | #endif 38 | 39 | #if EGGS_CXX14_HAS_CONSTEXPR 40 | // constexpr 41 | { 42 | struct test { static constexpr int call() 43 | { 44 | eggs::variant v(Constexpr(42)); 45 | eggs::variants::get<1>(v).x = 43; 46 | return 0; 47 | }}; 48 | constexpr int c = test::call(); 49 | } 50 | #endif 51 | } 52 | 53 | TEST_CASE("get(variant&)", "[variant.elem]") 54 | { 55 | eggs::variant v(eggs::variants::in_place<0>, 42); 56 | 57 | REQUIRE(v.which() == 0u); 58 | REQUIRE(v.target() != nullptr); 59 | 60 | int& ref = eggs::variants::get<0>(v); 61 | 62 | CHECK(ref == 42); 63 | } 64 | 65 | TEST_CASE("get(variant const&)", "[variant.elem]") 66 | { 67 | eggs::variant const v(42); 68 | 69 | REQUIRE(v.which() == 0u); 70 | REQUIRE(*v.target() == 42); 71 | 72 | int const& ref = eggs::variants::get<0>(v); 73 | 74 | CHECK(ref == 42); 75 | 76 | #if EGGS_CXX98_HAS_EXCEPTIONS 77 | // throws 78 | { 79 | CHECK_THROWS_AS( 80 | eggs::variants::get<1>(v) 81 | , eggs::variants::bad_variant_access); 82 | } 83 | #endif 84 | 85 | #if EGGS_CXX11_HAS_CONSTEXPR 86 | // constexpr 87 | { 88 | constexpr eggs::variant v(Constexpr(42)); 89 | constexpr bool vgb = eggs::variants::get<1>(v).x == 42; 90 | } 91 | #endif 92 | } 93 | 94 | TEST_CASE("get(variant const&)", "[variant.elem]") 95 | { 96 | eggs::variant const v(eggs::variants::in_place<0>, 42); 97 | 98 | REQUIRE(v.which() == 0u); 99 | REQUIRE(v.target() != nullptr); 100 | 101 | int const& ref = eggs::variants::get<0>(v); 102 | 103 | CHECK(ref == 42); 104 | } 105 | 106 | TEST_CASE("get(variant&&)", "[variant.elem]") 107 | { 108 | eggs::variant v(42); 109 | 110 | REQUIRE(v.which() == 0u); 111 | REQUIRE(*v.target() == 42); 112 | 113 | int&& ref = eggs::variants::get<0>(::move(v)); 114 | 115 | CHECK(ref == 42); 116 | 117 | #if EGGS_CXX14_HAS_CONSTEXPR 118 | // constexpr 119 | { 120 | struct test { static constexpr int call() 121 | { 122 | eggs::variant v(Constexpr(42)); 123 | eggs::variants::get<1>(v).x = 43; 124 | return 0; 125 | }}; 126 | constexpr int c = test::call(); 127 | } 128 | #endif 129 | } 130 | 131 | TEST_CASE("get(variant const&&)", "[variant.elem]") 132 | { 133 | eggs::variant const v(42); 134 | 135 | REQUIRE(v.which() == 0u); 136 | REQUIRE(*v.target() == 42); 137 | 138 | int const&& ref = eggs::variants::get<0>(::move(v)); 139 | 140 | CHECK(ref == 42); 141 | 142 | #if EGGS_CXX14_HAS_CONSTEXPR 143 | // constexpr 144 | { 145 | constexpr eggs::variant v(Constexpr(42)); 146 | constexpr bool vgb = eggs::variants::get<1>(::move(v)).x == 42; 147 | } 148 | #endif 149 | } 150 | 151 | TEST_CASE("get(variant&)", "[variant.elem]") 152 | { 153 | eggs::variant v(42); 154 | 155 | int& ref = eggs::variants::get(v); 156 | 157 | CHECK(ref == 42); 158 | 159 | #if EGGS_CXX98_HAS_EXCEPTIONS 160 | // throws 161 | { 162 | CHECK_THROWS_AS( 163 | eggs::variants::get(v) 164 | , eggs::variants::bad_variant_access); 165 | } 166 | #endif 167 | 168 | #if EGGS_CXX14_HAS_CONSTEXPR 169 | // constexpr 170 | { 171 | struct test { static constexpr int call() 172 | { 173 | eggs::variant v(Constexpr(42)); 174 | eggs::variants::get(v).x = 43; 175 | return 0; 176 | }}; 177 | constexpr int c = test::call(); 178 | } 179 | #endif 180 | } 181 | 182 | TEST_CASE("get(variant const&)", "[variant.elem]") 183 | { 184 | eggs::variant const v(42); 185 | 186 | int const& ref = eggs::variants::get(v); 187 | 188 | CHECK(ref == 42); 189 | 190 | #if EGGS_CXX98_HAS_EXCEPTIONS 191 | // throws 192 | { 193 | CHECK_THROWS_AS( 194 | eggs::variants::get(v) 195 | , eggs::variants::bad_variant_access); 196 | } 197 | #endif 198 | 199 | #if EGGS_CXX11_HAS_CONSTEXPR 200 | // constexpr 201 | { 202 | constexpr eggs::variant v(Constexpr(42)); 203 | constexpr bool vgb = eggs::variants::get(v).x == 42; 204 | } 205 | #endif 206 | } 207 | 208 | TEST_CASE("get(variant&&)", "[variant.elem]") 209 | { 210 | eggs::variant v(42); 211 | 212 | int&& ref = eggs::variants::get(::move(v)); 213 | 214 | CHECK(ref == 42); 215 | 216 | #if EGGS_CXX14_HAS_CONSTEXPR 217 | // constexpr 218 | { 219 | struct test { static constexpr int call() 220 | { 221 | eggs::variant v(Constexpr(42)); 222 | eggs::variants::get(v).x = 43; 223 | return 0; 224 | }}; 225 | constexpr int c = test::call(); 226 | } 227 | #endif 228 | } 229 | 230 | TEST_CASE("get(variant const&&)", "[variant.elem]") 231 | { 232 | eggs::variant const v(42); 233 | 234 | int const&& ref = eggs::variants::get(::move(v)); 235 | 236 | CHECK(ref == 42); 237 | 238 | #if EGGS_CXX14_HAS_CONSTEXPR 239 | // constexpr 240 | { 241 | constexpr eggs::variant v(Constexpr(42)); 242 | constexpr bool vgb = eggs::variants::get(::move(v)).x == 42; 243 | } 244 | #endif 245 | } 246 | -------------------------------------------------------------------------------- /test/elem.get_if.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "catch.hpp" 14 | #include "constexpr.hpp" 15 | 16 | TEST_CASE("get_if(variant*)", "[variant.elem]") 17 | { 18 | // no source 19 | { 20 | eggs::variant *v = nullptr; 21 | 22 | int* ptr = eggs::variants::get_if<0>(v); 23 | 24 | CHECK(ptr == nullptr); 25 | 26 | CHECK(noexcept(eggs::variants::get_if<0>(v)) == true); 27 | } 28 | 29 | // same source 30 | { 31 | eggs::variant v(42); 32 | 33 | REQUIRE(v.which() == 0u); 34 | REQUIRE(*v.target() == 42); 35 | 36 | int* ptr = eggs::variants::get_if<0>(&v); 37 | 38 | REQUIRE(ptr != nullptr); 39 | CHECK(*ptr == 42); 40 | 41 | CHECK(noexcept(eggs::variants::get_if<0>(&v)) == true); 42 | } 43 | 44 | // different source 45 | { 46 | eggs::variant v(42); 47 | 48 | REQUIRE(v.which() == 0u); 49 | REQUIRE(*v.target() == 42); 50 | 51 | std::string* ptr = eggs::variants::get_if<1>(&v); 52 | 53 | CHECK(ptr == nullptr); 54 | 55 | CHECK(noexcept(eggs::variants::get_if<1>(&v)) == true); 56 | } 57 | 58 | #if EGGS_CXX14_HAS_CONSTEXPR 59 | // constexpr 60 | { 61 | struct test { static constexpr int call() 62 | { 63 | eggs::variant v(Constexpr(42)); 64 | eggs::variants::get_if<1>(&v)->x = 43; 65 | return 0; 66 | }}; 67 | constexpr int c = test::call(); 68 | } 69 | #endif 70 | } 71 | 72 | TEST_CASE("get_if(variant*)", "[variant.elem]") 73 | { 74 | eggs::variant v(eggs::variants::in_place<0>, 42); 75 | 76 | REQUIRE(v.which() == 0u); 77 | REQUIRE(v.target() != nullptr); 78 | 79 | int* ptr = eggs::variants::get_if<0>(&v); 80 | 81 | REQUIRE(ptr != nullptr); 82 | CHECK(*ptr == 42); 83 | } 84 | 85 | TEST_CASE("get_if(variant const*)", "[variant.elem]") 86 | { 87 | // no source 88 | { 89 | eggs::variant *v = nullptr; 90 | 91 | int const* ptr = eggs::variants::get_if<0>(v); 92 | 93 | CHECK(ptr == nullptr); 94 | 95 | CHECK(noexcept(eggs::variants::get_if<0>(v)) == true); 96 | } 97 | 98 | // same source 99 | { 100 | eggs::variant const v(42); 101 | 102 | REQUIRE(v.which() == 0u); 103 | REQUIRE(*v.target() == 42); 104 | 105 | int const* ptr = eggs::variants::get_if<0>(&v); 106 | 107 | REQUIRE(ptr != nullptr); 108 | CHECK(*ptr == 42); 109 | 110 | CHECK(noexcept(eggs::variants::get_if<0>(&v)) == true); 111 | } 112 | 113 | // different source 114 | { 115 | eggs::variant v(42); 116 | 117 | REQUIRE(v.which() == 0u); 118 | REQUIRE(*v.target() == 42); 119 | 120 | std::string const* ptr = eggs::variants::get_if<1>(&v); 121 | 122 | CHECK(ptr == nullptr); 123 | 124 | CHECK(noexcept(eggs::variants::get_if<1>(&v)) == true); 125 | } 126 | 127 | #if EGGS_CXX11_HAS_CONSTEXPR 128 | // constexpr 129 | { 130 | static constexpr eggs::variant v(Constexpr(42)); 131 | constexpr bool vgb = eggs::variants::get_if<1>(&v)->x == 42; 132 | } 133 | #endif 134 | } 135 | 136 | TEST_CASE("get_if(variant const*)", "[variant.elem]") 137 | { 138 | eggs::variant const v(eggs::variants::in_place<0>, 42); 139 | 140 | REQUIRE(v.which() == 0u); 141 | REQUIRE(v.target() != nullptr); 142 | 143 | int const* ptr = eggs::variants::get_if<0>(&v); 144 | 145 | REQUIRE(ptr != nullptr); 146 | CHECK(*ptr == 42); 147 | } 148 | 149 | TEST_CASE("get_if(variant*)", "[variant.elem]") 150 | { 151 | // no source 152 | { 153 | eggs::variant *v = nullptr; 154 | 155 | int* ptr = eggs::variants::get_if(v); 156 | 157 | CHECK(ptr == nullptr); 158 | 159 | CHECK(noexcept(eggs::variants::get_if(v)) == true); 160 | } 161 | 162 | // same source 163 | { 164 | eggs::variant v(42); 165 | 166 | int* ptr = eggs::variants::get_if(&v); 167 | 168 | REQUIRE(ptr != nullptr); 169 | CHECK(*ptr == 42); 170 | 171 | CHECK(noexcept(eggs::variants::get_if(&v)) == true); 172 | } 173 | 174 | // different source 175 | { 176 | eggs::variant v(42); 177 | 178 | std::string* ptr = eggs::variants::get_if(&v); 179 | 180 | CHECK(ptr == nullptr); 181 | 182 | CHECK(noexcept(eggs::variants::get_if(&v)) == true); 183 | } 184 | 185 | #if EGGS_CXX14_HAS_CONSTEXPR 186 | // constexpr 187 | { 188 | struct test { static constexpr int call() 189 | { 190 | eggs::variant v(Constexpr(42)); 191 | eggs::variants::get_if(&v)->x = 43; 192 | return 0; 193 | }}; 194 | constexpr int c = test::call(); 195 | } 196 | #endif 197 | } 198 | 199 | TEST_CASE("get_if(variant const*)", "[variant.elem]") 200 | { 201 | // no source 202 | { 203 | eggs::variant *v = nullptr; 204 | 205 | int const* ptr = eggs::variants::get_if(v); 206 | 207 | CHECK(ptr == nullptr); 208 | 209 | CHECK(noexcept(eggs::variants::get_if(v)) == true); 210 | } 211 | 212 | // same source 213 | { 214 | eggs::variant const v(42); 215 | 216 | int const* ptr = eggs::variants::get_if(&v); 217 | 218 | REQUIRE(ptr != nullptr); 219 | CHECK(*ptr == 42); 220 | 221 | CHECK(noexcept(eggs::variants::get_if(&v)) == true); 222 | } 223 | 224 | // different source 225 | { 226 | eggs::variant v(42); 227 | 228 | std::string const* ptr = eggs::variants::get_if(&v); 229 | 230 | CHECK(ptr == nullptr); 231 | 232 | CHECK(noexcept(eggs::variants::get_if(&v)) == true); 233 | } 234 | 235 | #if EGGS_CXX11_HAS_CONSTEXPR 236 | // constexpr 237 | { 238 | static constexpr eggs::variant v(Constexpr(42)); 239 | constexpr bool vgb = eggs::variants::get_if(&v)->x == 42; 240 | } 241 | #endif 242 | } 243 | -------------------------------------------------------------------------------- /test/hash.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "catch.hpp" 17 | 18 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 19 | template 20 | struct _void 21 | { 22 | using type = void; 23 | }; 24 | 25 | template 26 | struct has_hash 27 | : std::false_type 28 | {}; 29 | 30 | template 31 | struct has_hash< 32 | T, typename _void< 33 | decltype(std::hash{}(std::declval())) 34 | >::type 35 | > : std::true_type 36 | {}; 37 | 38 | template 39 | struct NoThrowHashDefaultConstructible {}; 40 | namespace std 41 | { 42 | template 43 | struct hash> 44 | { 45 | hash() noexcept(NoThrow) {} 46 | std::size_t operator()(NoThrowHashDefaultConstructible const&) const noexcept { return 0; } 47 | }; 48 | } 49 | 50 | template 51 | struct NoThrowHashable {}; 52 | namespace std 53 | { 54 | template 55 | struct hash> 56 | { 57 | hash() noexcept {} 58 | std::size_t operator()(NoThrowHashable const&) const noexcept(NoThrow) { return 0; } 59 | }; 60 | } 61 | 62 | template ::value> 63 | struct has_nothrow_hash 64 | { 65 | EGGS_CXX11_STATIC_CONSTEXPR bool value = 66 | noexcept(std::hash{}(std::declval())); 67 | }; 68 | 69 | template 70 | struct has_nothrow_hash 71 | { 72 | EGGS_CXX11_STATIC_CONSTEXPR bool value = false; 73 | }; 74 | #endif 75 | 76 | struct NonHashable {}; 77 | // explicitly disable (pre C++17) 78 | namespace std 79 | { 80 | template <> struct hash {}; 81 | } 82 | 83 | TEST_CASE("std::hash>", "[variant.hash]") 84 | { 85 | eggs::variant const v(42); 86 | 87 | REQUIRE(v.which() == 0u); 88 | REQUIRE(*v.target() == 42); 89 | 90 | std::hash> variant_hasher; 91 | std::hash int_hasher; 92 | 93 | CHECK(variant_hasher(v) == int_hasher(42)); 94 | 95 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 96 | // noexcept 97 | { 98 | REQUIRE( 99 | has_hash< 100 | eggs::variant> 101 | >::value); 102 | CHECK( 103 | has_nothrow_hash< 104 | eggs::variant> 105 | >::value); 106 | 107 | REQUIRE( 108 | has_hash< 109 | eggs::variant> 110 | >::value); 111 | CHECK( 112 | !has_nothrow_hash< 113 | eggs::variant> 114 | >::value); 115 | 116 | REQUIRE( 117 | has_hash< 118 | eggs::variant> 119 | >::value); 120 | CHECK( 121 | has_nothrow_hash< 122 | eggs::variant> 123 | >::value); 124 | 125 | REQUIRE( 126 | has_hash< 127 | eggs::variant> 128 | >::value); 129 | CHECK( 130 | !has_nothrow_hash< 131 | eggs::variant> 132 | >::value); 133 | } 134 | 135 | // sfinae 136 | { 137 | CHECK( 138 | !std::is_constructible< 139 | std::hash> 140 | >::value); 141 | CHECK( 142 | !std::is_copy_constructible< 143 | std::hash> 144 | >::value); 145 | CHECK( 146 | !std::is_move_constructible< 147 | std::hash> 148 | >::value); 149 | CHECK( 150 | !std::is_copy_assignable< 151 | std::hash> 152 | >::value); 153 | CHECK( 154 | !std::is_move_assignable< 155 | std::hash> 156 | >::value); 157 | CHECK( 158 | !has_hash< 159 | eggs::variant 160 | >::value); 161 | } 162 | #endif 163 | } 164 | -------------------------------------------------------------------------------- /test/helper.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "catch.hpp" 15 | 16 | template 17 | struct no_variant_size 18 | : std::true_type 19 | {}; 20 | 21 | template 22 | struct no_variant_size< 23 | T, 24 | typename std::enable_if< 25 | sizeof(typename eggs::variants::variant_size::type) >= 0 26 | >::type 27 | > : std::false_type 28 | {}; 29 | 30 | TEST_CASE("variant_size", "[variant.helper]") 31 | { 32 | std::size_t variant_size_0 = 33 | eggs::variants::variant_size< 34 | eggs::variant<> 35 | >::value; 36 | std::size_t variant_size_1 = 37 | eggs::variants::variant_size< 38 | eggs::variant 39 | >::value; 40 | std::size_t variant_size_2 = 41 | eggs::variants::variant_size< 42 | eggs::variant 43 | >::value; 44 | 45 | CHECK(variant_size_0 == 0u); 46 | CHECK(variant_size_1 == 1u); 47 | CHECK(variant_size_2 == 2u); 48 | 49 | std::size_t const_variant_size_0 = 50 | eggs::variants::variant_size< 51 | eggs::variant<> const 52 | >::value; 53 | 54 | CHECK(const_variant_size_0 == 0u); 55 | 56 | CHECK(no_variant_size::value == true); 57 | } 58 | 59 | TEST_CASE("variant_element", "[variant.helper]") 60 | { 61 | using variant_element_int = 62 | eggs::variants::variant_element< 63 | 0, eggs::variant 64 | >::type; 65 | 66 | using variant_element_string = 67 | eggs::variants::variant_element< 68 | 1, eggs::variant 69 | >::type; 70 | 71 | CHECK(std::is_same::value); 72 | CHECK(std::is_same::value); 73 | 74 | using const_variant_element_int = 75 | eggs::variants::variant_element< 76 | 0, eggs::variant const 77 | >::type; 78 | 79 | CHECK(std::is_same::value); 80 | } 81 | -------------------------------------------------------------------------------- /test/in_place.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "catch.hpp" 16 | 17 | struct fun_index 18 | { 19 | template 20 | eggs::variants::in_place_index_t 21 | operator()(eggs::variants::in_place_index_t tag) 22 | { 23 | return tag; 24 | } 25 | }; 26 | 27 | struct fun_type 28 | { 29 | template 30 | eggs::variants::in_place_type_t 31 | operator()(eggs::variants::in_place_type_t tag) 32 | { 33 | return tag; 34 | } 35 | }; 36 | 37 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 38 | template 39 | struct _void 40 | { 41 | using type = void; 42 | }; 43 | 44 | template 45 | struct is_callable 46 | : std::false_type 47 | {}; 48 | 49 | template 50 | struct is_callable< 51 | T, Arg, typename _void< 52 | decltype(std::declval()(std::declval())) 53 | >::type 54 | > : std::true_type 55 | {}; 56 | #endif 57 | 58 | TEST_CASE("in_place_index_t", "[variant.in_place]") 59 | { 60 | #if !defined(__GNUC__) 61 | // triggers https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81059 62 | eggs::variants::in_place_index_t<0> tag = eggs::variants::in_place<0>; 63 | 64 | CHECK(tag == eggs::variants::in_place<0>); 65 | 66 | tag = fun_index{}(eggs::variants::in_place<0>); 67 | 68 | CHECK(tag == eggs::variants::in_place<0>); 69 | #endif 70 | 71 | using decayed_tag = std::decay>::type; 72 | 73 | CHECK(std::is_same>::value); 74 | 75 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 76 | // nullptr 77 | { 78 | CHECK( 79 | !is_callable< 80 | fun_index, std::nullptr_t 81 | >::value); 82 | } 83 | #endif 84 | } 85 | 86 | TEST_CASE("in_place_type_t", "[variant.in_place]") 87 | { 88 | #if !defined(__GNUC__) 89 | // triggers https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81059 90 | eggs::variants::in_place_type_t tag = eggs::variants::in_place; 91 | 92 | CHECK(tag == eggs::variants::in_place); 93 | 94 | tag = fun_type{}(eggs::variants::in_place); 95 | 96 | CHECK(tag == eggs::variants::in_place); 97 | #endif 98 | 99 | using decayed_tag = std::decay>::type; 100 | 101 | CHECK(std::is_same>::value); 102 | 103 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 104 | // nullptr 105 | { 106 | CHECK( 107 | !is_callable< 108 | fun_type, std::nullptr_t 109 | >::value); 110 | } 111 | #endif 112 | } 113 | -------------------------------------------------------------------------------- /test/obs.bool.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "catch.hpp" 14 | #include "constexpr.hpp" 15 | 16 | TEST_CASE("variant::operator bool()", "[variant.obs]") 17 | { 18 | // non-empty 19 | { 20 | eggs::variant const v(42); 21 | 22 | CHECK(bool(v) == true); 23 | 24 | CHECK(noexcept(bool(v)) == true); 25 | 26 | #if EGGS_CXX11_HAS_CONSTEXPR 27 | // constexpr 28 | { 29 | constexpr eggs::variant v(42); 30 | constexpr bool vb = bool(v); 31 | } 32 | #endif 33 | } 34 | 35 | // empty 36 | { 37 | eggs::variant const v; 38 | 39 | CHECK(bool(v) == false); 40 | 41 | CHECK(noexcept(bool(v)) == true); 42 | 43 | #if EGGS_CXX11_HAS_CONSTEXPR 44 | // constexpr 45 | { 46 | constexpr eggs::variant v; 47 | constexpr bool vb = bool(v); 48 | } 49 | #endif 50 | } 51 | } 52 | 53 | TEST_CASE("variant<>::operator bool()", "[variant.obs]") 54 | { 55 | eggs::variant<> const v; 56 | 57 | CHECK(bool(v) == false); 58 | 59 | CHECK(noexcept(bool(v)) == true); 60 | 61 | #if EGGS_CXX11_HAS_CONSTEXPR 62 | // constexpr 63 | { 64 | constexpr eggs::variant<> v; 65 | constexpr bool vb = bool(v); 66 | } 67 | #endif 68 | } 69 | -------------------------------------------------------------------------------- /test/obs.target.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "catch.hpp" 15 | #include "constexpr.hpp" 16 | 17 | struct Base {}; 18 | struct Derived : Base {}; 19 | 20 | struct HasMemberAddressofOperator 21 | { 22 | int x; 23 | 24 | HasMemberAddressofOperator() : x(0) {} 25 | #if EGGS_CXX11_HAS_CONSTEXPR 26 | constexpr HasMemberAddressofOperator(int i) : x(i) {} 27 | #endif 28 | 29 | void operator&() const {} 30 | }; 31 | 32 | #if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 33 | namespace eggs { namespace variants { namespace detail 34 | { 35 | template <> struct is_trivially_destructible : std::true_type {}; 36 | }}} 37 | #endif 38 | 39 | struct HasFreeAddressofOperator 40 | { 41 | int x; 42 | 43 | HasFreeAddressofOperator() : x(0) {} 44 | #if EGGS_CXX11_HAS_CONSTEXPR 45 | constexpr HasFreeAddressofOperator(int i) : x(i) {} 46 | #endif 47 | }; 48 | void operator&(HasFreeAddressofOperator const&) {} 49 | 50 | #if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 51 | namespace eggs { namespace variants { namespace detail 52 | { 53 | template <> struct is_trivially_destructible : std::true_type {}; 54 | }}} 55 | #endif 56 | 57 | TEST_CASE("variant::target()", "[variant.obs]") 58 | { 59 | // non-empty 60 | { 61 | eggs::variant const v(42); 62 | 63 | CHECK(v.target() != nullptr); 64 | 65 | CHECK(noexcept(v.target()) == true); 66 | 67 | #if EGGS_CXX11_HAS_CONSTEXPR 68 | // constexpr 69 | { 70 | static constexpr eggs::variant v(42); 71 | constexpr bool vttb = v.target() != nullptr; 72 | 73 | # if EGGS_CXX14_HAS_CONSTEXPR 74 | struct test { static constexpr int call() 75 | { 76 | eggs::variant v(Constexpr(42)); 77 | void* vtt = v.target(); 78 | return 0; 79 | }}; 80 | constexpr int c = test::call(); 81 | # endif 82 | } 83 | #endif 84 | } 85 | 86 | // empty 87 | { 88 | eggs::variant const v; 89 | 90 | CHECK(v.target() == nullptr); 91 | 92 | CHECK(noexcept(v.target()) == true); 93 | 94 | #if EGGS_CXX11_HAS_CONSTEXPR 95 | // constexpr 96 | { 97 | constexpr eggs::variant v; 98 | constexpr bool vttb = v.target() == nullptr; 99 | 100 | # if EGGS_CXX14_HAS_CONSTEXPR 101 | struct test { static constexpr int call() 102 | { 103 | eggs::variant v; 104 | void* vtt = v.target(); 105 | return 0; 106 | }}; 107 | constexpr int c = test::call(); 108 | # endif 109 | } 110 | #endif 111 | } 112 | } 113 | 114 | TEST_CASE("variant<>::target()", "[variant.obs]") 115 | { 116 | eggs::variant<> const v; 117 | 118 | CHECK(v.target() == nullptr); 119 | 120 | CHECK(noexcept(v.target()) == true); 121 | 122 | #if EGGS_CXX11_HAS_CONSTEXPR 123 | // constexpr 124 | { 125 | constexpr eggs::variant<> v; 126 | constexpr bool vttb = v.target() == nullptr; 127 | 128 | # if EGGS_CXX14_HAS_CONSTEXPR 129 | struct test { static constexpr int call() 130 | { 131 | eggs::variant<> v; 132 | void* vtt = v.target(); 133 | return 0; 134 | }}; 135 | constexpr int c = test::call(); 136 | # endif 137 | } 138 | #endif 139 | } 140 | 141 | TEST_CASE("variant::target()", "[variant.obs]") 142 | { 143 | // non-empty 144 | { 145 | eggs::variant const v(42); 146 | 147 | CHECK(v.target() == v.target()); 148 | CHECK(v.target() == nullptr); 149 | CHECK(v.target() == nullptr); 150 | 151 | CHECK(noexcept(v.target()) == true); 152 | } 153 | 154 | // non-empty, base 155 | { 156 | eggs::variant const v(Derived{}); 157 | 158 | CHECK(v.target() == v.target()); 159 | CHECK(v.target() == v.target()); 160 | CHECK(v.target() == nullptr); 161 | CHECK(v.target() == nullptr); 162 | 163 | CHECK(noexcept(v.target()) == true); 164 | } 165 | 166 | // empty 167 | { 168 | eggs::variant const v; 169 | 170 | CHECK(v.target() == nullptr); 171 | CHECK(v.target() == nullptr); 172 | CHECK(v.target() == nullptr); 173 | 174 | CHECK(noexcept(v.target()) == true); 175 | } 176 | } 177 | 178 | TEST_CASE("variant::target()", "[variant.obs]") 179 | { 180 | eggs::variant const v(42.f); 181 | 182 | REQUIRE(v.which() == 1u); 183 | 184 | CHECK(v.target() == v.target()); 185 | 186 | CHECK(noexcept(v.target()) == true); 187 | 188 | #if EGGS_CXX11_HAS_CONSTEXPR 189 | // constexpr 190 | { 191 | constexpr eggs::variant v(42.f); 192 | constexpr bool vttb = *v.target() == 42.f; 193 | 194 | # if EGGS_CXX14_HAS_CONSTEXPR 195 | struct test { static constexpr int call() 196 | { 197 | eggs::variant v(42.f); 198 | *v.target() = 43.f; 199 | return 0; 200 | }}; 201 | constexpr int c = test::call(); 202 | # endif 203 | } 204 | #endif 205 | } 206 | 207 | TEST_CASE("variant::target()", "[variant.obs]") 208 | { 209 | eggs::variant const v(std::string{"42"}); 210 | 211 | REQUIRE(v.which() == 1u); 212 | 213 | CHECK(v.target() == v.target()); 214 | 215 | CHECK(noexcept(v.target()) == true); 216 | 217 | #if EGGS_CXX11_HAS_CONSTEXPR 218 | // constexpr 219 | { 220 | constexpr eggs::variant v(Constexpr(42)); 221 | constexpr bool vttb = v.target()->x == 42; 222 | 223 | # if EGGS_CXX14_HAS_CONSTEXPR 224 | struct test { static constexpr int call() 225 | { 226 | eggs::variant v(Constexpr(42)); 227 | v.target()->x = 43; 228 | return 0; 229 | }}; 230 | constexpr int c = test::call(); 231 | # endif 232 | } 233 | #endif 234 | } 235 | 236 | TEST_CASE("variant::target()", "[variant.obs]") 237 | { 238 | eggs::variant const v(HasMemberAddressofOperator{}); 239 | 240 | REQUIRE(v.which() == 1u); 241 | 242 | CHECK(v.target() == v.target()); 243 | 244 | #if EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF && EGGS_CXX11_HAS_CONSTEXPR 245 | // constexpr 246 | { 247 | static constexpr eggs::variant v(HasMemberAddressofOperator(42)); 248 | constexpr bool vttb = v.target()->x == 42; 249 | 250 | # if EGGS_CXX14_HAS_CONSTEXPR 251 | struct test { static constexpr int call() 252 | { 253 | eggs::variant v(HasMemberAddressofOperator(42)); 254 | v.target()->x = 43; 255 | return 0; 256 | }}; 257 | constexpr int c = test::call(); 258 | # endif 259 | } 260 | #endif 261 | } 262 | 263 | TEST_CASE("variant::target()", "[variant.obs]") 264 | { 265 | eggs::variant const v(HasFreeAddressofOperator{}); 266 | 267 | REQUIRE(v.which() == 1u); 268 | 269 | CHECK(v.target() == v.target()); 270 | 271 | #if EGGS_CXX17_STD_HAS_CONSTEXPR_ADDRESSOF && EGGS_CXX11_HAS_CONSTEXPR 272 | // constexpr 273 | { 274 | static constexpr eggs::variant v(HasFreeAddressofOperator(42)); 275 | constexpr bool vttb = v.target()->x == 42; 276 | 277 | # if EGGS_CXX14_HAS_CONSTEXPR 278 | struct test { static constexpr int call() 279 | { 280 | eggs::variant v(HasFreeAddressofOperator(42)); 281 | v.target()->x = 43; 282 | return 0; 283 | }}; 284 | constexpr int c = test::call(); 285 | # endif 286 | } 287 | #endif 288 | } 289 | 290 | TEST_CASE("variant<>::target()", "[variant.obs]") 291 | { 292 | eggs::variant<> const v; 293 | 294 | CHECK(v.target() == nullptr); 295 | 296 | CHECK(noexcept(v.target()) == true); 297 | 298 | #if EGGS_CXX11_HAS_CONSTEXPR 299 | // constexpr 300 | { 301 | constexpr eggs::variant<> v; 302 | constexpr bool vttb = v.target() == nullptr; 303 | 304 | # if EGGS_CXX14_HAS_CONSTEXPR 305 | struct test { static constexpr int call() 306 | { 307 | eggs::variant<> v; 308 | int* vtt = v.target(); 309 | return 0; 310 | }}; 311 | constexpr int c = test::call(); 312 | # endif 313 | } 314 | #endif 315 | } 316 | -------------------------------------------------------------------------------- /test/obs.target_type.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include "catch.hpp" 15 | #include "constexpr.hpp" 16 | 17 | #if EGGS_CXX98_HAS_RTTI 18 | TEST_CASE("variant::target_type()", "[variant.obs]") 19 | { 20 | // non-empty 21 | { 22 | eggs::variant const v(42); 23 | 24 | CHECK(v.target_type() == typeid(int)); 25 | 26 | CHECK(noexcept(v.target_type()) == true); 27 | 28 | #if EGGS_CXX11_HAS_CONSTEXPR_RTTI 29 | // constexpr 30 | { 31 | constexpr eggs::variant v(42); 32 | constexpr std::type_info const& vtt = v.target_type(); 33 | } 34 | #endif 35 | } 36 | 37 | // empty 38 | { 39 | eggs::variant const v; 40 | 41 | CHECK(v.target_type() == typeid(void)); 42 | 43 | CHECK(noexcept(v.target_type()) == true); 44 | 45 | #if EGGS_CXX11_HAS_CONSTEXPR_RTTI 46 | // constexpr 47 | { 48 | constexpr eggs::variant v; 49 | constexpr std::type_info const& vtt = v.target_type(); 50 | } 51 | #endif 52 | } 53 | } 54 | 55 | TEST_CASE("variant<>::target_type()", "[variant.obs]") 56 | { 57 | eggs::variant<> const v; 58 | 59 | CHECK(v.target_type() == typeid(void)); 60 | 61 | CHECK(noexcept(v.target_type()) == true); 62 | 63 | #if EGGS_CXX11_HAS_CONSTEXPR_RTTI 64 | // constexpr 65 | { 66 | constexpr eggs::variant<> v; 67 | constexpr std::type_info const& vtt = v.target_type(); 68 | } 69 | #endif 70 | } 71 | #endif 72 | -------------------------------------------------------------------------------- /test/obs.which.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "catch.hpp" 14 | #include "constexpr.hpp" 15 | 16 | TEST_CASE("variant::which()", "[variant.obs]") 17 | { 18 | // non-empty 19 | { 20 | eggs::variant const v(42); 21 | 22 | CHECK(v.which() == 0); 23 | 24 | CHECK(noexcept(v.which()) == true); 25 | 26 | #if EGGS_CXX11_HAS_CONSTEXPR 27 | // constexpr 28 | { 29 | constexpr eggs::variant v(42); 30 | constexpr std::size_t vw = v.which(); 31 | } 32 | #endif 33 | } 34 | 35 | // empty 36 | { 37 | eggs::variant const v; 38 | 39 | CHECK(v.which() == eggs::variant_npos); 40 | 41 | CHECK(noexcept(v.which()) == true); 42 | 43 | #if EGGS_CXX11_HAS_CONSTEXPR 44 | // constexpr 45 | { 46 | constexpr eggs::variant v; 47 | constexpr std::size_t vw = v.which(); 48 | } 49 | #endif 50 | } 51 | } 52 | 53 | TEST_CASE("variant<>::which()", "[variant.obs]") 54 | { 55 | eggs::variant<> const v; 56 | 57 | CHECK(v.which() == eggs::variant_npos); 58 | 59 | CHECK(noexcept(v.which()) == true); 60 | 61 | #if EGGS_CXX11_HAS_CONSTEXPR 62 | // constexpr 63 | { 64 | constexpr eggs::variant<> v; 65 | constexpr std::size_t vw = v.which(); 66 | } 67 | #endif 68 | } 69 | -------------------------------------------------------------------------------- /test/rel.equality.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "catch.hpp" 17 | #include "constexpr.hpp" 18 | 19 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 20 | template 21 | struct _void 22 | { 23 | using type = void; 24 | }; 25 | 26 | template 27 | struct has_equal 28 | : std::false_type 29 | {}; 30 | 31 | template 32 | struct has_equal< 33 | T, U, typename _void< 34 | decltype(std::declval() == std::declval()) 35 | >::type 36 | > : std::true_type 37 | {}; 38 | 39 | template 40 | struct has_not_equal 41 | : std::false_type 42 | {}; 43 | 44 | template 45 | struct has_not_equal< 46 | T, U, typename _void< 47 | decltype(std::declval() != std::declval()) 48 | >::type 49 | > : std::true_type 50 | {}; 51 | 52 | template 53 | struct NonComparable 54 | { 55 | NonComparable(T const&) {} 56 | }; 57 | #endif 58 | 59 | TEST_CASE("operator==(variant const&, variant const&)", "[variant.rel]") 60 | { 61 | // same members 62 | { 63 | eggs::variant const v1(42); 64 | 65 | REQUIRE(v1.which() == 0u); 66 | REQUIRE(*v1.target() == 42); 67 | 68 | eggs::variant const v2(42); 69 | 70 | REQUIRE(v2.which() == v1.which()); 71 | REQUIRE(*v2.target() == 42); 72 | 73 | CHECK((v1 == v2) == true); 74 | CHECK((v1 != v2) == false); 75 | 76 | // partial order 77 | { 78 | eggs::variant const v(NAN); 79 | 80 | REQUIRE(v.which() == 0u); 81 | 82 | CHECK((v == v) == false); 83 | CHECK((v != v) == true); 84 | } 85 | 86 | #if EGGS_CXX11_HAS_CONSTEXPR 87 | // constexpr 88 | { 89 | constexpr eggs::variant v1(Constexpr(42)); 90 | constexpr eggs::variant v2(Constexpr(42)); 91 | constexpr bool veb = v1 == v2; 92 | constexpr bool vneb = v1 != v2; 93 | } 94 | #endif 95 | } 96 | 97 | // empty member 98 | { 99 | eggs::variant const v1; 100 | 101 | REQUIRE(v1.which() == eggs::variant_npos); 102 | 103 | eggs::variant const v2(42); 104 | 105 | REQUIRE(v2.which() == 0u); 106 | REQUIRE(*v2.target() == 42); 107 | 108 | CHECK((v1 == v2) == false); 109 | CHECK((v1 != v2) == true); 110 | 111 | #if EGGS_CXX11_HAS_CONSTEXPR 112 | // constexpr 113 | { 114 | constexpr eggs::variant v1; 115 | constexpr eggs::variant v2(Constexpr(42)); 116 | constexpr bool veb = v1 == v2; 117 | constexpr bool vneb = v1 != v2; 118 | } 119 | #endif 120 | } 121 | 122 | // different members 123 | { 124 | eggs::variant const v1(std::string("")); 125 | 126 | REQUIRE(v1.which() == 1u); 127 | REQUIRE(*v1.target() == ""); 128 | 129 | eggs::variant const v2(42); 130 | 131 | REQUIRE(v2.which() == 0u); 132 | REQUIRE(*v2.target() == 42); 133 | 134 | CHECK((v1 == v2) == false); 135 | CHECK((v1 != v2) == true); 136 | 137 | #if EGGS_CXX11_HAS_CONSTEXPR 138 | // constexpr 139 | { 140 | constexpr eggs::variant v1(42); 141 | constexpr eggs::variant v2(Constexpr(42)); 142 | constexpr bool veb = v1 == v2; 143 | constexpr bool vneb = v1 != v2; 144 | } 145 | #endif 146 | } 147 | 148 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 149 | // sfinae 150 | { 151 | CHECK( 152 | !has_equal< 153 | eggs::variant> 154 | >::value); 155 | CHECK( 156 | !has_not_equal< 157 | eggs::variant> 158 | >::value); 159 | } 160 | #endif 161 | } 162 | 163 | TEST_CASE("operator==(variant const&, T const&)", "[variant.rel]") 164 | { 165 | // same members 166 | { 167 | eggs::variant const v(42); 168 | 169 | REQUIRE(v.which() == 0u); 170 | REQUIRE(*v.target() == 42); 171 | 172 | CHECK((v == 42) == true); 173 | CHECK((v != 42) == false); 174 | 175 | // partial order 176 | { 177 | eggs::variant const v(NAN); 178 | 179 | REQUIRE(v.which() == 0u); 180 | 181 | CHECK((v == NAN) == false); 182 | CHECK((v != NAN) == true); 183 | } 184 | 185 | #if EGGS_CXX11_HAS_CONSTEXPR 186 | // constexpr 187 | { 188 | constexpr eggs::variant v(Constexpr(42)); 189 | constexpr bool veb = v == Constexpr(42); 190 | constexpr bool vneb = v != Constexpr(42); 191 | } 192 | #endif 193 | } 194 | 195 | // empty member 196 | { 197 | eggs::variant const v; 198 | 199 | REQUIRE(v.which() == eggs::variant_npos); 200 | 201 | CHECK((v == 42) == false); 202 | CHECK((v != 42) == true); 203 | 204 | #if EGGS_CXX11_HAS_CONSTEXPR 205 | // constexpr 206 | { 207 | constexpr eggs::variant v; 208 | constexpr bool veb = v == Constexpr(42); 209 | constexpr bool vneb = v != Constexpr(42); 210 | } 211 | #endif 212 | } 213 | 214 | // different members 215 | { 216 | eggs::variant const v(std::string("")); 217 | 218 | REQUIRE(v.which() == 1u); 219 | REQUIRE(*v.target() == ""); 220 | 221 | CHECK((v == 42) == false); 222 | CHECK((v != 42) == true); 223 | 224 | #if EGGS_CXX11_HAS_CONSTEXPR 225 | // constexpr 226 | { 227 | constexpr eggs::variant v(42); 228 | constexpr bool veb = v == Constexpr(42); 229 | constexpr bool vneb = v != Constexpr(42); 230 | } 231 | #endif 232 | } 233 | 234 | // implicit conversion 235 | { 236 | eggs::variant v("42"); 237 | 238 | REQUIRE(v.which() == 1u); 239 | REQUIRE(*v.target() == "42"); 240 | 241 | CHECK((v == "42") == true); 242 | CHECK((v != "42") == false); 243 | } 244 | 245 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 246 | // sfinae 247 | { 248 | CHECK( 249 | !has_equal< 250 | eggs::variant, std::string 251 | >::value); 252 | CHECK( 253 | !has_not_equal< 254 | eggs::variant, std::string 255 | >::value); 256 | 257 | CHECK( 258 | !has_equal< 259 | eggs::variant>, int 260 | >::value); 261 | CHECK( 262 | !has_not_equal< 263 | eggs::variant>, int 264 | >::value); 265 | } 266 | #endif 267 | } 268 | 269 | TEST_CASE("operator==(T const&, variant const&)", "[variant.rel]") 270 | { 271 | // same members 272 | { 273 | eggs::variant const v(42); 274 | 275 | REQUIRE(v.which() == 0u); 276 | REQUIRE(*v.target() == 42); 277 | 278 | CHECK((42 == v) == true); 279 | CHECK((42 != v) == false); 280 | 281 | // partial order 282 | { 283 | eggs::variant const v(NAN); 284 | 285 | REQUIRE(v.which() == 0u); 286 | 287 | CHECK((NAN == v) == false); 288 | CHECK((NAN != v) == true); 289 | } 290 | 291 | #if EGGS_CXX11_HAS_CONSTEXPR 292 | // constexpr 293 | { 294 | constexpr eggs::variant v(Constexpr(42)); 295 | constexpr bool veb = Constexpr(42) == v; 296 | constexpr bool vneb = Constexpr(42) != v; 297 | } 298 | #endif 299 | } 300 | 301 | // empty member 302 | { 303 | eggs::variant const v; 304 | 305 | REQUIRE(v.which() == eggs::variant_npos); 306 | 307 | CHECK((42 == v) == false); 308 | CHECK((42 != v) == true); 309 | 310 | #if EGGS_CXX11_HAS_CONSTEXPR 311 | // constexpr 312 | { 313 | constexpr eggs::variant v; 314 | constexpr bool veb = Constexpr(42) == v; 315 | constexpr bool vneb = Constexpr(42) != v; 316 | } 317 | #endif 318 | } 319 | 320 | // different members 321 | { 322 | eggs::variant const v(std::string("")); 323 | 324 | REQUIRE(v.which() == 1u); 325 | REQUIRE(*v.target() == ""); 326 | 327 | CHECK((42 == v) == false); 328 | CHECK((42 != v) == true); 329 | 330 | #if EGGS_CXX11_HAS_CONSTEXPR 331 | // constexpr 332 | { 333 | constexpr eggs::variant v(42); 334 | constexpr bool veb = Constexpr(42) == v; 335 | constexpr bool vneb = Constexpr(42) != v; 336 | } 337 | #endif 338 | } 339 | 340 | // implicit conversion 341 | { 342 | eggs::variant v("42"); 343 | 344 | REQUIRE(v.which() == 1u); 345 | REQUIRE(*v.target() == "42"); 346 | 347 | CHECK(("42" == v) == true); 348 | CHECK(("42" != v) == false); 349 | } 350 | 351 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 352 | // sfinae 353 | { 354 | CHECK( 355 | !has_equal< 356 | std::string, eggs::variant 357 | >::value); 358 | CHECK( 359 | !has_not_equal< 360 | std::string, eggs::variant 361 | >::value); 362 | 363 | CHECK( 364 | !has_equal< 365 | int, eggs::variant> 366 | >::value); 367 | CHECK( 368 | !has_not_equal< 369 | int, eggs::variant> 370 | >::value); 371 | } 372 | #endif 373 | } 374 | 375 | TEST_CASE("operator==(variant<> const&, variant<> const&)", "[variant.rel]") 376 | { 377 | eggs::variant<> const v1; 378 | 379 | REQUIRE(v1.which() == eggs::variant_npos); 380 | 381 | eggs::variant<> const v2; 382 | 383 | REQUIRE(v2.which() == eggs::variant_npos); 384 | 385 | CHECK((v1 == v2) == true); 386 | CHECK((v1 != v2) == false); 387 | 388 | #if EGGS_CXX11_HAS_CONSTEXPR 389 | // constexpr 390 | { 391 | constexpr eggs::variant<> v1; 392 | constexpr eggs::variant<> v2; 393 | constexpr bool veb = v1 == v2; 394 | constexpr bool vneb = v1 != v2; 395 | } 396 | #endif 397 | } 398 | -------------------------------------------------------------------------------- /test/swap.cpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "catch.hpp" 16 | #include "constexpr.hpp" 17 | #include "dtor.hpp" 18 | 19 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 20 | template 21 | struct _void 22 | { 23 | using type = void; 24 | }; 25 | 26 | template 27 | struct has_swap 28 | : std::false_type 29 | {}; 30 | 31 | template 32 | struct has_swap< 33 | T, typename _void< 34 | decltype(swap(std::declval(), std::declval())) 35 | >::type 36 | > : std::true_type 37 | {}; 38 | #endif 39 | 40 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 41 | template 42 | struct NoThrowMoveConstructible 43 | { 44 | NoThrowMoveConstructible() {} 45 | NoThrowMoveConstructible(NoThrowMoveConstructible&&) noexcept(NoThrow) {} 46 | NoThrowMoveConstructible& operator=(NoThrowMoveConstructible&&) noexcept { return *this; }; 47 | }; 48 | template 49 | void swap(NoThrowMoveConstructible&, NoThrowMoveConstructible&) noexcept {} 50 | 51 | template 52 | struct NoThrowMoveSwappable 53 | { 54 | NoThrowMoveSwappable() {} 55 | NoThrowMoveSwappable(NoThrowMoveSwappable&&) noexcept {} 56 | NoThrowMoveSwappable& operator=(NoThrowMoveSwappable&&) noexcept { return *this; }; 57 | }; 58 | template 59 | void swap(NoThrowMoveSwappable&, NoThrowMoveSwappable&) noexcept(NoThrow) {} 60 | #endif 61 | struct NonAssignable 62 | { 63 | NonAssignable() {} 64 | NonAssignable(NonAssignable&&) {}; // not trivially copyable 65 | NonAssignable& operator=(NonAssignable const&) = delete; 66 | ~NonAssignable() {} 67 | }; 68 | void swap(NonAssignable&, NonAssignable&) {} 69 | 70 | struct NonAssignableTrivial 71 | { 72 | NonAssignableTrivial() {} 73 | NonAssignableTrivial(NonAssignableTrivial&&) = default; 74 | NonAssignableTrivial& operator=(NonAssignableTrivial const&) = delete; 75 | }; 76 | void swap(NonAssignableTrivial&, NonAssignableTrivial&) {} 77 | 78 | # if !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_COPYABLE || !EGGS_CXX11_STD_HAS_IS_TRIVIALLY_DESTRUCTIBLE 79 | namespace eggs { namespace variants { namespace detail 80 | { 81 | template <> struct is_trivially_copyable : std::true_type {}; 82 | template <> struct is_trivially_destructible : std::true_type {}; 83 | }}} 84 | # endif 85 | 86 | struct NonSwappable 87 | { 88 | NonSwappable() {} 89 | NonSwappable(NonSwappable&&) {} 90 | NonSwappable& operator=(NonSwappable const&) { return *this; }; 91 | }; 92 | void swap(NonSwappable&, NonSwappable&) = delete; 93 | 94 | struct StdAssociateSwappable : std::true_type {}; 95 | 96 | #if !EGGS_CXX17_STD_HAS_SWAPPABLE_TRAITS 97 | namespace std 98 | { 99 | namespace swappable_traits 100 | { 101 | using ::eggs::variants::detail::is_swappable; 102 | using ::eggs::variants::detail::is_nothrow_swappable; 103 | } 104 | using namespace swappable_traits; 105 | } 106 | #endif 107 | 108 | TEST_CASE("variant::swap(variant&)", "[variant.swap]") 109 | { 110 | // empty source 111 | { 112 | eggs::variant v1; 113 | 114 | REQUIRE(v1.which() == eggs::variant_npos); 115 | 116 | eggs::variant v2(42); 117 | 118 | REQUIRE(v2.which() == 0u); 119 | REQUIRE(*v2.target() == 42); 120 | 121 | v2.swap(v1); 122 | 123 | CHECK(v1.which() == 0u); 124 | REQUIRE(v1.target() != nullptr); 125 | CHECK(*v1.target() == 42); 126 | CHECK(v2.which() == eggs::variant_npos); 127 | 128 | // dtor 129 | { 130 | eggs::variant v1; 131 | eggs::variant v2(eggs::variants::in_place); 132 | 133 | REQUIRE(v1.which() == eggs::variant_npos); 134 | REQUIRE(v2.which() == 1u); 135 | REQUIRE(Dtor::calls == 0u); 136 | 137 | v1.swap(v2); 138 | 139 | CHECK(v1.which() == 1u); 140 | CHECK(v2.which() == eggs::variant_npos); 141 | CHECK(Dtor::calls == 1u); 142 | } 143 | Dtor::calls = 0u; 144 | 145 | #if EGGS_CXX14_HAS_CONSTEXPR 146 | // constexpr 147 | { 148 | struct test { static constexpr int call() 149 | { 150 | eggs::variant v1; 151 | eggs::variant v2(ConstexprTrivial(42)); 152 | v2.swap(v1); 153 | return 0; 154 | }}; 155 | constexpr int c = test::call(); 156 | } 157 | #endif 158 | } 159 | 160 | // empty target 161 | { 162 | eggs::variant v1(42); 163 | 164 | REQUIRE(v1.which() == 0u); 165 | REQUIRE(*v1.target() == 42); 166 | 167 | eggs::variant v2; 168 | 169 | REQUIRE(v2.which() == eggs::variant_npos); 170 | 171 | v2.swap(v1); 172 | 173 | CHECK(v1.which() == eggs::variant_npos); 174 | CHECK(v2.which() == 0u); 175 | REQUIRE(v2.target() != nullptr); 176 | CHECK(*v2.target() == 42); 177 | 178 | // dtor 179 | { 180 | eggs::variant v1(eggs::variants::in_place); 181 | eggs::variant v2; 182 | 183 | REQUIRE(v1.which() == 1u); 184 | REQUIRE(v2.which() == eggs::variant_npos); 185 | REQUIRE(Dtor::calls == 0u); 186 | 187 | v1.swap(v2); 188 | 189 | CHECK(v1.which() == eggs::variant_npos); 190 | CHECK(v2.which() == 1u); 191 | CHECK(Dtor::calls == 1u); 192 | } 193 | Dtor::calls = 0u; 194 | 195 | #if EGGS_CXX14_HAS_CONSTEXPR 196 | // constexpr 197 | { 198 | struct test { static constexpr int call() 199 | { 200 | eggs::variant v1(ConstexprTrivial(42)); 201 | eggs::variant v2; 202 | v2.swap(v1); 203 | return 0; 204 | }}; 205 | constexpr int c = test::call(); 206 | } 207 | #endif 208 | } 209 | 210 | // same target 211 | { 212 | eggs::variant v1(42); 213 | 214 | REQUIRE(v1.which() == 0u); 215 | REQUIRE(*v1.target() == 42); 216 | 217 | eggs::variant v2(43); 218 | 219 | REQUIRE(v2.which() == v1.which()); 220 | REQUIRE(*v2.target() == 43); 221 | 222 | v2.swap(v1); 223 | 224 | CHECK(v1.which() == v1.which()); 225 | REQUIRE(v1.target() != nullptr); 226 | CHECK(*v1.target() == 43); 227 | CHECK(v2.which() == 0u); 228 | REQUIRE(v2.target() != nullptr); 229 | CHECK(*v2.target() == 42); 230 | 231 | // dtor 232 | { 233 | eggs::variant v1(eggs::variants::in_place); 234 | eggs::variant v2(eggs::variants::in_place); 235 | 236 | REQUIRE(v1.which() == 1u); 237 | REQUIRE(v2.which() == 1u); 238 | REQUIRE(Dtor::calls == 0u); 239 | 240 | v1.swap(v2); 241 | 242 | CHECK(v1.which() == 1u); 243 | CHECK(v2.which() == 1u); 244 | CHECK(Dtor::calls == 0u); 245 | } 246 | Dtor::calls = 0u; 247 | 248 | #if EGGS_CXX14_HAS_CONSTEXPR 249 | // constexpr 250 | { 251 | struct test { static constexpr int call() 252 | { 253 | eggs::variant v1(ConstexprTrivial(42)); 254 | eggs::variant v2(ConstexprTrivial(43)); 255 | v2.swap(v1); 256 | return 0; 257 | }}; 258 | constexpr int c = test::call(); 259 | } 260 | #endif 261 | } 262 | 263 | // different target 264 | { 265 | eggs::variant v1(42); 266 | 267 | REQUIRE(v1.which() == 0u); 268 | REQUIRE(*v1.target() == 42); 269 | 270 | eggs::variant v2(std::string("")); 271 | 272 | REQUIRE(v2.which() == 1u); 273 | REQUIRE(*v2.target() == ""); 274 | 275 | v2.swap(v1); 276 | 277 | CHECK(v1.which() == 1u); 278 | REQUIRE(v1.target() != nullptr); 279 | CHECK(*v1.target() == ""); 280 | CHECK(v2.which() == 0u); 281 | REQUIRE(v2.target() != nullptr); 282 | CHECK(*v2.target() == 42); 283 | 284 | // dtor 285 | { 286 | eggs::variant v1(42); 287 | eggs::variant v2(eggs::variants::in_place); 288 | 289 | REQUIRE(v1.which() == 0u); 290 | REQUIRE(v2.which() == 1u); 291 | REQUIRE(Dtor::calls == 0u); 292 | 293 | v1.swap(v2); 294 | 295 | CHECK(v1.which() == 1u); 296 | CHECK(v2.which() == 0u); 297 | CHECK(Dtor::calls == 1u); 298 | } 299 | Dtor::calls = 0u; 300 | 301 | #if EGGS_CXX14_HAS_CONSTEXPR 302 | // constexpr 303 | { 304 | struct test { static constexpr int call() 305 | { 306 | eggs::variant v1(ConstexprTrivial(42)); 307 | eggs::variant v2(43); 308 | v2.swap(v1); 309 | return 0; 310 | }}; 311 | constexpr int c = test::call(); 312 | } 313 | #endif 314 | } 315 | 316 | #if EGGS_CXX11_STD_HAS_IS_NOTHROW_TRAITS 317 | // noexcept 318 | { 319 | REQUIRE( 320 | std::is_swappable< 321 | eggs::variant> 322 | >::value); 323 | CHECK( 324 | std::is_nothrow_swappable< 325 | eggs::variant> 326 | >::value); 327 | 328 | REQUIRE( 329 | std::is_swappable< 330 | eggs::variant> 331 | >::value); 332 | CHECK( 333 | !std::is_nothrow_swappable< 334 | eggs::variant> 335 | >::value); 336 | 337 | REQUIRE( 338 | std::is_swappable< 339 | eggs::variant> 340 | >::value); 341 | CHECK( 342 | std::is_nothrow_swappable< 343 | eggs::variant> 344 | >::value); 345 | 346 | REQUIRE( 347 | std::is_swappable< 348 | eggs::variant> 349 | >::value); 350 | CHECK( 351 | !std::is_nothrow_swappable< 352 | eggs::variant> 353 | >::value); 354 | } 355 | #endif 356 | 357 | #if EGGS_CXX11_HAS_SFINAE_FOR_EXPRESSIONS 358 | // sfinae 359 | { 360 | eggs::variant v1, v2; 361 | eggs::variants::swap(v1, v2); 362 | 363 | CHECK( 364 | !has_swap< 365 | eggs::variant 366 | >::value); 367 | } 368 | #endif 369 | } 370 | 371 | TEST_CASE("variant::swap(variant<...>&)", "[variant.swap]") 372 | { 373 | eggs::variant v1(42); 374 | 375 | REQUIRE(v1.which() == 0u); 376 | 377 | eggs::variant v2(NonAssignable{}); 378 | 379 | REQUIRE(v2.which() == 1u); 380 | 381 | v2.swap(v1); 382 | 383 | CHECK(v1.which() == 1u); 384 | CHECK(v2.which() == 0u); 385 | 386 | // trivially_copyable 387 | { 388 | eggs::variant v1(42); 389 | 390 | REQUIRE(v1.which() == 0u); 391 | 392 | eggs::variant v2(NonAssignableTrivial{}); 393 | 394 | REQUIRE(v2.which() == 1u); 395 | 396 | v2.swap(v1); 397 | 398 | CHECK(v1.which() == 1u); 399 | CHECK(v2.which() == 0u); 400 | } 401 | } 402 | 403 | TEST_CASE("variant<>::swap(variant<>&)", "[variant.swap]") 404 | { 405 | eggs::variant<> v1; 406 | 407 | REQUIRE(v1.which() == eggs::variant_npos); 408 | 409 | eggs::variant<> v2; 410 | 411 | REQUIRE(v2.which() == eggs::variant_npos); 412 | 413 | v2.swap(v1); 414 | 415 | CHECK(v1.which() == eggs::variant_npos); 416 | CHECK(v2.which() == eggs::variant_npos); 417 | 418 | CHECK(noexcept(v2.swap(v1)) == true); 419 | 420 | #if EGGS_CXX14_HAS_CONSTEXPR 421 | // constexpr 422 | { 423 | struct test { static constexpr int call() 424 | { 425 | eggs::variant<> v1; 426 | eggs::variant<> v2; 427 | v2.swap(v1); 428 | return 0; 429 | }}; 430 | constexpr int c = test::call(); 431 | } 432 | #endif 433 | } 434 | -------------------------------------------------------------------------------- /test/throw.hpp: -------------------------------------------------------------------------------- 1 | // Eggs.Variant 2 | // 3 | // Copyright Agustin K-ballo Berge, Fusion Fenix 2014-2018 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #ifndef EGGS_VARIANT_TEST_THROW_HPP 9 | #define EGGS_VARIANT_TEST_THROW_HPP 10 | 11 | #include 12 | 13 | #include 14 | 15 | #if EGGS_CXX98_HAS_EXCEPTIONS 16 | struct Throw 17 | { 18 | Throw() {} 19 | Throw(int) { throw 0; } 20 | Throw(std::initializer_list) { throw 0; } 21 | Throw(Throw const&) { throw 0; } 22 | Throw(Throw&&) { throw 0; } 23 | Throw& operator=(Throw const&) { throw 0; } 24 | Throw& operator=(Throw&&) { throw 0; } 25 | ~Throw() {} 26 | }; 27 | #endif 28 | 29 | #endif /*EGGS_VARIANT_TEST_THROW_HPP*/ 30 | --------------------------------------------------------------------------------