├── .gitignore ├── CMakeLists.txt ├── include └── make_overloaded_function.hpp ├── test ├── test_make_overloaded_function.cpp └── nonstd │ └── variant.hpp ├── LICENSE.txt ├── README.md └── .clang-format /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(make_overloaded_function) 3 | 4 | add_library(make_overloaded_function INTERFACE) 5 | target_include_directories(make_overloaded_function INTERFACE "include") 6 | target_compile_features(make_overloaded_function INTERFACE cxx_variadic_templates) 7 | 8 | if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 9 | add_executable(test_make_overloaded_function test/test_make_overloaded_function) 10 | target_link_libraries(test_make_overloaded_function make_overloaded_function) 11 | endif() 12 | -------------------------------------------------------------------------------- /include/make_overloaded_function.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 by Michael Maltese 2 | // 3 | // https://github.com/ligfx/make_overloaded_function 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // (See accompanying file LICENSE.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | #pragma once 10 | 11 | #ifndef MAKE_OVERLOADED_FUNCTION_HPP 12 | #define MAKE_OVERLOADED_FUNCTION_HPP 13 | 14 | template struct overloaded; 15 | 16 | template struct overloaded : F1 { 17 | using F1::operator(); 18 | overloaded(F1 f0) : F1(f0) {} 19 | }; 20 | 21 | template 22 | struct overloaded : F1, overloaded { 23 | using F1::operator(); 24 | using overloaded::operator(); 25 | overloaded(F1 f0, Fs... fs) : F1(f0), overloaded(fs...) {} 26 | }; 27 | 28 | template 29 | overloaded make_overloaded_function(Fs... fs) { 30 | return overloaded(fs...); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /test/test_make_overloaded_function.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "nonstd/variant.hpp" 7 | 8 | #include "make_overloaded_function.hpp" 9 | 10 | using var_t = nonstd::variant; 11 | 12 | int main() { 13 | std::vector vec = {var_t(10), var_t(15l), var_t(1.5), var_t("hello")}; 14 | 15 | std::stringstream out; 16 | 17 | for (auto &v : vec) { 18 | nonstd::visit(make_overloaded_function( 19 | [&](int arg) { out << arg << ' '; }, 20 | [&](long arg) { out << arg << "l "; }, 21 | [&](double arg) { out << std::fixed << arg << ' '; }, 22 | [&](const std::string &arg) { out << arg << ' '; }), 23 | v); 24 | } 25 | 26 | std::cout << out.str() << std::endl; 27 | if (out.str() == "10 15l 1.500000 hello ") { 28 | std::cout << "SUCCESS" << std::endl; 29 | return 0; 30 | } else { 31 | std::cout << "FAILURE" << std::endl; 32 | return 1; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /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: -------------------------------------------------------------------------------- 1 | # make_overloaded_function: A single-file header-only library that lets you easily combine lambdas for C++11 and later 2 | 3 | [![Language](https://img.shields.io/badge/C%2B%2B-11%2F14%2F17%2F20-blue)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Latest download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/ligfx/make_overloaded_function/master/include/make_overloaded_function.hpp) 4 | 5 | A single-file header-only library that lets you easily combine lambdas for use with std::visit and polyfills. The [documentation for std::visit](https://en.cppreference.com/w/cpp/utility/variant/visit) gives an example type and function *overloaded*, but it has issues prior to C++17. This library works all the way back to C++11 (when lambdas were introduced), making it a great fit for std::variant polyfill libraries like [variant-lite](https://github.com/martinmoene/variant-lite). 6 | 7 | ## Example usage 8 | 9 | ```c++ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // the variant to visit 16 | using var_t = nonstd::variant; 17 | 18 | std::vector vec = {var_t(10), var_t(15l), var_t(1.5), var_t("hello")}; 19 | 20 | for (auto& v: vec) { 21 | nonstd::visit(make_overloaded_function( 22 | [&](int arg) { out << arg << ' '; }, 23 | [&](long arg) { out << arg << "l "; }, 24 | [&](double arg) { out << std::fixed << arg << ' '; }, 25 | [&](const std::string& arg) { out << arg << ' '; } 26 | ), v); 27 | } 28 | ``` 29 | Output: 30 | ``` 31 | 10 15l 1.500000 hello 32 | ``` 33 | 34 | ## License 35 | 36 | *make_overloaded_function* is distributed under the [Boost Software License](https://github.com/ligfx/make_overloaded_function/blob/master/LICENSE.txt). 37 | 38 | ## Dependencies 39 | 40 | *make_overloaded_function* has no dependencies other than a C++11-compliant compiler. 41 | 42 | [variant-lite](https://github.com/martinmoene/variant-lite) is recommended as a variant implementation for C++11 and C++14. 43 | 44 | ## API 45 | 46 | template
47 | overloaded **make_overloaded_function**(Fs... args); 48 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllArgumentsOnNextLine: true 12 | AllowAllConstructorInitializersOnNextLine: true 13 | AllowAllParametersOfDeclarationOnNextLine: true 14 | AllowShortBlocksOnASingleLine: false 15 | AllowShortCaseLabelsOnASingleLine: false 16 | AllowShortFunctionsOnASingleLine: All 17 | AllowShortLambdasOnASingleLine: All 18 | AllowShortIfStatementsOnASingleLine: Never 19 | AllowShortLoopsOnASingleLine: false 20 | AlwaysBreakAfterDefinitionReturnType: None 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: MultiLine 24 | BinPackArguments: true 25 | BinPackParameters: true 26 | BraceWrapping: 27 | AfterCaseLabel: false 28 | AfterClass: false 29 | AfterControlStatement: false 30 | AfterEnum: false 31 | AfterFunction: false 32 | AfterNamespace: false 33 | AfterObjCDeclaration: false 34 | AfterStruct: false 35 | AfterUnion: false 36 | AfterExternBlock: false 37 | BeforeCatch: false 38 | BeforeElse: false 39 | IndentBraces: false 40 | SplitEmptyFunction: true 41 | SplitEmptyRecord: true 42 | SplitEmptyNamespace: true 43 | BreakBeforeBinaryOperators: None 44 | BreakBeforeBraces: Attach 45 | BreakBeforeInheritanceComma: false 46 | BreakInheritanceList: BeforeColon 47 | BreakBeforeTernaryOperators: true 48 | BreakConstructorInitializersBeforeComma: false 49 | BreakConstructorInitializers: BeforeColon 50 | BreakAfterJavaFieldAnnotations: false 51 | BreakStringLiterals: true 52 | ColumnLimit: 80 53 | CommentPragmas: '^ IWYU pragma:' 54 | CompactNamespaces: false 55 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 56 | ConstructorInitializerIndentWidth: 4 57 | ContinuationIndentWidth: 4 58 | Cpp11BracedListStyle: true 59 | DerivePointerAlignment: false 60 | DisableFormat: false 61 | ExperimentalAutoDetectBinPacking: false 62 | FixNamespaceComments: true 63 | ForEachMacros: 64 | - foreach 65 | - Q_FOREACH 66 | - BOOST_FOREACH 67 | IncludeBlocks: Preserve 68 | IncludeCategories: 69 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 70 | Priority: 2 71 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 72 | Priority: 3 73 | - Regex: '.*' 74 | Priority: 1 75 | IncludeIsMainRegex: '(Test)?$' 76 | IndentCaseLabels: false 77 | IndentPPDirectives: None 78 | IndentWidth: 2 79 | IndentWrappedFunctionNames: false 80 | JavaScriptQuotes: Leave 81 | JavaScriptWrapImports: true 82 | KeepEmptyLinesAtTheStartOfBlocks: true 83 | MacroBlockBegin: '' 84 | MacroBlockEnd: '' 85 | MaxEmptyLinesToKeep: 1 86 | NamespaceIndentation: None 87 | ObjCBinPackProtocolList: Auto 88 | ObjCBlockIndentWidth: 2 89 | ObjCSpaceAfterProperty: false 90 | ObjCSpaceBeforeProtocolList: true 91 | PenaltyBreakAssignment: 2 92 | PenaltyBreakBeforeFirstCallParameter: 19 93 | PenaltyBreakComment: 300 94 | PenaltyBreakFirstLessLess: 120 95 | PenaltyBreakString: 1000 96 | PenaltyBreakTemplateDeclaration: 10 97 | PenaltyExcessCharacter: 1000000 98 | PenaltyReturnTypeOnItsOwnLine: 60 99 | PointerAlignment: Right 100 | ReflowComments: true 101 | SortIncludes: true 102 | SortUsingDeclarations: true 103 | SpaceAfterCStyleCast: false 104 | SpaceAfterLogicalNot: false 105 | SpaceAfterTemplateKeyword: true 106 | SpaceBeforeAssignmentOperators: true 107 | SpaceBeforeCpp11BracedList: false 108 | SpaceBeforeCtorInitializerColon: true 109 | SpaceBeforeInheritanceColon: true 110 | SpaceBeforeParens: ControlStatements 111 | SpaceBeforeRangeBasedForLoopColon: true 112 | SpaceInEmptyParentheses: false 113 | SpacesBeforeTrailingComments: 1 114 | SpacesInAngles: false 115 | SpacesInContainerLiterals: true 116 | SpacesInCStyleCastParentheses: false 117 | SpacesInParentheses: false 118 | SpacesInSquareBrackets: false 119 | Standard: Cpp11 120 | StatementMacros: 121 | - Q_UNUSED 122 | - QT_REQUIRE_VERSION 123 | TabWidth: 8 124 | UseTab: Never 125 | ... 126 | 127 | -------------------------------------------------------------------------------- /test/nonstd/variant.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2018 by Martin Moene 2 | // 3 | // https://github.com/martinmoene/variant-lite 4 | // 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | #pragma once 9 | 10 | #ifndef NONSTD_VARIANT_LITE_HPP 11 | #define NONSTD_VARIANT_LITE_HPP 12 | 13 | #define variant_lite_MAJOR 1 14 | #define variant_lite_MINOR 2 15 | #define variant_lite_PATCH 2 16 | 17 | #define variant_lite_VERSION variant_STRINGIFY(variant_lite_MAJOR) "." variant_STRINGIFY(variant_lite_MINOR) "." variant_STRINGIFY(variant_lite_PATCH) 18 | 19 | #define variant_STRINGIFY( x ) variant_STRINGIFY_( x ) 20 | #define variant_STRINGIFY_( x ) #x 21 | 22 | // variant-lite configuration: 23 | 24 | #define variant_VARIANT_DEFAULT 0 25 | #define variant_VARIANT_NONSTD 1 26 | #define variant_VARIANT_STD 2 27 | 28 | #if !defined( variant_CONFIG_SELECT_VARIANT ) 29 | # define variant_CONFIG_SELECT_VARIANT ( variant_HAVE_STD_VARIANT ? variant_VARIANT_STD : variant_VARIANT_NONSTD ) 30 | #endif 31 | 32 | #ifndef variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 33 | # define variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 0 34 | #endif 35 | 36 | #ifndef variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 37 | # define variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 0 38 | #endif 39 | 40 | // Control presence of exception handling (try and auto discover): 41 | 42 | #ifndef variant_CONFIG_NO_EXCEPTIONS 43 | # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND) 44 | # define variant_CONFIG_NO_EXCEPTIONS 0 45 | # else 46 | # define variant_CONFIG_NO_EXCEPTIONS 1 47 | # endif 48 | #endif 49 | 50 | // C++ language version detection (C++20 is speculative): 51 | // Note: VC14.0/1900 (VS2015) lacks too much from C++14. 52 | 53 | #ifndef variant_CPLUSPLUS 54 | # if defined(_MSVC_LANG ) && !defined(__clang__) 55 | # define variant_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG ) 56 | # else 57 | # define variant_CPLUSPLUS __cplusplus 58 | # endif 59 | #endif 60 | 61 | #define variant_CPP98_OR_GREATER ( variant_CPLUSPLUS >= 199711L ) 62 | #define variant_CPP11_OR_GREATER ( variant_CPLUSPLUS >= 201103L ) 63 | #define variant_CPP11_OR_GREATER_ ( variant_CPLUSPLUS >= 201103L ) 64 | #define variant_CPP14_OR_GREATER ( variant_CPLUSPLUS >= 201402L ) 65 | #define variant_CPP17_OR_GREATER ( variant_CPLUSPLUS >= 201703L ) 66 | #define variant_CPP20_OR_GREATER ( variant_CPLUSPLUS >= 202000L ) 67 | 68 | // Use C++17 std::variant if available and requested: 69 | 70 | #if variant_CPP17_OR_GREATER && defined(__has_include ) 71 | # if __has_include( ) 72 | # define variant_HAVE_STD_VARIANT 1 73 | # else 74 | # define variant_HAVE_STD_VARIANT 0 75 | # endif 76 | #else 77 | # define variant_HAVE_STD_VARIANT 0 78 | #endif 79 | 80 | #define variant_USES_STD_VARIANT ( (variant_CONFIG_SELECT_VARIANT == variant_VARIANT_STD) || ((variant_CONFIG_SELECT_VARIANT == variant_VARIANT_DEFAULT) && variant_HAVE_STD_VARIANT) ) 81 | 82 | // 83 | // in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite: 84 | // 85 | 86 | #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES 87 | #define nonstd_lite_HAVE_IN_PLACE_TYPES 1 88 | 89 | // C++17 std::in_place in : 90 | 91 | #if variant_CPP17_OR_GREATER 92 | 93 | #include 94 | 95 | namespace nonstd { 96 | 97 | using std::in_place; 98 | using std::in_place_type; 99 | using std::in_place_index; 100 | using std::in_place_t; 101 | using std::in_place_type_t; 102 | using std::in_place_index_t; 103 | 104 | #define nonstd_lite_in_place_t( T) std::in_place_t 105 | #define nonstd_lite_in_place_type_t( T) std::in_place_type_t 106 | #define nonstd_lite_in_place_index_t(K) std::in_place_index_t 107 | 108 | #define nonstd_lite_in_place( T) std::in_place_t{} 109 | #define nonstd_lite_in_place_type( T) std::in_place_type_t{} 110 | #define nonstd_lite_in_place_index(K) std::in_place_index_t{} 111 | 112 | } // namespace nonstd 113 | 114 | #else // variant_CPP17_OR_GREATER 115 | 116 | #include 117 | 118 | namespace nonstd { 119 | namespace detail { 120 | 121 | template< class T > 122 | struct in_place_type_tag {}; 123 | 124 | template< std::size_t K > 125 | struct in_place_index_tag {}; 126 | 127 | } // namespace detail 128 | 129 | struct in_place_t {}; 130 | 131 | template< class T > 132 | inline in_place_t in_place( detail::in_place_type_tag = detail::in_place_type_tag() ) 133 | { 134 | return in_place_t(); 135 | } 136 | 137 | template< std::size_t K > 138 | inline in_place_t in_place( detail::in_place_index_tag = detail::in_place_index_tag() ) 139 | { 140 | return in_place_t(); 141 | } 142 | 143 | template< class T > 144 | inline in_place_t in_place_type( detail::in_place_type_tag = detail::in_place_type_tag() ) 145 | { 146 | return in_place_t(); 147 | } 148 | 149 | template< std::size_t K > 150 | inline in_place_t in_place_index( detail::in_place_index_tag = detail::in_place_index_tag() ) 151 | { 152 | return in_place_t(); 153 | } 154 | 155 | // mimic templated typedef: 156 | 157 | #define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) 158 | #define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag ) 159 | #define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag ) 160 | 161 | #define nonstd_lite_in_place( T) nonstd::in_place_type 162 | #define nonstd_lite_in_place_type( T) nonstd::in_place_type 163 | #define nonstd_lite_in_place_index(K) nonstd::in_place_index 164 | 165 | } // namespace nonstd 166 | 167 | #endif // variant_CPP17_OR_GREATER 168 | #endif // nonstd_lite_HAVE_IN_PLACE_TYPES 169 | 170 | // 171 | // Use C++17 std::variant: 172 | // 173 | 174 | #if variant_USES_STD_VARIANT 175 | 176 | #include // std::hash<> 177 | #include 178 | 179 | #if ! variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 180 | # define variant_size_V(T) nonstd::variant_size::value 181 | #endif 182 | 183 | #if ! variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 184 | # define variant_alternative_T(K,T) typename nonstd::variant_alternative::type 185 | #endif 186 | 187 | namespace nonstd { 188 | 189 | using std::variant; 190 | using std::monostate; 191 | using std::bad_variant_access; 192 | using std::variant_size; 193 | using std::variant_size_v; 194 | using std::variant_alternative; 195 | using std::variant_alternative_t; 196 | using std::hash; 197 | 198 | using std::visit; 199 | using std::holds_alternative; 200 | using std::get; 201 | using std::get_if; 202 | using std::operator==; 203 | using std::operator!=; 204 | using std::operator<; 205 | using std::operator<=; 206 | using std::operator>; 207 | using std::operator>=; 208 | using std::swap; 209 | 210 | constexpr auto variant_npos = std::variant_npos; 211 | } 212 | 213 | #else // variant_USES_STD_VARIANT 214 | 215 | #include 216 | #include 217 | #include 218 | #include 219 | 220 | #if variant_CONFIG_NO_EXCEPTIONS 221 | # include 222 | #else 223 | # include 224 | #endif 225 | 226 | // variant-lite type and visitor argument count configuration (script/generate_header.py): 227 | 228 | #define variant_CONFIG_MAX_TYPE_COUNT 16 229 | #define variant_CONFIG_MAX_VISITOR_ARG_COUNT 5 230 | 231 | // variant-lite alignment configuration: 232 | 233 | #ifndef variant_CONFIG_MAX_ALIGN_HACK 234 | # define variant_CONFIG_MAX_ALIGN_HACK 0 235 | #endif 236 | 237 | #ifndef variant_CONFIG_ALIGN_AS 238 | // no default, used in #if defined() 239 | #endif 240 | 241 | #ifndef variant_CONFIG_ALIGN_AS_FALLBACK 242 | # define variant_CONFIG_ALIGN_AS_FALLBACK double 243 | #endif 244 | 245 | // half-open range [lo..hi): 246 | #define variant_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) ) 247 | 248 | // Compiler versions: 249 | // 250 | // MSVC++ 6.0 _MSC_VER == 1200 variant_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0) 251 | // MSVC++ 7.0 _MSC_VER == 1300 variant_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002) 252 | // MSVC++ 7.1 _MSC_VER == 1310 variant_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) 253 | // MSVC++ 8.0 _MSC_VER == 1400 variant_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005) 254 | // MSVC++ 9.0 _MSC_VER == 1500 variant_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008) 255 | // MSVC++ 10.0 _MSC_VER == 1600 variant_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010) 256 | // MSVC++ 11.0 _MSC_VER == 1700 variant_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) 257 | // MSVC++ 12.0 _MSC_VER == 1800 variant_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) 258 | // MSVC++ 14.0 _MSC_VER == 1900 variant_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) 259 | // MSVC++ 14.1 _MSC_VER >= 1910 variant_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017) 260 | // MSVC++ 14.2 _MSC_VER >= 1920 variant_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019) 261 | 262 | #if defined(_MSC_VER ) && !defined(__clang__) 263 | # define variant_COMPILER_MSVC_VER (_MSC_VER ) 264 | # define variant_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) ) 265 | #else 266 | # define variant_COMPILER_MSVC_VER 0 267 | # define variant_COMPILER_MSVC_VERSION 0 268 | #endif 269 | 270 | #define variant_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) ) 271 | 272 | #if defined(__clang__) 273 | # define variant_COMPILER_CLANG_VERSION variant_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) 274 | #else 275 | # define variant_COMPILER_CLANG_VERSION 0 276 | #endif 277 | 278 | #if defined(__GNUC__) && !defined(__clang__) 279 | # define variant_COMPILER_GNUC_VERSION variant_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 280 | #else 281 | # define variant_COMPILER_GNUC_VERSION 0 282 | #endif 283 | 284 | #if variant_BETWEEN( variant_COMPILER_MSVC_VER, 1300, 1900 ) 285 | # pragma warning( push ) 286 | # pragma warning( disable: 4345 ) // initialization behavior changed 287 | #endif 288 | 289 | // Presence of language and library features: 290 | 291 | #define variant_HAVE( feature ) ( variant_HAVE_##feature ) 292 | 293 | #ifdef _HAS_CPP0X 294 | # define variant_HAS_CPP0X _HAS_CPP0X 295 | #else 296 | # define variant_HAS_CPP0X 0 297 | #endif 298 | 299 | // Unless defined otherwise below, consider VC14 as C++11 for variant-lite: 300 | 301 | #if variant_COMPILER_MSVC_VER >= 1900 302 | # undef variant_CPP11_OR_GREATER 303 | # define variant_CPP11_OR_GREATER 1 304 | #endif 305 | 306 | #define variant_CPP11_90 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1500) 307 | #define variant_CPP11_100 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1600) 308 | #define variant_CPP11_110 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1700) 309 | #define variant_CPP11_120 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1800) 310 | #define variant_CPP11_140 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1900) 311 | #define variant_CPP11_141 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1910) 312 | 313 | #define variant_CPP14_000 (variant_CPP14_OR_GREATER) 314 | #define variant_CPP17_000 (variant_CPP17_OR_GREATER) 315 | 316 | // Presence of C++11 language features: 317 | 318 | #define variant_HAVE_CONSTEXPR_11 variant_CPP11_140 319 | #define variant_HAVE_INITIALIZER_LIST variant_CPP11_120 320 | #define variant_HAVE_NOEXCEPT variant_CPP11_140 321 | #define variant_HAVE_NULLPTR variant_CPP11_100 322 | #define variant_HAVE_OVERRIDE variant_CPP11_140 323 | 324 | // Presence of C++14 language features: 325 | 326 | #define variant_HAVE_CONSTEXPR_14 variant_CPP14_000 327 | 328 | // Presence of C++17 language features: 329 | 330 | // no flag 331 | 332 | // Presence of C++ library features: 333 | 334 | #define variant_HAVE_CONDITIONAL variant_CPP11_120 335 | #define variant_HAVE_REMOVE_CV variant_CPP11_120 336 | #define variant_HAVE_STD_ADD_POINTER variant_CPP11_90 337 | #define variant_HAVE_TYPE_TRAITS variant_CPP11_90 338 | 339 | #define variant_HAVE_TR1_TYPE_TRAITS (!! variant_COMPILER_GNUC_VERSION ) 340 | #define variant_HAVE_TR1_ADD_POINTER (!! variant_COMPILER_GNUC_VERSION ) 341 | 342 | // C++ feature usage: 343 | 344 | #if variant_HAVE_CONSTEXPR_11 345 | # define variant_constexpr constexpr 346 | #else 347 | # define variant_constexpr /*constexpr*/ 348 | #endif 349 | 350 | #if variant_HAVE_CONSTEXPR_14 351 | # define variant_constexpr14 constexpr 352 | #else 353 | # define variant_constexpr14 /*constexpr*/ 354 | #endif 355 | 356 | #if variant_HAVE_NOEXCEPT 357 | # define variant_noexcept noexcept 358 | #else 359 | # define variant_noexcept /*noexcept*/ 360 | #endif 361 | 362 | #if variant_HAVE_NULLPTR 363 | # define variant_nullptr nullptr 364 | #else 365 | # define variant_nullptr NULL 366 | #endif 367 | 368 | #if variant_HAVE_OVERRIDE 369 | # define variant_override override 370 | #else 371 | # define variant_override /*override*/ 372 | #endif 373 | 374 | // additional includes: 375 | 376 | #if variant_CPP11_OR_GREATER 377 | # include // std::hash 378 | #endif 379 | 380 | #if variant_HAVE_INITIALIZER_LIST 381 | # include 382 | #endif 383 | 384 | #if variant_HAVE_TYPE_TRAITS 385 | # include 386 | #elif variant_HAVE_TR1_TYPE_TRAITS 387 | # include 388 | #endif 389 | 390 | // Method enabling 391 | 392 | #if variant_CPP11_OR_GREATER 393 | 394 | #define variant_REQUIRES_0(...) \ 395 | template< bool B = (__VA_ARGS__), typename std::enable_if::type = 0 > 396 | 397 | #define variant_REQUIRES_T(...) \ 398 | , typename std::enable_if< (__VA_ARGS__), int >::type = 0 399 | 400 | #define variant_REQUIRES_R(R, ...) \ 401 | typename std::enable_if< (__VA_ARGS__), R>::type 402 | 403 | #define variant_REQUIRES_A(...) \ 404 | , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr 405 | 406 | #endif 407 | 408 | // 409 | // variant: 410 | // 411 | 412 | namespace nonstd { namespace variants { 413 | 414 | // C++11 emulation: 415 | 416 | namespace std11 { 417 | 418 | #if variant_HAVE_STD_ADD_POINTER 419 | 420 | using std::add_pointer; 421 | 422 | #elif variant_HAVE_TR1_ADD_POINTER 423 | 424 | using std::tr1::add_pointer; 425 | 426 | #else 427 | 428 | template< class T > struct remove_reference { typedef T type; }; 429 | template< class T > struct remove_reference { typedef T type; }; 430 | 431 | template< class T > struct add_pointer 432 | { 433 | typedef typename remove_reference::type * type; 434 | }; 435 | 436 | #endif // variant_HAVE_STD_ADD_POINTER 437 | 438 | #if variant_HAVE_REMOVE_CV 439 | 440 | using std::remove_cv; 441 | 442 | #else 443 | 444 | template< class T > struct remove_const { typedef T type; }; 445 | template< class T > struct remove_const { typedef T type; }; 446 | 447 | template< class T > struct remove_volatile { typedef T type; }; 448 | template< class T > struct remove_volatile { typedef T type; }; 449 | 450 | template< class T > 451 | struct remove_cv 452 | { 453 | typedef typename remove_volatile::type>::type type; 454 | }; 455 | 456 | #endif // variant_HAVE_REMOVE_CV 457 | 458 | #if variant_HAVE_CONDITIONAL 459 | 460 | using std::conditional; 461 | 462 | #else 463 | 464 | template< bool Cond, class Then, class Else > 465 | struct conditional; 466 | 467 | template< class Then, class Else > 468 | struct conditional< true , Then, Else > { typedef Then type; }; 469 | 470 | template< class Then, class Else > 471 | struct conditional< false, Then, Else > { typedef Else type; }; 472 | 473 | #endif // variant_HAVE_CONDITIONAL 474 | 475 | } // namespace std11 476 | 477 | /// type traits C++17: 478 | 479 | namespace std17 { 480 | 481 | #if variant_CPP17_OR_GREATER 482 | 483 | using std::is_swappable; 484 | using std::is_nothrow_swappable; 485 | 486 | #elif variant_CPP11_OR_GREATER 487 | 488 | namespace detail { 489 | 490 | using std::swap; 491 | 492 | struct is_swappable 493 | { 494 | template< typename T, typename = decltype( swap( std::declval(), std::declval() ) ) > 495 | static std::true_type test( int ); 496 | 497 | template< typename > 498 | static std::false_type test(...); 499 | }; 500 | 501 | struct is_nothrow_swappable 502 | { 503 | // wrap noexcept(epr) in separate function as work-around for VC140 (VS2015): 504 | 505 | template< typename T > 506 | static constexpr bool test() 507 | { 508 | return noexcept( swap( std::declval(), std::declval() ) ); 509 | } 510 | 511 | template< typename T > 512 | static auto test( int ) -> std::integral_constant()>{} 513 | 514 | template< typename > 515 | static std::false_type test(...); 516 | }; 517 | 518 | } // namespace detail 519 | 520 | // is [nothow] swappable: 521 | 522 | template< typename T > 523 | struct is_swappable : decltype( detail::is_swappable::test(0) ){}; 524 | 525 | template< typename T > 526 | struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test(0) ){}; 527 | 528 | #endif // variant_CPP17_OR_GREATER 529 | 530 | } // namespace std17 531 | 532 | // detail: 533 | 534 | namespace detail { 535 | 536 | // typelist: 537 | 538 | #define variant_TL1( T1 ) detail::typelist< T1, detail::nulltype > 539 | #define variant_TL2( T1, T2) detail::typelist< T1, variant_TL1( T2) > 540 | #define variant_TL3( T1, T2, T3) detail::typelist< T1, variant_TL2( T2, T3) > 541 | #define variant_TL4( T1, T2, T3, T4) detail::typelist< T1, variant_TL3( T2, T3, T4) > 542 | #define variant_TL5( T1, T2, T3, T4, T5) detail::typelist< T1, variant_TL4( T2, T3, T4, T5) > 543 | #define variant_TL6( T1, T2, T3, T4, T5, T6) detail::typelist< T1, variant_TL5( T2, T3, T4, T5, T6) > 544 | #define variant_TL7( T1, T2, T3, T4, T5, T6, T7) detail::typelist< T1, variant_TL6( T2, T3, T4, T5, T6, T7) > 545 | #define variant_TL8( T1, T2, T3, T4, T5, T6, T7, T8) detail::typelist< T1, variant_TL7( T2, T3, T4, T5, T6, T7, T8) > 546 | #define variant_TL9( T1, T2, T3, T4, T5, T6, T7, T8, T9) detail::typelist< T1, variant_TL8( T2, T3, T4, T5, T6, T7, T8, T9) > 547 | #define variant_TL10( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) detail::typelist< T1, variant_TL9( T2, T3, T4, T5, T6, T7, T8, T9, T10) > 548 | #define variant_TL11( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) detail::typelist< T1, variant_TL10( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) > 549 | #define variant_TL12( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) detail::typelist< T1, variant_TL11( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) > 550 | #define variant_TL13( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) detail::typelist< T1, variant_TL12( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) > 551 | #define variant_TL14( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) detail::typelist< T1, variant_TL13( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) > 552 | #define variant_TL15( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) detail::typelist< T1, variant_TL14( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) > 553 | #define variant_TL16( T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) detail::typelist< T1, variant_TL15( T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) > 554 | 555 | 556 | // variant parameter unused type tags: 557 | 558 | template< class T > 559 | struct TX : T 560 | { 561 | inline TX operator+ ( ) const { return TX(); } 562 | inline TX operator- ( ) const { return TX(); } 563 | 564 | inline TX operator! ( ) const { return TX(); } 565 | inline TX operator~ ( ) const { return TX(); } 566 | 567 | inline TX*operator& ( ) const { return variant_nullptr; } 568 | 569 | template< class U > inline TX operator* ( U const & ) const { return TX(); } 570 | template< class U > inline TX operator/ ( U const & ) const { return TX(); } 571 | 572 | template< class U > inline TX operator% ( U const & ) const { return TX(); } 573 | template< class U > inline TX operator+ ( U const & ) const { return TX(); } 574 | template< class U > inline TX operator- ( U const & ) const { return TX(); } 575 | 576 | template< class U > inline TX operator<<( U const & ) const { return TX(); } 577 | template< class U > inline TX operator>>( U const & ) const { return TX(); } 578 | 579 | inline bool operator==( T const & ) const { return false; } 580 | inline bool operator< ( T const & ) const { return false; } 581 | 582 | template< class U > inline TX operator& ( U const & ) const { return TX(); } 583 | template< class U > inline TX operator| ( U const & ) const { return TX(); } 584 | template< class U > inline TX operator^ ( U const & ) const { return TX(); } 585 | 586 | template< class U > inline TX operator&&( U const & ) const { return TX(); } 587 | template< class U > inline TX operator||( U const & ) const { return TX(); } 588 | }; 589 | 590 | struct S0{}; typedef TX T0; 591 | struct S1{}; typedef TX T1; 592 | struct S2{}; typedef TX T2; 593 | struct S3{}; typedef TX T3; 594 | struct S4{}; typedef TX T4; 595 | struct S5{}; typedef TX T5; 596 | struct S6{}; typedef TX T6; 597 | struct S7{}; typedef TX T7; 598 | struct S8{}; typedef TX T8; 599 | struct S9{}; typedef TX T9; 600 | struct S10{}; typedef TX T10; 601 | struct S11{}; typedef TX T11; 602 | struct S12{}; typedef TX T12; 603 | struct S13{}; typedef TX T13; 604 | struct S14{}; typedef TX T14; 605 | struct S15{}; typedef TX T15; 606 | 607 | 608 | struct nulltype{}; 609 | 610 | template< class Head, class Tail > 611 | struct typelist 612 | { 613 | typedef Head head; 614 | typedef Tail tail; 615 | }; 616 | 617 | // typelist max element size: 618 | 619 | template< class List > 620 | struct typelist_max; 621 | 622 | template<> 623 | struct typelist_max< nulltype > 624 | { 625 | enum V { value = 0 } ; 626 | typedef void type; 627 | }; 628 | 629 | template< class Head, class Tail > 630 | struct typelist_max< typelist > 631 | { 632 | private: 633 | enum TV { tail_value = size_t( typelist_max::value ) }; 634 | 635 | typedef typename typelist_max::type tail_type; 636 | 637 | public: 638 | enum V { value = (sizeof( Head ) > tail_value) ? sizeof( Head ) : std::size_t( tail_value ) } ; 639 | 640 | typedef typename std11::conditional< (sizeof( Head ) > tail_value), Head, tail_type>::type type; 641 | }; 642 | 643 | #if variant_CPP11_OR_GREATER 644 | 645 | // typelist max alignof element type: 646 | 647 | template< class List > 648 | struct typelist_max_alignof; 649 | 650 | template<> 651 | struct typelist_max_alignof< nulltype > 652 | { 653 | enum V { value = 0 } ; 654 | }; 655 | 656 | template< class Head, class Tail > 657 | struct typelist_max_alignof< typelist > 658 | { 659 | private: 660 | enum TV { tail_value = size_t( typelist_max_alignof::value ) }; 661 | 662 | public: 663 | enum V { value = (alignof( Head ) > tail_value) ? alignof( Head ) : std::size_t( tail_value ) }; 664 | }; 665 | 666 | #endif 667 | 668 | // typelist size (length): 669 | 670 | template< class List > 671 | struct typelist_size 672 | { 673 | enum V { value = 1 }; 674 | }; 675 | 676 | template<> struct typelist_size< T0 > { enum V { value = 0 }; }; 677 | template<> struct typelist_size< T1 > { enum V { value = 0 }; }; 678 | template<> struct typelist_size< T2 > { enum V { value = 0 }; }; 679 | template<> struct typelist_size< T3 > { enum V { value = 0 }; }; 680 | template<> struct typelist_size< T4 > { enum V { value = 0 }; }; 681 | template<> struct typelist_size< T5 > { enum V { value = 0 }; }; 682 | template<> struct typelist_size< T6 > { enum V { value = 0 }; }; 683 | template<> struct typelist_size< T7 > { enum V { value = 0 }; }; 684 | template<> struct typelist_size< T8 > { enum V { value = 0 }; }; 685 | template<> struct typelist_size< T9 > { enum V { value = 0 }; }; 686 | template<> struct typelist_size< T10 > { enum V { value = 0 }; }; 687 | template<> struct typelist_size< T11 > { enum V { value = 0 }; }; 688 | template<> struct typelist_size< T12 > { enum V { value = 0 }; }; 689 | template<> struct typelist_size< T13 > { enum V { value = 0 }; }; 690 | template<> struct typelist_size< T14 > { enum V { value = 0 }; }; 691 | template<> struct typelist_size< T15 > { enum V { value = 0 }; }; 692 | 693 | 694 | template<> struct typelist_size< nulltype > { enum V { value = 0 } ; }; 695 | 696 | template< class Head, class Tail > 697 | struct typelist_size< typelist > 698 | { 699 | enum V { value = typelist_size::value + typelist_size::value }; 700 | }; 701 | 702 | // typelist index of type: 703 | 704 | template< class List, class T > 705 | struct typelist_index_of; 706 | 707 | template< class T > 708 | struct typelist_index_of< nulltype, T > 709 | { 710 | enum V { value = -1 }; 711 | }; 712 | 713 | template< class Tail, class T > 714 | struct typelist_index_of< typelist, T > 715 | { 716 | enum V { value = 0 }; 717 | }; 718 | 719 | template< class Head, class Tail, class T > 720 | struct typelist_index_of< typelist, T > 721 | { 722 | private: 723 | enum TV { nextVal = typelist_index_of::value }; 724 | 725 | public: 726 | enum V { value = nextVal == -1 ? -1 : 1 + nextVal } ; 727 | }; 728 | 729 | // typelist type at index: 730 | 731 | template< class List, std::size_t i> 732 | struct typelist_type_at; 733 | 734 | template< class Head, class Tail > 735 | struct typelist_type_at< typelist, 0 > 736 | { 737 | typedef Head type; 738 | }; 739 | 740 | template< class Head, class Tail, std::size_t i > 741 | struct typelist_type_at< typelist, i > 742 | { 743 | typedef typename typelist_type_at::type type; 744 | }; 745 | 746 | #if variant_CONFIG_MAX_ALIGN_HACK 747 | 748 | // Max align, use most restricted type for alignment: 749 | 750 | #define variant_UNIQUE( name ) variant_UNIQUE2( name, __LINE__ ) 751 | #define variant_UNIQUE2( name, line ) variant_UNIQUE3( name, line ) 752 | #define variant_UNIQUE3( name, line ) name ## line 753 | 754 | #define variant_ALIGN_TYPE( type ) \ 755 | type variant_UNIQUE( _t ); struct_t< type > variant_UNIQUE( _st ) 756 | 757 | template< class T > 758 | struct struct_t { T _; }; 759 | 760 | union max_align_t 761 | { 762 | variant_ALIGN_TYPE( char ); 763 | variant_ALIGN_TYPE( short int ); 764 | variant_ALIGN_TYPE( int ); 765 | variant_ALIGN_TYPE( long int ); 766 | variant_ALIGN_TYPE( float ); 767 | variant_ALIGN_TYPE( double ); 768 | variant_ALIGN_TYPE( long double ); 769 | variant_ALIGN_TYPE( char * ); 770 | variant_ALIGN_TYPE( short int * ); 771 | variant_ALIGN_TYPE( int * ); 772 | variant_ALIGN_TYPE( long int * ); 773 | variant_ALIGN_TYPE( float * ); 774 | variant_ALIGN_TYPE( double * ); 775 | variant_ALIGN_TYPE( long double * ); 776 | variant_ALIGN_TYPE( void * ); 777 | 778 | #ifdef HAVE_LONG_LONG 779 | variant_ALIGN_TYPE( long long ); 780 | #endif 781 | 782 | struct Unknown; 783 | 784 | Unknown ( * variant_UNIQUE(_) )( Unknown ); 785 | Unknown * Unknown::* variant_UNIQUE(_); 786 | Unknown ( Unknown::* variant_UNIQUE(_) )( Unknown ); 787 | 788 | struct_t< Unknown ( * )( Unknown) > variant_UNIQUE(_); 789 | struct_t< Unknown * Unknown::* > variant_UNIQUE(_); 790 | struct_t< Unknown ( Unknown::* )(Unknown) > variant_UNIQUE(_); 791 | }; 792 | 793 | #undef variant_UNIQUE 794 | #undef variant_UNIQUE2 795 | #undef variant_UNIQUE3 796 | 797 | #undef variant_ALIGN_TYPE 798 | 799 | #elif defined( variant_CONFIG_ALIGN_AS ) // variant_CONFIG_MAX_ALIGN_HACK 800 | 801 | // Use user-specified type for alignment: 802 | 803 | #define variant_ALIGN_AS( unused ) \ 804 | variant_CONFIG_ALIGN_AS 805 | 806 | #else // variant_CONFIG_MAX_ALIGN_HACK 807 | 808 | // Determine POD type to use for alignment: 809 | 810 | #define variant_ALIGN_AS( to_align ) \ 811 | typename detail::type_of_size< detail::alignment_types, detail::alignment_of< to_align >::value >::type 812 | 813 | template< typename T > 814 | struct alignment_of; 815 | 816 | template< typename T > 817 | struct alignment_of_hack 818 | { 819 | char c; 820 | T t; 821 | alignment_of_hack(); 822 | }; 823 | 824 | template< size_t A, size_t S > 825 | struct alignment_logic 826 | { 827 | enum V { value = A < S ? A : S }; 828 | }; 829 | 830 | template< typename T > 831 | struct alignment_of 832 | { 833 | enum V { value = alignment_logic< 834 | sizeof( alignment_of_hack ) - sizeof(T), sizeof(T) >::value }; 835 | }; 836 | 837 | template< typename List, size_t N > 838 | struct type_of_size 839 | { 840 | typedef typename std11::conditional< 841 | N == sizeof( typename List::head ), 842 | typename List::head, 843 | typename type_of_size::type >::type type; 844 | }; 845 | 846 | template< size_t N > 847 | struct type_of_size< nulltype, N > 848 | { 849 | typedef variant_CONFIG_ALIGN_AS_FALLBACK type; 850 | }; 851 | 852 | template< typename T> 853 | struct struct_t { T _; }; 854 | 855 | #define variant_ALIGN_TYPE( type ) \ 856 | typelist< type , typelist< struct_t< type > 857 | 858 | struct Unknown; 859 | 860 | typedef 861 | variant_ALIGN_TYPE( char ), 862 | variant_ALIGN_TYPE( short ), 863 | variant_ALIGN_TYPE( int ), 864 | variant_ALIGN_TYPE( long ), 865 | variant_ALIGN_TYPE( float ), 866 | variant_ALIGN_TYPE( double ), 867 | variant_ALIGN_TYPE( long double ), 868 | 869 | variant_ALIGN_TYPE( char *), 870 | variant_ALIGN_TYPE( short * ), 871 | variant_ALIGN_TYPE( int * ), 872 | variant_ALIGN_TYPE( long * ), 873 | variant_ALIGN_TYPE( float * ), 874 | variant_ALIGN_TYPE( double * ), 875 | variant_ALIGN_TYPE( long double * ), 876 | 877 | variant_ALIGN_TYPE( Unknown ( * )( Unknown ) ), 878 | variant_ALIGN_TYPE( Unknown * Unknown::* ), 879 | variant_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ), 880 | 881 | nulltype 882 | > > > > > > > > > > > > > > 883 | > > > > > > > > > > > > > > 884 | > > > > > > 885 | alignment_types; 886 | 887 | #undef variant_ALIGN_TYPE 888 | 889 | #endif // variant_CONFIG_MAX_ALIGN_HACK 890 | 891 | #if variant_CPP11_OR_GREATER 892 | 893 | template< typename T> 894 | inline std::size_t hash( T const & v ) 895 | { 896 | return std::hash()( v ); 897 | } 898 | 899 | inline std::size_t hash( T0 const & ) { return 0; } 900 | inline std::size_t hash( T1 const & ) { return 0; } 901 | inline std::size_t hash( T2 const & ) { return 0; } 902 | inline std::size_t hash( T3 const & ) { return 0; } 903 | inline std::size_t hash( T4 const & ) { return 0; } 904 | inline std::size_t hash( T5 const & ) { return 0; } 905 | inline std::size_t hash( T6 const & ) { return 0; } 906 | inline std::size_t hash( T7 const & ) { return 0; } 907 | inline std::size_t hash( T8 const & ) { return 0; } 908 | inline std::size_t hash( T9 const & ) { return 0; } 909 | inline std::size_t hash( T10 const & ) { return 0; } 910 | inline std::size_t hash( T11 const & ) { return 0; } 911 | inline std::size_t hash( T12 const & ) { return 0; } 912 | inline std::size_t hash( T13 const & ) { return 0; } 913 | inline std::size_t hash( T14 const & ) { return 0; } 914 | inline std::size_t hash( T15 const & ) { return 0; } 915 | 916 | 917 | #endif // variant_CPP11_OR_GREATER 918 | 919 | 920 | 921 | 922 | 923 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 924 | struct helper 925 | { 926 | typedef signed char type_index_t; 927 | typedef variant_TL16( T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 ) variant_types; 928 | 929 | template< class U > 930 | static U * as( void * data ) 931 | { 932 | return reinterpret_cast( data ); 933 | } 934 | 935 | template< class U > 936 | static U const * as( void const * data ) 937 | { 938 | return reinterpret_cast( data ); 939 | } 940 | 941 | static type_index_t to_index_t( std::size_t index ) 942 | { 943 | return static_cast( index ); 944 | } 945 | 946 | static void destroy( type_index_t index, void * data ) 947 | { 948 | switch ( index ) 949 | { 950 | case 0: as( data )->~T0(); break; 951 | case 1: as( data )->~T1(); break; 952 | case 2: as( data )->~T2(); break; 953 | case 3: as( data )->~T3(); break; 954 | case 4: as( data )->~T4(); break; 955 | case 5: as( data )->~T5(); break; 956 | case 6: as( data )->~T6(); break; 957 | case 7: as( data )->~T7(); break; 958 | case 8: as( data )->~T8(); break; 959 | case 9: as( data )->~T9(); break; 960 | case 10: as( data )->~T10(); break; 961 | case 11: as( data )->~T11(); break; 962 | case 12: as( data )->~T12(); break; 963 | case 13: as( data )->~T13(); break; 964 | case 14: as( data )->~T14(); break; 965 | case 15: as( data )->~T15(); break; 966 | 967 | } 968 | } 969 | 970 | #if variant_CPP11_OR_GREATER 971 | template< class T, class... Args > 972 | static type_index_t construct_t( void * data, Args&&... args ) 973 | { 974 | new( data ) T( std::forward(args)... ); 975 | 976 | return to_index_t( detail::typelist_index_of< variant_types, T>::value ); 977 | } 978 | 979 | template< std::size_t K, class... Args > 980 | static type_index_t construct_i( void * data, Args&&... args ) 981 | { 982 | using type = typename detail::typelist_type_at< variant_types, K >::type; 983 | 984 | construct_t< type >( data, std::forward(args)... ); 985 | 986 | return to_index_t( K ); 987 | } 988 | 989 | static type_index_t move_construct( type_index_t const from_index, void * from_value, void * to_value ) 990 | { 991 | switch ( from_index ) 992 | { 993 | case 0: new( to_value ) T0( std::move( *as( from_value ) ) ); break; 994 | case 1: new( to_value ) T1( std::move( *as( from_value ) ) ); break; 995 | case 2: new( to_value ) T2( std::move( *as( from_value ) ) ); break; 996 | case 3: new( to_value ) T3( std::move( *as( from_value ) ) ); break; 997 | case 4: new( to_value ) T4( std::move( *as( from_value ) ) ); break; 998 | case 5: new( to_value ) T5( std::move( *as( from_value ) ) ); break; 999 | case 6: new( to_value ) T6( std::move( *as( from_value ) ) ); break; 1000 | case 7: new( to_value ) T7( std::move( *as( from_value ) ) ); break; 1001 | case 8: new( to_value ) T8( std::move( *as( from_value ) ) ); break; 1002 | case 9: new( to_value ) T9( std::move( *as( from_value ) ) ); break; 1003 | case 10: new( to_value ) T10( std::move( *as( from_value ) ) ); break; 1004 | case 11: new( to_value ) T11( std::move( *as( from_value ) ) ); break; 1005 | case 12: new( to_value ) T12( std::move( *as( from_value ) ) ); break; 1006 | case 13: new( to_value ) T13( std::move( *as( from_value ) ) ); break; 1007 | case 14: new( to_value ) T14( std::move( *as( from_value ) ) ); break; 1008 | case 15: new( to_value ) T15( std::move( *as( from_value ) ) ); break; 1009 | 1010 | } 1011 | return from_index; 1012 | } 1013 | 1014 | static type_index_t move_assign( type_index_t const from_index, void * from_value, void * to_value ) 1015 | { 1016 | switch ( from_index ) 1017 | { 1018 | case 0: *as( to_value ) = std::move( *as( from_value ) ); break; 1019 | case 1: *as( to_value ) = std::move( *as( from_value ) ); break; 1020 | case 2: *as( to_value ) = std::move( *as( from_value ) ); break; 1021 | case 3: *as( to_value ) = std::move( *as( from_value ) ); break; 1022 | case 4: *as( to_value ) = std::move( *as( from_value ) ); break; 1023 | case 5: *as( to_value ) = std::move( *as( from_value ) ); break; 1024 | case 6: *as( to_value ) = std::move( *as( from_value ) ); break; 1025 | case 7: *as( to_value ) = std::move( *as( from_value ) ); break; 1026 | case 8: *as( to_value ) = std::move( *as( from_value ) ); break; 1027 | case 9: *as( to_value ) = std::move( *as( from_value ) ); break; 1028 | case 10: *as( to_value ) = std::move( *as( from_value ) ); break; 1029 | case 11: *as( to_value ) = std::move( *as( from_value ) ); break; 1030 | case 12: *as( to_value ) = std::move( *as( from_value ) ); break; 1031 | case 13: *as( to_value ) = std::move( *as( from_value ) ); break; 1032 | case 14: *as( to_value ) = std::move( *as( from_value ) ); break; 1033 | case 15: *as( to_value ) = std::move( *as( from_value ) ); break; 1034 | 1035 | } 1036 | return from_index; 1037 | } 1038 | #endif 1039 | 1040 | static type_index_t copy_construct( type_index_t const from_index, const void * from_value, void * to_value ) 1041 | { 1042 | switch ( from_index ) 1043 | { 1044 | case 0: new( to_value ) T0( *as( from_value ) ); break; 1045 | case 1: new( to_value ) T1( *as( from_value ) ); break; 1046 | case 2: new( to_value ) T2( *as( from_value ) ); break; 1047 | case 3: new( to_value ) T3( *as( from_value ) ); break; 1048 | case 4: new( to_value ) T4( *as( from_value ) ); break; 1049 | case 5: new( to_value ) T5( *as( from_value ) ); break; 1050 | case 6: new( to_value ) T6( *as( from_value ) ); break; 1051 | case 7: new( to_value ) T7( *as( from_value ) ); break; 1052 | case 8: new( to_value ) T8( *as( from_value ) ); break; 1053 | case 9: new( to_value ) T9( *as( from_value ) ); break; 1054 | case 10: new( to_value ) T10( *as( from_value ) ); break; 1055 | case 11: new( to_value ) T11( *as( from_value ) ); break; 1056 | case 12: new( to_value ) T12( *as( from_value ) ); break; 1057 | case 13: new( to_value ) T13( *as( from_value ) ); break; 1058 | case 14: new( to_value ) T14( *as( from_value ) ); break; 1059 | case 15: new( to_value ) T15( *as( from_value ) ); break; 1060 | 1061 | } 1062 | return from_index; 1063 | } 1064 | 1065 | static type_index_t copy_assign( type_index_t const from_index, const void * from_value, void * to_value ) 1066 | { 1067 | switch ( from_index ) 1068 | { 1069 | case 0: *as( to_value ) = *as( from_value ); break; 1070 | case 1: *as( to_value ) = *as( from_value ); break; 1071 | case 2: *as( to_value ) = *as( from_value ); break; 1072 | case 3: *as( to_value ) = *as( from_value ); break; 1073 | case 4: *as( to_value ) = *as( from_value ); break; 1074 | case 5: *as( to_value ) = *as( from_value ); break; 1075 | case 6: *as( to_value ) = *as( from_value ); break; 1076 | case 7: *as( to_value ) = *as( from_value ); break; 1077 | case 8: *as( to_value ) = *as( from_value ); break; 1078 | case 9: *as( to_value ) = *as( from_value ); break; 1079 | case 10: *as( to_value ) = *as( from_value ); break; 1080 | case 11: *as( to_value ) = *as( from_value ); break; 1081 | case 12: *as( to_value ) = *as( from_value ); break; 1082 | case 13: *as( to_value ) = *as( from_value ); break; 1083 | case 14: *as( to_value ) = *as( from_value ); break; 1084 | case 15: *as( to_value ) = *as( from_value ); break; 1085 | 1086 | } 1087 | return from_index; 1088 | } 1089 | }; 1090 | 1091 | } // namespace detail 1092 | 1093 | // 1094 | // Variant: 1095 | // 1096 | 1097 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1098 | class variant; 1099 | 1100 | // 19.7.8 Class monostate 1101 | 1102 | class monostate{}; 1103 | 1104 | // 19.7.9 monostate relational operators 1105 | 1106 | inline variant_constexpr bool operator< ( monostate, monostate ) variant_noexcept { return false; } 1107 | inline variant_constexpr bool operator> ( monostate, monostate ) variant_noexcept { return false; } 1108 | inline variant_constexpr bool operator<=( monostate, monostate ) variant_noexcept { return true; } 1109 | inline variant_constexpr bool operator>=( monostate, monostate ) variant_noexcept { return true; } 1110 | inline variant_constexpr bool operator==( monostate, monostate ) variant_noexcept { return true; } 1111 | inline variant_constexpr bool operator!=( monostate, monostate ) variant_noexcept { return false; } 1112 | 1113 | // 19.7.4 variant helper classes 1114 | 1115 | // obtain the size of the variant's list of alternatives at compile time 1116 | 1117 | template< class T > 1118 | struct variant_size; /* undefined */ 1119 | 1120 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1121 | struct variant_size< variant > 1122 | { 1123 | enum _ { value = detail::typelist_size< variant_TL16(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) >::value }; 1124 | }; 1125 | 1126 | #if variant_CPP14_OR_GREATER 1127 | template< class T > 1128 | constexpr std::size_t variant_size_v = variant_size::value; 1129 | #endif 1130 | 1131 | #if ! variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 1132 | # define variant_size_V(T) nonstd::variant_size::value 1133 | #endif 1134 | 1135 | // obtain the type of the alternative specified by its index, at compile time: 1136 | 1137 | template< std::size_t K, class T > 1138 | struct variant_alternative; /* undefined */ 1139 | 1140 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1141 | struct variant_alternative< K, variant > 1142 | { 1143 | typedef typename detail::typelist_type_at::type type; 1144 | }; 1145 | 1146 | #if variant_CPP11_OR_GREATER 1147 | template< std::size_t K, class T > 1148 | using variant_alternative_t = typename variant_alternative::type; 1149 | #endif 1150 | 1151 | #if ! variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 1152 | # define variant_alternative_T(K,T) typename nonstd::variant_alternative::type 1153 | #endif 1154 | 1155 | // NTS:implement specializes the std::uses_allocator type trait 1156 | // std::uses_allocator 1157 | 1158 | // index of the variant in the invalid state (constant) 1159 | 1160 | #if variant_CPP11_OR_GREATER 1161 | variant_constexpr std::size_t variant_npos = static_cast( -1 ); 1162 | #else 1163 | static const std::size_t variant_npos = static_cast( -1 ); 1164 | #endif 1165 | 1166 | #if ! variant_CONFIG_NO_EXCEPTIONS 1167 | 1168 | // 19.7.11 Class bad_variant_access 1169 | 1170 | class bad_variant_access : public std::exception 1171 | { 1172 | public: 1173 | #if variant_CPP11_OR_GREATER 1174 | virtual const char* what() const variant_noexcept variant_override 1175 | #else 1176 | virtual const char* what() const throw() 1177 | #endif 1178 | { 1179 | return "bad variant access"; 1180 | } 1181 | }; 1182 | 1183 | #endif // variant_CONFIG_NO_EXCEPTIONS 1184 | 1185 | // 19.7.3 Class template variant 1186 | 1187 | template< 1188 | class T0, 1189 | class T1 = detail::T1, 1190 | class T2 = detail::T2, 1191 | class T3 = detail::T3, 1192 | class T4 = detail::T4, 1193 | class T5 = detail::T5, 1194 | class T6 = detail::T6, 1195 | class T7 = detail::T7, 1196 | class T8 = detail::T8, 1197 | class T9 = detail::T9, 1198 | class T10 = detail::T10, 1199 | class T11 = detail::T11, 1200 | class T12 = detail::T12, 1201 | class T13 = detail::T13, 1202 | class T14 = detail::T14, 1203 | class T15 = detail::T15 1204 | > 1205 | class variant 1206 | { 1207 | typedef detail::helper< T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 > helper_type; 1208 | typedef variant_TL16( T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 ) variant_types; 1209 | 1210 | public: 1211 | // 19.7.3.1 Constructors 1212 | 1213 | variant() : type_index( 0 ) { new( ptr() ) T0(); } 1214 | 1215 | variant( T0 const & t0 ) : type_index( 0 ) { new( ptr() ) T0( t0 ); } 1216 | variant( T1 const & t1 ) : type_index( 1 ) { new( ptr() ) T1( t1 ); } 1217 | variant( T2 const & t2 ) : type_index( 2 ) { new( ptr() ) T2( t2 ); } 1218 | variant( T3 const & t3 ) : type_index( 3 ) { new( ptr() ) T3( t3 ); } 1219 | variant( T4 const & t4 ) : type_index( 4 ) { new( ptr() ) T4( t4 ); } 1220 | variant( T5 const & t5 ) : type_index( 5 ) { new( ptr() ) T5( t5 ); } 1221 | variant( T6 const & t6 ) : type_index( 6 ) { new( ptr() ) T6( t6 ); } 1222 | variant( T7 const & t7 ) : type_index( 7 ) { new( ptr() ) T7( t7 ); } 1223 | variant( T8 const & t8 ) : type_index( 8 ) { new( ptr() ) T8( t8 ); } 1224 | variant( T9 const & t9 ) : type_index( 9 ) { new( ptr() ) T9( t9 ); } 1225 | variant( T10 const & t10 ) : type_index( 10 ) { new( ptr() ) T10( t10 ); } 1226 | variant( T11 const & t11 ) : type_index( 11 ) { new( ptr() ) T11( t11 ); } 1227 | variant( T12 const & t12 ) : type_index( 12 ) { new( ptr() ) T12( t12 ); } 1228 | variant( T13 const & t13 ) : type_index( 13 ) { new( ptr() ) T13( t13 ); } 1229 | variant( T14 const & t14 ) : type_index( 14 ) { new( ptr() ) T14( t14 ); } 1230 | variant( T15 const & t15 ) : type_index( 15 ) { new( ptr() ) T15( t15 ); } 1231 | 1232 | 1233 | #if variant_CPP11_OR_GREATER 1234 | variant( T0 && t0 ) : type_index( 0 ) { new( ptr() ) T0( std::move(t0) ); } 1235 | variant( T1 && t1 ) : type_index( 1 ) { new( ptr() ) T1( std::move(t1) ); } 1236 | variant( T2 && t2 ) : type_index( 2 ) { new( ptr() ) T2( std::move(t2) ); } 1237 | variant( T3 && t3 ) : type_index( 3 ) { new( ptr() ) T3( std::move(t3) ); } 1238 | variant( T4 && t4 ) : type_index( 4 ) { new( ptr() ) T4( std::move(t4) ); } 1239 | variant( T5 && t5 ) : type_index( 5 ) { new( ptr() ) T5( std::move(t5) ); } 1240 | variant( T6 && t6 ) : type_index( 6 ) { new( ptr() ) T6( std::move(t6) ); } 1241 | variant( T7 && t7 ) : type_index( 7 ) { new( ptr() ) T7( std::move(t7) ); } 1242 | variant( T8 && t8 ) : type_index( 8 ) { new( ptr() ) T8( std::move(t8) ); } 1243 | variant( T9 && t9 ) : type_index( 9 ) { new( ptr() ) T9( std::move(t9) ); } 1244 | variant( T10 && t10 ) : type_index( 10 ) { new( ptr() ) T10( std::move(t10) ); } 1245 | variant( T11 && t11 ) : type_index( 11 ) { new( ptr() ) T11( std::move(t11) ); } 1246 | variant( T12 && t12 ) : type_index( 12 ) { new( ptr() ) T12( std::move(t12) ); } 1247 | variant( T13 && t13 ) : type_index( 13 ) { new( ptr() ) T13( std::move(t13) ); } 1248 | variant( T14 && t14 ) : type_index( 14 ) { new( ptr() ) T14( std::move(t14) ); } 1249 | variant( T15 && t15 ) : type_index( 15 ) { new( ptr() ) T15( std::move(t15) ); } 1250 | 1251 | #endif 1252 | 1253 | variant(variant const & other) 1254 | : type_index( other.type_index ) 1255 | { 1256 | (void) helper_type::copy_construct( other.type_index, other.ptr(), ptr() ); 1257 | } 1258 | 1259 | #if variant_CPP11_OR_GREATER 1260 | 1261 | variant( variant && other ) noexcept( 1262 | std::is_nothrow_move_constructible::value && 1263 | std::is_nothrow_move_constructible::value && 1264 | std::is_nothrow_move_constructible::value && 1265 | std::is_nothrow_move_constructible::value && 1266 | std::is_nothrow_move_constructible::value && 1267 | std::is_nothrow_move_constructible::value && 1268 | std::is_nothrow_move_constructible::value && 1269 | std::is_nothrow_move_constructible::value && 1270 | std::is_nothrow_move_constructible::value && 1271 | std::is_nothrow_move_constructible::value && 1272 | std::is_nothrow_move_constructible::value && 1273 | std::is_nothrow_move_constructible::value && 1274 | std::is_nothrow_move_constructible::value && 1275 | std::is_nothrow_move_constructible::value && 1276 | std::is_nothrow_move_constructible::value && 1277 | std::is_nothrow_move_constructible::value) 1278 | : type_index( other.type_index ) 1279 | { 1280 | (void) helper_type::move_construct( other.type_index, other.ptr(), ptr() ); 1281 | } 1282 | 1283 | template< std::size_t K > 1284 | using type_at_t = typename detail::typelist_type_at< variant_types, K >::type; 1285 | 1286 | template< class T, class... Args 1287 | variant_REQUIRES_T( std::is_constructible< T, Args...>::value ) 1288 | > 1289 | explicit variant( nonstd_lite_in_place_type_t(T), Args&&... args) 1290 | { 1291 | type_index = variant_npos_internal(); 1292 | type_index = helper_type::template construct_t( ptr(), std::forward(args)... ); 1293 | } 1294 | 1295 | template< class T, class U, class... Args 1296 | variant_REQUIRES_T( std::is_constructible< T, std::initializer_list&, Args...>::value ) 1297 | > 1298 | explicit variant( nonstd_lite_in_place_type_t(T), std::initializer_list il, Args&&... args ) 1299 | { 1300 | type_index = variant_npos_internal(); 1301 | type_index = helper_type::template construct_t( ptr(), il, std::forward(args)... ); 1302 | } 1303 | 1304 | template< std::size_t K, class... Args 1305 | variant_REQUIRES_T( std::is_constructible< type_at_t, Args...>::value ) 1306 | > 1307 | explicit variant( nonstd_lite_in_place_index_t(K), Args&&... args ) 1308 | { 1309 | type_index = variant_npos_internal(); 1310 | type_index = helper_type::template construct_i( ptr(), std::forward(args)... ); 1311 | } 1312 | 1313 | template< size_t K, class U, class... Args 1314 | variant_REQUIRES_T( std::is_constructible< type_at_t, std::initializer_list&, Args...>::value ) 1315 | > 1316 | explicit variant( nonstd_lite_in_place_index_t(K), std::initializer_list il, Args&&... args ) 1317 | { 1318 | type_index = variant_npos_internal(); 1319 | type_index = helper_type::template construct_i( ptr(), il, std::forward(args)... ); 1320 | } 1321 | 1322 | #endif // variant_CPP11_OR_GREATER 1323 | 1324 | // 19.7.3.2 Destructor 1325 | 1326 | ~variant() 1327 | { 1328 | if ( ! valueless_by_exception() ) 1329 | { 1330 | helper_type::destroy( type_index, ptr() ); 1331 | } 1332 | } 1333 | 1334 | // 19.7.3.3 Assignment 1335 | 1336 | variant & operator=( variant const & other ) 1337 | { 1338 | return copy_assign( other ); 1339 | } 1340 | 1341 | #if variant_CPP11_OR_GREATER 1342 | 1343 | variant & operator=( variant && other ) noexcept( 1344 | std::is_nothrow_move_assignable::value && 1345 | std::is_nothrow_move_assignable::value && 1346 | std::is_nothrow_move_assignable::value && 1347 | std::is_nothrow_move_assignable::value && 1348 | std::is_nothrow_move_assignable::value && 1349 | std::is_nothrow_move_assignable::value && 1350 | std::is_nothrow_move_assignable::value && 1351 | std::is_nothrow_move_assignable::value && 1352 | std::is_nothrow_move_assignable::value && 1353 | std::is_nothrow_move_assignable::value && 1354 | std::is_nothrow_move_assignable::value && 1355 | std::is_nothrow_move_assignable::value && 1356 | std::is_nothrow_move_assignable::value && 1357 | std::is_nothrow_move_assignable::value && 1358 | std::is_nothrow_move_assignable::value && 1359 | std::is_nothrow_move_assignable::value) 1360 | { 1361 | return move_assign( std::move( other ) ); 1362 | } 1363 | 1364 | variant & operator=( T0 && t0 ) { return assign_value<0>( std::move( t0 ) ); } 1365 | variant & operator=( T1 && t1 ) { return assign_value<1>( std::move( t1 ) ); } 1366 | variant & operator=( T2 && t2 ) { return assign_value<2>( std::move( t2 ) ); } 1367 | variant & operator=( T3 && t3 ) { return assign_value<3>( std::move( t3 ) ); } 1368 | variant & operator=( T4 && t4 ) { return assign_value<4>( std::move( t4 ) ); } 1369 | variant & operator=( T5 && t5 ) { return assign_value<5>( std::move( t5 ) ); } 1370 | variant & operator=( T6 && t6 ) { return assign_value<6>( std::move( t6 ) ); } 1371 | variant & operator=( T7 && t7 ) { return assign_value<7>( std::move( t7 ) ); } 1372 | variant & operator=( T8 && t8 ) { return assign_value<8>( std::move( t8 ) ); } 1373 | variant & operator=( T9 && t9 ) { return assign_value<9>( std::move( t9 ) ); } 1374 | variant & operator=( T10 && t10 ) { return assign_value<10>( std::move( t10 ) ); } 1375 | variant & operator=( T11 && t11 ) { return assign_value<11>( std::move( t11 ) ); } 1376 | variant & operator=( T12 && t12 ) { return assign_value<12>( std::move( t12 ) ); } 1377 | variant & operator=( T13 && t13 ) { return assign_value<13>( std::move( t13 ) ); } 1378 | variant & operator=( T14 && t14 ) { return assign_value<14>( std::move( t14 ) ); } 1379 | variant & operator=( T15 && t15 ) { return assign_value<15>( std::move( t15 ) ); } 1380 | 1381 | 1382 | #endif 1383 | 1384 | variant & operator=( T0 const & t0 ) { return assign_value<0>( t0 ); } 1385 | variant & operator=( T1 const & t1 ) { return assign_value<1>( t1 ); } 1386 | variant & operator=( T2 const & t2 ) { return assign_value<2>( t2 ); } 1387 | variant & operator=( T3 const & t3 ) { return assign_value<3>( t3 ); } 1388 | variant & operator=( T4 const & t4 ) { return assign_value<4>( t4 ); } 1389 | variant & operator=( T5 const & t5 ) { return assign_value<5>( t5 ); } 1390 | variant & operator=( T6 const & t6 ) { return assign_value<6>( t6 ); } 1391 | variant & operator=( T7 const & t7 ) { return assign_value<7>( t7 ); } 1392 | variant & operator=( T8 const & t8 ) { return assign_value<8>( t8 ); } 1393 | variant & operator=( T9 const & t9 ) { return assign_value<9>( t9 ); } 1394 | variant & operator=( T10 const & t10 ) { return assign_value<10>( t10 ); } 1395 | variant & operator=( T11 const & t11 ) { return assign_value<11>( t11 ); } 1396 | variant & operator=( T12 const & t12 ) { return assign_value<12>( t12 ); } 1397 | variant & operator=( T13 const & t13 ) { return assign_value<13>( t13 ); } 1398 | variant & operator=( T14 const & t14 ) { return assign_value<14>( t14 ); } 1399 | variant & operator=( T15 const & t15 ) { return assign_value<15>( t15 ); } 1400 | 1401 | 1402 | std::size_t index() const 1403 | { 1404 | return variant_npos_internal() == type_index ? variant_npos : static_cast( type_index ); 1405 | } 1406 | 1407 | // 19.7.3.4 Modifiers 1408 | 1409 | #if variant_CPP11_OR_GREATER 1410 | template< class T, class... Args 1411 | variant_REQUIRES_T( std::is_constructible< T, Args...>::value ) 1412 | > 1413 | T& emplace( Args&&... args ) 1414 | { 1415 | helper_type::destroy( type_index, ptr() ); 1416 | type_index = variant_npos_internal(); 1417 | type_index = helper_type::template construct_t( ptr(), std::forward(args)... ); 1418 | 1419 | return *as(); 1420 | } 1421 | 1422 | template< class T, class U, class... Args 1423 | variant_REQUIRES_T( std::is_constructible< T, std::initializer_list&, Args...>::value ) 1424 | > 1425 | T& emplace( std::initializer_list il, Args&&... args ) 1426 | { 1427 | helper_type::destroy( type_index, ptr() ); 1428 | type_index = variant_npos_internal(); 1429 | type_index = helper_type::template construct_t( ptr(), il, std::forward(args)... ); 1430 | 1431 | return *as(); 1432 | } 1433 | 1434 | template< size_t K, class... Args 1435 | variant_REQUIRES_T( std::is_constructible< type_at_t, Args...>::value ) 1436 | > 1437 | variant_alternative_t & emplace( Args&&... args ) 1438 | { 1439 | return this->template emplace< type_at_t >( std::forward(args)... ); 1440 | } 1441 | 1442 | template< size_t K, class U, class... Args 1443 | variant_REQUIRES_T( std::is_constructible< type_at_t, std::initializer_list&, Args...>::value ) 1444 | > 1445 | variant_alternative_t & emplace( std::initializer_list il, Args&&... args ) 1446 | { 1447 | return this->template emplace< type_at_t >( il, std::forward(args)... ); 1448 | } 1449 | 1450 | #endif // variant_CPP11_OR_GREATER 1451 | 1452 | // 19.7.3.5 Value status 1453 | 1454 | bool valueless_by_exception() const 1455 | { 1456 | return type_index == variant_npos_internal(); 1457 | } 1458 | 1459 | // 19.7.3.6 Swap 1460 | 1461 | void swap( variant & other ) 1462 | #if variant_CPP11_OR_GREATER 1463 | noexcept( 1464 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1465 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1466 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1467 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1468 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1469 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1470 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1471 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1472 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1473 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1474 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1475 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1476 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1477 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1478 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value && 1479 | std::is_nothrow_move_constructible::value && std17::is_nothrow_swappable::value 1480 | 1481 | ) 1482 | #endif 1483 | { 1484 | if ( valueless_by_exception() && other.valueless_by_exception() ) 1485 | { 1486 | // no effect 1487 | } 1488 | else if ( type_index == other.type_index ) 1489 | { 1490 | this->swap_value( type_index, other ); 1491 | } 1492 | else 1493 | { 1494 | #if variant_CPP11_OR_GREATER 1495 | variant tmp( std::move( *this ) ); 1496 | *this = std::move( other ); 1497 | other = std::move( tmp ); 1498 | #else 1499 | variant tmp( *this ); 1500 | *this = other; 1501 | other = tmp; 1502 | #endif 1503 | } 1504 | } 1505 | 1506 | // 1507 | // non-standard: 1508 | // 1509 | 1510 | template< class T > 1511 | static variant_constexpr std::size_t index_of() variant_noexcept 1512 | { 1513 | return to_size_t( detail::typelist_index_of::type >::value ); 1514 | } 1515 | 1516 | template< class T > 1517 | T & get() 1518 | { 1519 | const std::size_t i = index_of(); 1520 | 1521 | #if variant_CONFIG_NO_EXCEPTIONS 1522 | assert( i == index() ); 1523 | #else 1524 | if ( i != index() ) 1525 | { 1526 | throw bad_variant_access(); 1527 | } 1528 | #endif 1529 | return *as(); 1530 | } 1531 | 1532 | template< class T > 1533 | T const & get() const 1534 | { 1535 | const std::size_t i = index_of(); 1536 | 1537 | #if variant_CONFIG_NO_EXCEPTIONS 1538 | assert( i == index() ); 1539 | #else 1540 | if ( i != index() ) 1541 | { 1542 | throw bad_variant_access(); 1543 | } 1544 | #endif 1545 | return *as(); 1546 | } 1547 | 1548 | template< std::size_t K > 1549 | typename variant_alternative< K, variant >::type & 1550 | get() 1551 | { 1552 | return this->template get< typename detail::typelist_type_at< variant_types, K >::type >(); 1553 | } 1554 | 1555 | template< std::size_t K > 1556 | typename variant_alternative< K, variant >::type const & 1557 | get() const 1558 | { 1559 | return this->template get< typename detail::typelist_type_at< variant_types, K >::type >(); 1560 | } 1561 | 1562 | private: 1563 | typedef typename helper_type::type_index_t type_index_t; 1564 | 1565 | void * ptr() variant_noexcept 1566 | { 1567 | return &data; 1568 | } 1569 | 1570 | void const * ptr() const variant_noexcept 1571 | { 1572 | return &data; 1573 | } 1574 | 1575 | template< class U > 1576 | U * as() 1577 | { 1578 | return reinterpret_cast( ptr() ); 1579 | } 1580 | 1581 | template< class U > 1582 | U const * as() const 1583 | { 1584 | return reinterpret_cast( ptr() ); 1585 | } 1586 | 1587 | template< class U > 1588 | static variant_constexpr std::size_t to_size_t( U index ) 1589 | { 1590 | return static_cast( index ); 1591 | } 1592 | 1593 | variant_constexpr type_index_t variant_npos_internal() const variant_noexcept 1594 | { 1595 | return static_cast( -1 ); 1596 | } 1597 | 1598 | variant & copy_assign( variant const & other ) 1599 | { 1600 | if ( valueless_by_exception() && other.valueless_by_exception() ) 1601 | { 1602 | // no effect 1603 | } 1604 | else if ( ! valueless_by_exception() && other.valueless_by_exception() ) 1605 | { 1606 | helper_type::destroy( type_index, ptr() ); 1607 | type_index = variant_npos_internal(); 1608 | } 1609 | else if ( index() == other.index() ) 1610 | { 1611 | type_index = helper_type::copy_assign( other.type_index, other.ptr(), ptr() ); 1612 | } 1613 | else 1614 | { 1615 | helper_type::destroy( type_index, ptr() ); 1616 | type_index = variant_npos_internal(); 1617 | type_index = helper_type::copy_construct( other.type_index, other.ptr(), ptr() ); 1618 | } 1619 | return *this; 1620 | } 1621 | 1622 | #if variant_CPP11_OR_GREATER 1623 | 1624 | variant & move_assign( variant && other ) 1625 | { 1626 | if ( valueless_by_exception() && other.valueless_by_exception() ) 1627 | { 1628 | // no effect 1629 | } 1630 | else if ( ! valueless_by_exception() && other.valueless_by_exception() ) 1631 | { 1632 | helper_type::destroy( type_index, ptr() ); 1633 | type_index = variant_npos_internal(); 1634 | } 1635 | else if ( index() == other.index() ) 1636 | { 1637 | type_index = helper_type::move_assign( other.type_index, other.ptr(), ptr() ); 1638 | } 1639 | else 1640 | { 1641 | helper_type::destroy( type_index, ptr() ); 1642 | type_index = variant_npos_internal(); 1643 | type_index = helper_type::move_construct( other.type_index, other.ptr(), ptr() ); 1644 | } 1645 | return *this; 1646 | } 1647 | 1648 | template< std::size_t K, class T > 1649 | variant & assign_value( T && value ) 1650 | { 1651 | if( index() == K ) 1652 | { 1653 | *as() = std::forward( value ); 1654 | } 1655 | else 1656 | { 1657 | helper_type::destroy( type_index, ptr() ); 1658 | type_index = variant_npos_internal(); 1659 | new( ptr() ) T( std::forward( value ) ); 1660 | type_index = K; 1661 | } 1662 | return *this; 1663 | } 1664 | 1665 | #endif // variant_CPP11_OR_GREATER 1666 | 1667 | template< std::size_t K, class T > 1668 | variant & assign_value( T const & value ) 1669 | { 1670 | if( index() == K ) 1671 | { 1672 | *as() = value; 1673 | } 1674 | else 1675 | { 1676 | helper_type::destroy( type_index, ptr() ); 1677 | type_index = variant_npos_internal(); 1678 | new( ptr() ) T( value ); 1679 | type_index = K; 1680 | } 1681 | return *this; 1682 | } 1683 | 1684 | void swap_value( type_index_t index, variant & other ) 1685 | { 1686 | using std::swap; 1687 | switch( index ) 1688 | { 1689 | case 0: swap( this->get<0>(), other.get<0>() ); break; 1690 | case 1: swap( this->get<1>(), other.get<1>() ); break; 1691 | case 2: swap( this->get<2>(), other.get<2>() ); break; 1692 | case 3: swap( this->get<3>(), other.get<3>() ); break; 1693 | case 4: swap( this->get<4>(), other.get<4>() ); break; 1694 | case 5: swap( this->get<5>(), other.get<5>() ); break; 1695 | case 6: swap( this->get<6>(), other.get<6>() ); break; 1696 | case 7: swap( this->get<7>(), other.get<7>() ); break; 1697 | case 8: swap( this->get<8>(), other.get<8>() ); break; 1698 | case 9: swap( this->get<9>(), other.get<9>() ); break; 1699 | case 10: swap( this->get<10>(), other.get<10>() ); break; 1700 | case 11: swap( this->get<11>(), other.get<11>() ); break; 1701 | case 12: swap( this->get<12>(), other.get<12>() ); break; 1702 | case 13: swap( this->get<13>(), other.get<13>() ); break; 1703 | case 14: swap( this->get<14>(), other.get<14>() ); break; 1704 | case 15: swap( this->get<15>(), other.get<15>() ); break; 1705 | 1706 | } 1707 | } 1708 | 1709 | private: 1710 | enum { data_size = detail::typelist_max< variant_types >::value }; 1711 | 1712 | #if variant_CPP11_OR_GREATER 1713 | 1714 | enum { data_align = detail::typelist_max_alignof< variant_types >::value }; 1715 | 1716 | using aligned_storage_t = typename std::aligned_storage< data_size, data_align >::type; 1717 | aligned_storage_t data; 1718 | 1719 | #elif variant_CONFIG_MAX_ALIGN_HACK 1720 | 1721 | typedef union { unsigned char data[ data_size ]; } aligned_storage_t; 1722 | 1723 | detail::max_align_t hack; 1724 | aligned_storage_t data; 1725 | 1726 | #else 1727 | typedef typename detail::typelist_max< variant_types >::type max_type; 1728 | 1729 | typedef variant_ALIGN_AS( max_type ) align_as_type; 1730 | 1731 | typedef union { align_as_type data[ 1 + ( data_size - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t; 1732 | aligned_storage_t data; 1733 | 1734 | // # undef variant_ALIGN_AS 1735 | 1736 | #endif // variant_CONFIG_MAX_ALIGN_HACK 1737 | 1738 | type_index_t type_index; 1739 | }; 1740 | 1741 | // 19.7.5 Value access 1742 | 1743 | template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1744 | inline bool holds_alternative( variant const & v ) variant_noexcept 1745 | { 1746 | return v.index() == variant::template index_of(); 1747 | } 1748 | 1749 | template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1750 | inline R & get( variant & v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) ) 1751 | { 1752 | return v.template get(); 1753 | } 1754 | 1755 | template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1756 | inline R const & get( variant const & v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) ) 1757 | { 1758 | return v.template get(); 1759 | } 1760 | 1761 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1762 | inline typename variant_alternative< K, variant >::type & 1763 | get( variant & v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1764 | { 1765 | #if variant_CONFIG_NO_EXCEPTIONS 1766 | assert( K == v.index() ); 1767 | #else 1768 | if ( K != v.index() ) 1769 | { 1770 | throw bad_variant_access(); 1771 | } 1772 | #endif 1773 | return v.template get(); 1774 | } 1775 | 1776 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1777 | inline typename variant_alternative< K, variant >::type const & 1778 | get( variant const & v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1779 | { 1780 | #if variant_CONFIG_NO_EXCEPTIONS 1781 | assert( K == v.index() ); 1782 | #else 1783 | if ( K != v.index() ) 1784 | { 1785 | throw bad_variant_access(); 1786 | } 1787 | #endif 1788 | return v.template get(); 1789 | } 1790 | 1791 | #if variant_CPP11_OR_GREATER 1792 | 1793 | template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1794 | inline R && get( variant && v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) ) 1795 | { 1796 | return std::move(v.template get()); 1797 | } 1798 | 1799 | template< class R, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1800 | inline R const && get( variant const && v, nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R) ) 1801 | { 1802 | return std::move(v.template get()); 1803 | } 1804 | 1805 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1806 | inline typename variant_alternative< K, variant >::type && 1807 | get( variant && v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1808 | { 1809 | #if variant_CONFIG_NO_EXCEPTIONS 1810 | assert( K == v.index() ); 1811 | #else 1812 | if ( K != v.index() ) 1813 | { 1814 | throw bad_variant_access(); 1815 | } 1816 | #endif 1817 | return std::move(v.template get()); 1818 | } 1819 | 1820 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1821 | inline typename variant_alternative< K, variant >::type const && 1822 | get( variant const && v, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1823 | { 1824 | #if variant_CONFIG_NO_EXCEPTIONS 1825 | assert( K == v.index() ); 1826 | #else 1827 | if ( K != v.index() ) 1828 | { 1829 | throw bad_variant_access(); 1830 | } 1831 | #endif 1832 | return std::move(v.template get()); 1833 | } 1834 | 1835 | #endif // variant_CPP11_OR_GREATER 1836 | 1837 | template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1838 | inline typename std11::add_pointer::type 1839 | get_if( variant * pv, nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T) ) 1840 | { 1841 | return ( pv->index() == variant::template index_of() ) ? &get( *pv ) : variant_nullptr; 1842 | } 1843 | 1844 | template< class T, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1845 | inline typename std11::add_pointer::type 1846 | get_if( variant const * pv, nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T)) 1847 | { 1848 | return ( pv->index() == variant::template index_of() ) ? &get( *pv ) : variant_nullptr; 1849 | } 1850 | 1851 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1852 | inline typename std11::add_pointer< typename variant_alternative >::type >::type 1853 | get_if( variant * pv, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1854 | { 1855 | return ( pv->index() == K ) ? &get( *pv ) : variant_nullptr; 1856 | } 1857 | 1858 | template< std::size_t K, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 1859 | inline typename std11::add_pointer< const typename variant_alternative >::type >::type 1860 | get_if( variant const * pv, nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K) ) 1861 | { 1862 | return ( pv->index() == K ) ? &get( *pv ) : variant_nullptr; 1863 | } 1864 | 1865 | // 19.7.10 Specialized algorithms 1866 | 1867 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 1868 | #if variant_CPP11_OR_GREATER 1869 | variant_REQUIRES_T( 1870 | std::is_move_constructible::value && std17::is_swappable::value && 1871 | std::is_move_constructible::value && std17::is_swappable::value && 1872 | std::is_move_constructible::value && std17::is_swappable::value && 1873 | std::is_move_constructible::value && std17::is_swappable::value && 1874 | std::is_move_constructible::value && std17::is_swappable::value && 1875 | std::is_move_constructible::value && std17::is_swappable::value && 1876 | std::is_move_constructible::value && std17::is_swappable::value && 1877 | std::is_move_constructible::value && std17::is_swappable::value && 1878 | std::is_move_constructible::value && std17::is_swappable::value && 1879 | std::is_move_constructible::value && std17::is_swappable::value && 1880 | std::is_move_constructible::value && std17::is_swappable::value && 1881 | std::is_move_constructible::value && std17::is_swappable::value && 1882 | std::is_move_constructible::value && std17::is_swappable::value && 1883 | std::is_move_constructible::value && std17::is_swappable::value && 1884 | std::is_move_constructible::value && std17::is_swappable::value && 1885 | std::is_move_constructible::value && std17::is_swappable::value 1886 | ) 1887 | #endif 1888 | > 1889 | inline void swap( 1890 | variant & a, 1891 | variant & b ) 1892 | #if variant_CPP11_OR_GREATER 1893 | noexcept( noexcept( a.swap( b ) ) ) 1894 | #endif 1895 | { 1896 | a.swap( b ); 1897 | } 1898 | 1899 | // 19.7.7 Visitation 1900 | 1901 | // Variant 'visitor' implementation 1902 | 1903 | namespace detail 1904 | { 1905 | 1906 | template< typename R, typename VT > 1907 | struct VisitorApplicatorImpl 1908 | { 1909 | template< typename Visitor, typename T > 1910 | static R apply(Visitor const& v, T const& arg) 1911 | { 1912 | return v(arg); 1913 | } 1914 | }; 1915 | 1916 | template< typename R, typename VT > 1917 | struct VisitorApplicatorImpl > 1918 | { 1919 | template< typename Visitor, typename T > 1920 | static R apply(Visitor const&, T) 1921 | { 1922 | return R(); 1923 | } 1924 | }; 1925 | 1926 | template 1927 | struct VisitorApplicator; 1928 | 1929 | template< typename R, typename Visitor, typename V1 > 1930 | struct VisitorUnwrapper; 1931 | 1932 | #if variant_CPP11_OR_GREATER 1933 | template< size_t NumVars, typename R, typename Visitor, typename ... T > 1934 | #else 1935 | template< size_t NumVars, typename R, typename Visitor, typename T1, typename T2 = S0, typename T3 = S0, typename T4 = S0, typename T5 = S0 > 1936 | #endif 1937 | struct TypedVisitorUnwrapper; 1938 | 1939 | template< typename R, typename Visitor, typename T2 > 1940 | struct TypedVisitorUnwrapper<2, R, Visitor, T2> 1941 | { 1942 | const Visitor& visitor; 1943 | T2 const& val2; 1944 | 1945 | TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_) 1946 | : visitor(visitor_) 1947 | , val2(val2_) 1948 | 1949 | { 1950 | } 1951 | 1952 | template 1953 | R operator()(const T& val1) const 1954 | { 1955 | return visitor(val1, val2); 1956 | } 1957 | }; 1958 | 1959 | template< typename R, typename Visitor, typename T2, typename T3 > 1960 | struct TypedVisitorUnwrapper<3, R, Visitor, T2, T3> 1961 | { 1962 | const Visitor& visitor; 1963 | T2 const& val2; 1964 | T3 const& val3; 1965 | 1966 | TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_) 1967 | : visitor(visitor_) 1968 | , val2(val2_) 1969 | , val3(val3_) 1970 | 1971 | { 1972 | } 1973 | 1974 | template 1975 | R operator()(const T& val1) const 1976 | { 1977 | return visitor(val1, val2, val3); 1978 | } 1979 | }; 1980 | 1981 | template< typename R, typename Visitor, typename T2, typename T3, typename T4 > 1982 | struct TypedVisitorUnwrapper<4, R, Visitor, T2, T3, T4> 1983 | { 1984 | const Visitor& visitor; 1985 | T2 const& val2; 1986 | T3 const& val3; 1987 | T4 const& val4; 1988 | 1989 | TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_, T4 const& val4_) 1990 | : visitor(visitor_) 1991 | , val2(val2_) 1992 | , val3(val3_) 1993 | , val4(val4_) 1994 | 1995 | { 1996 | } 1997 | 1998 | template 1999 | R operator()(const T& val1) const 2000 | { 2001 | return visitor(val1, val2, val3, val4); 2002 | } 2003 | }; 2004 | 2005 | template< typename R, typename Visitor, typename T2, typename T3, typename T4, typename T5 > 2006 | struct TypedVisitorUnwrapper<5, R, Visitor, T2, T3, T4, T5> 2007 | { 2008 | const Visitor& visitor; 2009 | T2 const& val2; 2010 | T3 const& val3; 2011 | T4 const& val4; 2012 | T5 const& val5; 2013 | 2014 | TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_, T3 const& val3_, T4 const& val4_, T5 const& val5_) 2015 | : visitor(visitor_) 2016 | , val2(val2_) 2017 | , val3(val3_) 2018 | , val4(val4_) 2019 | , val5(val5_) 2020 | 2021 | { 2022 | } 2023 | 2024 | template 2025 | R operator()(const T& val1) const 2026 | { 2027 | return visitor(val1, val2, val3, val4, val5); 2028 | } 2029 | }; 2030 | 2031 | 2032 | 2033 | template 2034 | struct VisitorUnwrapper 2035 | { 2036 | const Visitor& visitor; 2037 | const V2& r; 2038 | 2039 | VisitorUnwrapper(const Visitor& visitor_, const V2& r_) 2040 | : visitor(visitor_) 2041 | , r(r_) 2042 | { 2043 | } 2044 | 2045 | 2046 | template< typename T1 > 2047 | R operator()(T1 const& val1) const 2048 | { 2049 | typedef TypedVisitorUnwrapper<2, R, Visitor, T1> visitor_type; 2050 | return VisitorApplicator::apply(visitor_type(visitor, val1), r); 2051 | } 2052 | 2053 | template< typename T1, typename T2 > 2054 | R operator()(T1 const& val1, T2 const& val2) const 2055 | { 2056 | typedef TypedVisitorUnwrapper<3, R, Visitor, T1, T2> visitor_type; 2057 | return VisitorApplicator::apply(visitor_type(visitor, val1, val2), r); 2058 | } 2059 | 2060 | template< typename T1, typename T2, typename T3 > 2061 | R operator()(T1 const& val1, T2 const& val2, T3 const& val3) const 2062 | { 2063 | typedef TypedVisitorUnwrapper<4, R, Visitor, T1, T2, T3> visitor_type; 2064 | return VisitorApplicator::apply(visitor_type(visitor, val1, val2, val3), r); 2065 | } 2066 | 2067 | template< typename T1, typename T2, typename T3, typename T4 > 2068 | R operator()(T1 const& val1, T2 const& val2, T3 const& val3, T4 const& val4) const 2069 | { 2070 | typedef TypedVisitorUnwrapper<5, R, Visitor, T1, T2, T3, T4> visitor_type; 2071 | return VisitorApplicator::apply(visitor_type(visitor, val1, val2, val3, val4), r); 2072 | } 2073 | 2074 | template< typename T1, typename T2, typename T3, typename T4, typename T5 > 2075 | R operator()(T1 const& val1, T2 const& val2, T3 const& val3, T4 const& val4, T5 const& val5) const 2076 | { 2077 | typedef TypedVisitorUnwrapper<6, R, Visitor, T1, T2, T3, T4, T5> visitor_type; 2078 | return VisitorApplicator::apply(visitor_type(visitor, val1, val2, val3, val4, val5), r); 2079 | } 2080 | 2081 | }; 2082 | 2083 | 2084 | template 2085 | struct VisitorApplicator 2086 | { 2087 | template 2088 | static R apply(const Visitor& v, const V1& arg) 2089 | { 2090 | switch( arg.index() ) 2091 | { 2092 | case 0: return apply_visitor<0>(v, arg); 2093 | case 1: return apply_visitor<1>(v, arg); 2094 | case 2: return apply_visitor<2>(v, arg); 2095 | case 3: return apply_visitor<3>(v, arg); 2096 | case 4: return apply_visitor<4>(v, arg); 2097 | case 5: return apply_visitor<5>(v, arg); 2098 | case 6: return apply_visitor<6>(v, arg); 2099 | case 7: return apply_visitor<7>(v, arg); 2100 | case 8: return apply_visitor<8>(v, arg); 2101 | case 9: return apply_visitor<9>(v, arg); 2102 | case 10: return apply_visitor<10>(v, arg); 2103 | case 11: return apply_visitor<11>(v, arg); 2104 | case 12: return apply_visitor<12>(v, arg); 2105 | case 13: return apply_visitor<13>(v, arg); 2106 | case 14: return apply_visitor<14>(v, arg); 2107 | case 15: return apply_visitor<15>(v, arg); 2108 | 2109 | default: return R(); 2110 | } 2111 | } 2112 | 2113 | template 2114 | static R apply_visitor(const Visitor& v, const V1& arg) 2115 | { 2116 | 2117 | #if variant_CPP11_OR_GREATER 2118 | typedef typename variant_alternative::type>::type value_type; 2119 | #else 2120 | typedef typename variant_alternative::type value_type; 2121 | #endif 2122 | return VisitorApplicatorImpl::apply(v, get(arg)); 2123 | } 2124 | 2125 | #if variant_CPP11_OR_GREATER 2126 | template 2127 | static R apply(const Visitor& v, const V1& arg1, const V2& arg2, const V ... args) 2128 | { 2129 | typedef VisitorUnwrapper Unwrapper; 2130 | Unwrapper unwrapper(v, arg1); 2131 | return apply(unwrapper, arg2, args ...); 2132 | } 2133 | #else 2134 | 2135 | template< typename Visitor, typename V1, typename V2 > 2136 | static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2) 2137 | { 2138 | typedef VisitorUnwrapper Unwrapper; 2139 | Unwrapper unwrapper(v, arg1); 2140 | return apply(unwrapper, arg2); 2141 | } 2142 | 2143 | template< typename Visitor, typename V1, typename V2, typename V3 > 2144 | static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3) 2145 | { 2146 | typedef VisitorUnwrapper Unwrapper; 2147 | Unwrapper unwrapper(v, arg1); 2148 | return apply(unwrapper, arg2, arg3); 2149 | } 2150 | 2151 | template< typename Visitor, typename V1, typename V2, typename V3, typename V4 > 2152 | static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4) 2153 | { 2154 | typedef VisitorUnwrapper Unwrapper; 2155 | Unwrapper unwrapper(v, arg1); 2156 | return apply(unwrapper, arg2, arg3, arg4); 2157 | } 2158 | 2159 | template< typename Visitor, typename V1, typename V2, typename V3, typename V4, typename V5 > 2160 | static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4, V5 const& arg5) 2161 | { 2162 | typedef VisitorUnwrapper Unwrapper; 2163 | Unwrapper unwrapper(v, arg1); 2164 | return apply(unwrapper, arg2, arg3, arg4, arg5); 2165 | } 2166 | 2167 | #endif 2168 | }; 2169 | 2170 | #if variant_CPP11_OR_GREATER 2171 | template< size_t NumVars, typename Visitor, typename ... V > 2172 | struct VisitorImpl 2173 | { 2174 | typedef decltype(std::declval()(get<0>(static_cast(std::declval()))...)) result_type; 2175 | typedef VisitorApplicator applicator_type; 2176 | }; 2177 | #endif 2178 | } // detail 2179 | 2180 | #if variant_CPP11_OR_GREATER 2181 | // No perfect forwarding here in order to simplify code 2182 | template< typename Visitor, typename ... V > 2183 | inline auto visit(Visitor const& v, V const& ... vars) -> typename detail::VisitorImpl ::result_type 2184 | { 2185 | typedef detail::VisitorImpl impl_type; 2186 | return impl_type::applicator_type::apply(v, vars...); 2187 | } 2188 | #else 2189 | 2190 | template< typename R, typename Visitor, typename V1 > 2191 | inline R visit(const Visitor& v, V1 const& arg1) 2192 | { 2193 | return detail::VisitorApplicator::apply(v, arg1); 2194 | } 2195 | 2196 | template< typename R, typename Visitor, typename V1, typename V2 > 2197 | inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2) 2198 | { 2199 | return detail::VisitorApplicator::apply(v, arg1, arg2); 2200 | } 2201 | 2202 | template< typename R, typename Visitor, typename V1, typename V2, typename V3 > 2203 | inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3) 2204 | { 2205 | return detail::VisitorApplicator::apply(v, arg1, arg2, arg3); 2206 | } 2207 | 2208 | template< typename R, typename Visitor, typename V1, typename V2, typename V3, typename V4 > 2209 | inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4) 2210 | { 2211 | return detail::VisitorApplicator::apply(v, arg1, arg2, arg3, arg4); 2212 | } 2213 | 2214 | template< typename R, typename Visitor, typename V1, typename V2, typename V3, typename V4, typename V5 > 2215 | inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3, V4 const& arg4, V5 const& arg5) 2216 | { 2217 | return detail::VisitorApplicator::apply(v, arg1, arg2, arg3, arg4, arg5); 2218 | } 2219 | 2220 | #endif 2221 | 2222 | // 19.7.6 Relational operators 2223 | 2224 | namespace detail { 2225 | 2226 | template< class Variant > 2227 | struct Comparator 2228 | { 2229 | static inline bool equal( Variant const & v, Variant const & w ) 2230 | { 2231 | switch( v.index() ) 2232 | { 2233 | case 0: return get<0>( v ) == get<0>( w ); 2234 | case 1: return get<1>( v ) == get<1>( w ); 2235 | case 2: return get<2>( v ) == get<2>( w ); 2236 | case 3: return get<3>( v ) == get<3>( w ); 2237 | case 4: return get<4>( v ) == get<4>( w ); 2238 | case 5: return get<5>( v ) == get<5>( w ); 2239 | case 6: return get<6>( v ) == get<6>( w ); 2240 | case 7: return get<7>( v ) == get<7>( w ); 2241 | case 8: return get<8>( v ) == get<8>( w ); 2242 | case 9: return get<9>( v ) == get<9>( w ); 2243 | case 10: return get<10>( v ) == get<10>( w ); 2244 | case 11: return get<11>( v ) == get<11>( w ); 2245 | case 12: return get<12>( v ) == get<12>( w ); 2246 | case 13: return get<13>( v ) == get<13>( w ); 2247 | case 14: return get<14>( v ) == get<14>( w ); 2248 | case 15: return get<15>( v ) == get<15>( w ); 2249 | 2250 | default: return false; 2251 | } 2252 | } 2253 | 2254 | static inline bool less_than( Variant const & v, Variant const & w ) 2255 | { 2256 | switch( v.index() ) 2257 | { 2258 | case 0: return get<0>( v ) < get<0>( w ); 2259 | case 1: return get<1>( v ) < get<1>( w ); 2260 | case 2: return get<2>( v ) < get<2>( w ); 2261 | case 3: return get<3>( v ) < get<3>( w ); 2262 | case 4: return get<4>( v ) < get<4>( w ); 2263 | case 5: return get<5>( v ) < get<5>( w ); 2264 | case 6: return get<6>( v ) < get<6>( w ); 2265 | case 7: return get<7>( v ) < get<7>( w ); 2266 | case 8: return get<8>( v ) < get<8>( w ); 2267 | case 9: return get<9>( v ) < get<9>( w ); 2268 | case 10: return get<10>( v ) < get<10>( w ); 2269 | case 11: return get<11>( v ) < get<11>( w ); 2270 | case 12: return get<12>( v ) < get<12>( w ); 2271 | case 13: return get<13>( v ) < get<13>( w ); 2272 | case 14: return get<14>( v ) < get<14>( w ); 2273 | case 15: return get<15>( v ) < get<15>( w ); 2274 | 2275 | default: return false; 2276 | } 2277 | } 2278 | }; 2279 | 2280 | } //namespace detail 2281 | 2282 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2283 | inline bool operator==( 2284 | variant const & v, 2285 | variant const & w ) 2286 | { 2287 | if ( v.index() != w.index() ) return false; 2288 | else if ( v.valueless_by_exception() ) return true; 2289 | else return detail::Comparator< variant >::equal( v, w ); 2290 | } 2291 | 2292 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2293 | inline bool operator!=( 2294 | variant const & v, 2295 | variant const & w ) 2296 | { 2297 | return ! ( v == w ); 2298 | } 2299 | 2300 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2301 | inline bool operator<( 2302 | variant const & v, 2303 | variant const & w ) 2304 | { 2305 | if ( w.valueless_by_exception() ) return false; 2306 | else if ( v.valueless_by_exception() ) return true; 2307 | else if ( v.index() < w.index() ) return true; 2308 | else if ( v.index() > w.index() ) return false; 2309 | else return detail::Comparator< variant >::less_than( v, w ); 2310 | } 2311 | 2312 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2313 | inline bool operator>( 2314 | variant const & v, 2315 | variant const & w ) 2316 | { 2317 | return w < v; 2318 | } 2319 | 2320 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2321 | inline bool operator<=( 2322 | variant const & v, 2323 | variant const & w ) 2324 | { 2325 | return ! ( v > w ); 2326 | } 2327 | 2328 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2329 | inline bool operator>=( 2330 | variant const & v, 2331 | variant const & w ) 2332 | { 2333 | return ! ( v < w ); 2334 | } 2335 | 2336 | } // namespace variants 2337 | 2338 | using namespace variants; 2339 | 2340 | } // namespace nonstd 2341 | 2342 | #if variant_CPP11_OR_GREATER 2343 | 2344 | // 19.7.12 Hash support 2345 | 2346 | namespace std { 2347 | 2348 | template<> 2349 | struct hash< nonstd::monostate > 2350 | { 2351 | std::size_t operator()( nonstd::monostate ) const variant_noexcept 2352 | { 2353 | return 42; 2354 | } 2355 | }; 2356 | 2357 | template< class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15 > 2358 | struct hash< nonstd::variant > 2359 | { 2360 | std::size_t operator()( nonstd::variant const & v ) const variant_noexcept 2361 | { 2362 | namespace nvd = nonstd::variants::detail; 2363 | 2364 | switch( v.index() ) 2365 | { 2366 | case 0: return nvd::hash( 0 ) ^ nvd::hash( get<0>( v ) ); 2367 | case 1: return nvd::hash( 1 ) ^ nvd::hash( get<1>( v ) ); 2368 | case 2: return nvd::hash( 2 ) ^ nvd::hash( get<2>( v ) ); 2369 | case 3: return nvd::hash( 3 ) ^ nvd::hash( get<3>( v ) ); 2370 | case 4: return nvd::hash( 4 ) ^ nvd::hash( get<4>( v ) ); 2371 | case 5: return nvd::hash( 5 ) ^ nvd::hash( get<5>( v ) ); 2372 | case 6: return nvd::hash( 6 ) ^ nvd::hash( get<6>( v ) ); 2373 | case 7: return nvd::hash( 7 ) ^ nvd::hash( get<7>( v ) ); 2374 | case 8: return nvd::hash( 8 ) ^ nvd::hash( get<8>( v ) ); 2375 | case 9: return nvd::hash( 9 ) ^ nvd::hash( get<9>( v ) ); 2376 | case 10: return nvd::hash( 10 ) ^ nvd::hash( get<10>( v ) ); 2377 | case 11: return nvd::hash( 11 ) ^ nvd::hash( get<11>( v ) ); 2378 | case 12: return nvd::hash( 12 ) ^ nvd::hash( get<12>( v ) ); 2379 | case 13: return nvd::hash( 13 ) ^ nvd::hash( get<13>( v ) ); 2380 | case 14: return nvd::hash( 14 ) ^ nvd::hash( get<14>( v ) ); 2381 | case 15: return nvd::hash( 15 ) ^ nvd::hash( get<15>( v ) ); 2382 | 2383 | default: return 0; 2384 | } 2385 | } 2386 | }; 2387 | 2388 | } //namespace std 2389 | 2390 | #endif // variant_CPP11_OR_GREATER 2391 | 2392 | #if variant_BETWEEN( variant_COMPILER_MSVC_VER, 1300, 1900 ) 2393 | # pragma warning( pop ) 2394 | #endif 2395 | 2396 | #endif // variant_USES_STD_VARIANT 2397 | 2398 | #endif // NONSTD_VARIANT_LITE_HPP 2399 | --------------------------------------------------------------------------------