├── doc ├── .gitignore ├── variant2-docinfo-footer.html ├── variant2 │ ├── copyright.adoc │ ├── implementation.adoc │ └── changelog.adoc ├── Jamfile └── variant2.adoc ├── test ├── quick.cpp ├── CMakeLists.txt ├── throw_exception.cpp ├── cmake_install_test │ └── CMakeLists.txt ├── variant_derived_construct.cpp ├── cmake_subdir_test │ └── CMakeLists.txt ├── variant_value_construct_cx_2.cpp ├── variant_default_construct_cx_2.cpp ├── variant_value_construct_cx_3.cpp ├── variant_default_construct_cx_4.cpp ├── variant_default_construct_cx_3.cpp ├── variant_ostream_insert.cpp ├── variant_visit_cx.cpp ├── variant_holds_alternative_cx.cpp ├── variant_move_assign_throw.cpp ├── variant_copy_assign_throw.cpp ├── variant_default_construct_cx_5.cpp ├── variant_visit_r_cx.cpp ├── variant_default_construct_cx.cpp ├── variant_value_construct_cx_4.cpp ├── variant_derived_construct2.cpp ├── variant_json_value_from.cpp ├── variant_json_value_to.cpp ├── variant_copy_construct_throw.cpp ├── variant_move_construct_throw.cpp ├── variant_uses_double_storage.cpp ├── variant_visit_cx_2.cpp ├── is_output_streamable.cpp ├── variant_visit_derived.cpp ├── variant_convert_construct_throw.cpp ├── variant_index_type.cpp ├── variant_emplace_type_cx.cpp ├── variant_holds_alternative.cpp ├── variant_get_by_type_cx.cpp ├── variant_hash.cpp ├── variant_lt_gt.cpp ├── variant_value_assign_cx.cpp ├── variant_move_construct_cx.cpp ├── variant_trivial.cpp ├── variant_many_types.cpp ├── variant_eq_ne.cpp ├── variant_get_by_index_cx.cpp ├── variant_copy_construct_cx.cpp ├── variant_move_assign_cx.cpp ├── variant_visit_r.cpp ├── variant_eq_ne_cx.cpp ├── variant_lt_gt_cx.cpp ├── variant_value_construct_cx.cpp ├── variant_special.cpp ├── variant_copy_assign_cx.cpp ├── variant_default_construct.cpp ├── variant_value_construct.cpp ├── variant_in_place_type_construct_cx.cpp ├── variant_in_place_index_construct_cx.cpp ├── variant_emplace_index_cx.cpp ├── variant_in_place_type_construct.cpp ├── variant_in_place_index_construct.cpp ├── variant_visit_by_index.cpp ├── variant_move_construct.cpp ├── variant_visit.cpp ├── variant_copy_construct.cpp ├── variant_size.cpp ├── variant_subset.cpp ├── variant_destroy.cpp ├── variant_convert_construct.cpp ├── Jamfile ├── variant_emplace_type.cpp ├── variant_value_assign.cpp ├── variant_copy_assign.cpp └── variant_move_assign.cpp ├── include └── boost │ └── variant2.hpp ├── meta └── libraries.json ├── index.html ├── README.md ├── .drone ├── drone.bat └── drone.sh ├── CMakeLists.txt ├── benchmark ├── benchmark2.cpp ├── benchmark1.cpp └── benchmark2.md ├── .gitattributes └── appveyor.yml /doc/.gitignore: -------------------------------------------------------------------------------- 1 | /pdf/ 2 | /html/ 3 | -------------------------------------------------------------------------------- /doc/variant2-docinfo-footer.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /test/quick.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | using namespace boost::variant2; 8 | 9 | int main() 10 | { 11 | variant v( 2 ); 12 | return get<1>( v ) == 2? 0: 1; 13 | } 14 | -------------------------------------------------------------------------------- /include/boost/variant2.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOOST_VARIANT2_HPP_INCLUDED 2 | #define BOOST_VARIANT2_HPP_INCLUDED 3 | 4 | // Copyright 2021 Peter Dimov. 5 | // Distributed under the Boost Software License, Version 1.0. 6 | // https://www.boost.org/LICENSE_1_0.txt 7 | 8 | #include 9 | 10 | #endif // #ifndef BOOST_VARIANT2_HPP_INCLUDED 11 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "variant2", 3 | "name": "Variant2", 4 | "authors": [ 5 | "Peter Dimov" 6 | ], 7 | "maintainers": [ 8 | "Peter Dimov " 9 | ], 10 | "description": "A never-valueless, strong guarantee implementation of std::variant.", 11 | "category": [ 12 | "Containers", "Data" 13 | ], 14 | "cxxstd": "11" 15 | } 16 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018, 2019 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) 6 | 7 | if(HAVE_BOOST_TEST) 8 | 9 | boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::variant2 Boost::core Boost::container_hash) 10 | 11 | endif() 12 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Automatic redirection failed, please go to 7 | doc/html/variant2.html. 8 | 9 | 10 | 16 | -------------------------------------------------------------------------------- /doc/variant2/copyright.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Copyright 2018, 2019 Peter Dimov 3 | 4 | Distributed under the Boost Software License, Version 1.0. 5 | 6 | See accompanying file LICENSE_1_0.txt or copy at 7 | http://www.boost.org/LICENSE_1_0.txt 8 | //// 9 | 10 | [#copyright] 11 | # Copyright and License 12 | :idprefix: 13 | 14 | This documentation is copyright 2018, 2019 Peter Dimov and is distributed under 15 | the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. 16 | -------------------------------------------------------------------------------- /test/throw_exception.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // http://www.boost.org/LICENSE_1_0.txt 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace boost 12 | { 13 | 14 | void throw_exception( std::exception const & e ) 15 | { 16 | std::fprintf( stderr, "Exception: %s\n", e.what() ); 17 | std::terminate(); 18 | } 19 | 20 | } // namespace boost 21 | -------------------------------------------------------------------------------- /test/cmake_install_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018, 2019 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...3.16) 6 | 7 | project(cmake_install_test LANGUAGES CXX) 8 | 9 | find_package(boost_variant2 REQUIRED) 10 | 11 | add_executable(quick ../quick.cpp) 12 | target_link_libraries(quick Boost::variant2) 13 | 14 | enable_testing() 15 | add_test(quick quick) 16 | 17 | add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) 18 | -------------------------------------------------------------------------------- /doc/Jamfile: -------------------------------------------------------------------------------- 1 | # Copyright 2017, 2018 Peter Dimov 2 | # 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # (See accompanying file LICENSE_1_0.txt or copy at 5 | # http://www.boost.org/LICENSE_1_0.txt) 6 | 7 | import asciidoctor ; 8 | 9 | html variant2.html : variant2.adoc ; 10 | 11 | install html_ : variant2.html : html ; 12 | 13 | pdf variant2.pdf : variant2.adoc ; 14 | explicit variant2.pdf ; 15 | 16 | install pdf_ : variant2.pdf : pdf ; 17 | explicit pdf_ ; 18 | 19 | ############################################################################### 20 | alias boostdoc ; 21 | explicit boostdoc ; 22 | alias boostrelease : html_ ; 23 | explicit boostrelease ; 24 | -------------------------------------------------------------------------------- /test/variant_derived_construct.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | using namespace boost::variant2; 8 | 9 | template class X: variant 10 | { 11 | using base = variant; 12 | using base::base; 13 | }; 14 | 15 | struct Y 16 | { 17 | Y( Y const& rhs ) = default; 18 | 19 | template Y( T const& t ) 20 | { 21 | t.bar(); 22 | } 23 | }; 24 | 25 | int main() 26 | { 27 | using W = X; 28 | 29 | W a( 1 ); 30 | W b( a ); 31 | 32 | (void)b; 33 | } 34 | -------------------------------------------------------------------------------- /doc/variant2/implementation.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Copyright 2019 Peter Dimov 3 | Distributed under the Boost Software License, Version 1.0. 4 | https://www.boost.org/LICENSE_1_0.txt 5 | //// 6 | 7 | [#implementation] 8 | # Implementation 9 | :idprefix: implementation_ 10 | 11 | ## Dependencies 12 | 13 | This implementation only depends on Boost.Config, Boost.Assert, and Boost.Mp11. 14 | 15 | ## Supported Compilers 16 | 17 | * GCC 4.8 or later with `-std=c++11` or above 18 | * Clang 3.9 or later with `-std=c++11` or above 19 | * Visual Studio 2015 or later 20 | 21 | Tested on https://github.com/boostorg/variant2/actions[Github Actions] and 22 | https://ci.appveyor.com/project/pdimov/variant2-fkab9[Appveyor]. 23 | -------------------------------------------------------------------------------- /doc/variant2.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Copyright 2018 Peter Dimov 3 | 4 | Distributed under the Boost Software License, Version 1.0. 5 | 6 | See accompanying file LICENSE_1_0.txt or copy at 7 | http://www.boost.org/LICENSE_1_0.txt 8 | //// 9 | 10 | # Boost.Variant2: A never valueless variant type 11 | Peter Dimov 12 | :toc: left 13 | :toclevels: 4 14 | :idprefix: 15 | :docinfo: private-footer 16 | :source-highlighter: rouge 17 | :source-language: c++ 18 | 19 | :leveloffset: +1 20 | 21 | include::variant2/overview.adoc[] 22 | include::variant2/changelog.adoc[] 23 | include::variant2/design.adoc[] 24 | include::variant2/implementation.adoc[] 25 | include::variant2/reference.adoc[] 26 | include::variant2/copyright.adoc[] 27 | 28 | :leveloffset: -1 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boost.Variant2 2 | 3 | This repository contains a never-valueless, strong guarantee, C++11/14/17 4 | implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant). 5 | See [the documentation](https://www.boost.org/libs/variant2) 6 | for more information. 7 | 8 | The library is part of Boost, starting from release 1.71. It depends on 9 | Boost.Mp11, Boost.Config, and Boost.Assert. 10 | 11 | Supported compilers: 12 | 13 | * g++ 4.8 or later with `-std=c++11` or above 14 | * clang++ 3.9 or later with `-std=c++11` or above 15 | * Visual Studio 2015 or later 16 | 17 | Tested on [Github Actions](https://github.com/boostorg/variant2/actions) and 18 | [Appveyor](https://ci.appveyor.com/project/pdimov/variant2-fkab9). 19 | -------------------------------------------------------------------------------- /test/cmake_subdir_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2018, 2019 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...3.16) 6 | 7 | project(cmake_subdir_test LANGUAGES CXX) 8 | 9 | add_subdirectory(../.. boostorg/variant2) 10 | 11 | add_subdirectory(../../../assert boostorg/assert) 12 | add_subdirectory(../../../config boostorg/config) 13 | add_subdirectory(../../../mp11 boostorg/mp11) 14 | 15 | add_executable(quick ../quick.cpp) 16 | target_link_libraries(quick Boost::variant2) 17 | 18 | enable_testing() 19 | add_test(quick quick) 20 | 21 | add_custom_target(check VERBATIM COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) 22 | -------------------------------------------------------------------------------- /test/variant_value_construct_cx_2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #else 14 | 15 | using namespace boost::variant2; 16 | 17 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 18 | 19 | struct X 20 | { 21 | constexpr ~X() {} 22 | }; 23 | 24 | int main() 25 | { 26 | constexpr variant v( 5 ); 27 | 28 | STATIC_ASSERT( v.index() == 1 ); 29 | STATIC_ASSERT( get<1>(v) == 5 ); 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /test/variant_default_construct_cx_2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #else 14 | 15 | using namespace boost::variant2; 16 | 17 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 18 | 19 | struct X 20 | { 21 | constexpr ~X() {} 22 | }; 23 | 24 | int main() 25 | { 26 | constexpr variant v; 27 | 28 | STATIC_ASSERT( v.index() == 0 ); 29 | STATIC_ASSERT( get<0>(v) == 0 ); 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /.drone/drone.bat: -------------------------------------------------------------------------------- 1 | @REM Copyright 2022 Peter Dimov 2 | @REM Distributed under the Boost Software License, Version 1.0. 3 | @REM https://www.boost.org/LICENSE_1_0.txt 4 | 5 | @ECHO ON 6 | 7 | set LIBRARY=%1 8 | set DRONE_BUILD_DIR=%CD% 9 | 10 | set BOOST_BRANCH=develop 11 | if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master 12 | cd .. 13 | git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root 14 | cd boost-root 15 | git submodule update --init tools/boostdep 16 | xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\ 17 | python tools/boostdep/depinst/depinst.py %LIBRARY% 18 | cmd /c bootstrap 19 | b2 -d0 headers 20 | 21 | if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% 22 | if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% 23 | if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS% 24 | b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker 25 | -------------------------------------------------------------------------------- /.drone/drone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Peter Dimov 4 | # Distributed under the Boost Software License, Version 1.0. 5 | # https://www.boost.org/LICENSE_1_0.txt 6 | 7 | set -ex 8 | export PATH=~/.local/bin:/usr/local/bin:$PATH 9 | 10 | DRONE_BUILD_DIR=$(pwd) 11 | 12 | BOOST_BRANCH=develop 13 | if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi 14 | 15 | cd .. 16 | git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root 17 | cd boost-root 18 | git submodule update --init tools/boostdep 19 | cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY 20 | python tools/boostdep/depinst/depinst.py $LIBRARY 21 | ./bootstrap.sh 22 | ./b2 -d0 headers 23 | 24 | echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam 25 | ./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} 26 | -------------------------------------------------------------------------------- /test/variant_value_construct_cx_3.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION < 180000 14 | 15 | BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_CLANG_VERSION < 180000") 16 | int main() {} 17 | 18 | #else 19 | 20 | using namespace boost::variant2; 21 | 22 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 23 | 24 | struct X 25 | { 26 | ~X() {} 27 | }; 28 | 29 | int main() 30 | { 31 | constexpr variant v( 5 ); 32 | 33 | STATIC_ASSERT( v.index() == 1 ); 34 | STATIC_ASSERT( get<1>(v) == 5 ); 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /test/variant_default_construct_cx_4.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 10 | 11 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because __cpp_constexpr_dynamic_alloc < 201907L") 12 | int main() {} 13 | 14 | #elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION < 180000 15 | 16 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because BOOST_CLANG_VERSION < 180000") 17 | int main() {} 18 | 19 | #else 20 | 21 | using namespace boost::variant2; 22 | 23 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 24 | 25 | int main() 26 | { 27 | constexpr variant v; 28 | 29 | STATIC_ASSERT( v.index() == 0 ); 30 | STATIC_ASSERT( get<0>(v) == 0 ); 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /test/variant_default_construct_cx_3.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION < 180000 14 | 15 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because BOOST_CLANG_VERSION < 180000") 16 | int main() {} 17 | 18 | #else 19 | 20 | using namespace boost::variant2; 21 | 22 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 23 | 24 | struct X 25 | { 26 | ~X() {} 27 | }; 28 | 29 | int main() 30 | { 31 | constexpr variant v; 32 | 33 | STATIC_ASSERT( v.index() == 0 ); 34 | STATIC_ASSERT( get<0>(v) == 0 ); 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /test/variant_ostream_insert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace boost::variant2; 11 | 12 | template std::string to_string( T const& t ) 13 | { 14 | std::ostringstream os; 15 | 16 | os << t; 17 | 18 | return os.str(); 19 | } 20 | 21 | int main() 22 | { 23 | { 24 | BOOST_TEST_EQ( to_string( monostate() ), "monostate" ); 25 | } 26 | 27 | { 28 | variant v; 29 | 30 | BOOST_TEST_EQ( to_string( v ), to_string( monostate() ) ); 31 | 32 | v = 1; 33 | BOOST_TEST_EQ( to_string( v ), to_string( 1 ) ); 34 | 35 | v = 3.14f; 36 | BOOST_TEST_EQ( to_string( v ), to_string( 3.14f ) ); 37 | 38 | v = "test"; 39 | BOOST_TEST_EQ( to_string( v ), to_string( "test" ) ); 40 | } 41 | 42 | return boost::report_errors(); 43 | } 44 | -------------------------------------------------------------------------------- /test/variant_visit_cx.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017, 2024 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // http://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | using namespace boost::variant2; 7 | 8 | #if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) 9 | 10 | #include 11 | 12 | BOOST_PRAGMA_MESSAGE("Skipping constexpr visit test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") 13 | 14 | int main() {} 15 | 16 | #else 17 | 18 | struct X 19 | { 20 | constexpr operator int() const { return 2; } 21 | }; 22 | 23 | struct F 24 | { 25 | constexpr int operator()( int x ) const 26 | { 27 | return x; 28 | } 29 | }; 30 | 31 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 32 | 33 | int main() 34 | { 35 | { 36 | constexpr variant v( 1 ); 37 | STATIC_ASSERT( visit( F(), v ) == 1 ); 38 | } 39 | 40 | { 41 | constexpr variant v( 'a' ); 42 | STATIC_ASSERT( visit( F(), v ) == 'a' ); 43 | } 44 | 45 | { 46 | constexpr variant v( X{} ); 47 | STATIC_ASSERT( visit( F(), v ) == 2 ); 48 | } 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /test/variant_holds_alternative_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 14 | 15 | int main() 16 | { 17 | { 18 | constexpr variant v; 19 | STATIC_ASSERT( holds_alternative( v ) ); 20 | } 21 | 22 | { 23 | constexpr variant v; 24 | STATIC_ASSERT( holds_alternative( v ) ); 25 | STATIC_ASSERT( !holds_alternative( v ) ); 26 | } 27 | 28 | { 29 | constexpr variant v( 3.14f ); 30 | STATIC_ASSERT( !holds_alternative( v ) ); 31 | STATIC_ASSERT( holds_alternative( v ) ); 32 | } 33 | 34 | { 35 | constexpr variant v; 36 | STATIC_ASSERT( holds_alternative( v ) ); 37 | } 38 | 39 | { 40 | constexpr variant v( 3.14f ); 41 | STATIC_ASSERT( holds_alternative( v ) ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/variant_move_assign_throw.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | struct Y1 20 | { 21 | Y1() noexcept {} // =default fails on msvc-14.0 22 | 23 | Y1(Y1&&) 24 | { 25 | throw std::runtime_error( "Y1(Y1&&)" ); 26 | } 27 | 28 | Y1& operator=(Y1&&) = default; 29 | }; 30 | 31 | struct Y2 32 | { 33 | Y2() noexcept {} 34 | 35 | Y2(Y2&&) 36 | { 37 | throw std::runtime_error( "Y2(Y2&&)" ); 38 | } 39 | 40 | Y2& operator=(Y2&&) = default; 41 | }; 42 | 43 | void test() 44 | { 45 | variant v1( in_place_type_t{} ); 46 | variant v2( in_place_type_t{} ); 47 | 48 | BOOST_TEST_THROWS( v1 = std::move( v2 ), std::runtime_error ); 49 | } 50 | 51 | int main() 52 | { 53 | test(); 54 | return boost::report_errors(); 55 | } 56 | -------------------------------------------------------------------------------- /test/variant_copy_assign_throw.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | struct Y1 20 | { 21 | Y1() noexcept {} // =default fails on msvc-14.0 22 | 23 | Y1(Y1 const&) 24 | { 25 | throw std::runtime_error( "Y1(Y1 const&)" ); 26 | } 27 | 28 | Y1& operator=(Y1 const&) = default; 29 | }; 30 | 31 | struct Y2 32 | { 33 | Y2() noexcept {} 34 | 35 | Y2(Y2 const&) 36 | { 37 | throw std::runtime_error( "Y2(Y2 const&)" ); 38 | } 39 | 40 | Y2& operator=(Y2 const&) = default; 41 | }; 42 | 43 | void test() 44 | { 45 | variant v1( in_place_type_t{} ); 46 | variant v2( in_place_type_t{} ); 47 | 48 | BOOST_TEST_THROWS( v1 = v2, std::runtime_error ); 49 | } 50 | 51 | int main() 52 | { 53 | test(); 54 | return boost::report_errors(); 55 | } 56 | -------------------------------------------------------------------------------- /test/variant_default_construct_cx_5.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #elif defined(BOOST_MSVC) && BOOST_MSVC < 1950 14 | 15 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because BOOST_MSVC < 1950") 16 | int main() {} 17 | 18 | #elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION < 180000 19 | 20 | BOOST_PRAGMA_MESSAGE("Skipping constexpr destructor test because BOOST_CLANG_VERSION < 180000") 21 | int main() {} 22 | 23 | #else 24 | 25 | using namespace boost::variant2; 26 | 27 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 28 | 29 | struct X 30 | { 31 | }; 32 | 33 | struct Y 34 | { 35 | constexpr ~Y() {} 36 | }; 37 | 38 | struct Z 39 | { 40 | ~Z() {} 41 | }; 42 | 43 | int main() 44 | { 45 | constexpr variant v; 46 | STATIC_ASSERT( v.index() == 0 ); 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /test/variant_visit_r_cx.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017, 2024 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // http://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | using namespace boost::variant2; 7 | 8 | #if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) 9 | 10 | #include 11 | 12 | BOOST_PRAGMA_MESSAGE("Skipping constexpr visit test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") 13 | 14 | int main() {} 15 | 16 | #else 17 | 18 | struct X 19 | { 20 | int v; 21 | constexpr operator int() const { return v; } 22 | }; 23 | 24 | struct F 25 | { 26 | template constexpr T operator()( T x ) const 27 | { 28 | return x; 29 | } 30 | }; 31 | 32 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 33 | 34 | int main() 35 | { 36 | { 37 | constexpr variant v( 1 ); 38 | STATIC_ASSERT( visit( F(), v ) == 1 ); 39 | } 40 | 41 | { 42 | constexpr variant v( 'a' ); 43 | STATIC_ASSERT( visit( F(), v ) == 'a' ); 44 | } 45 | 46 | { 47 | constexpr variant v( X{2} ); 48 | STATIC_ASSERT( visit( F(), v ) == 2 ); 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /test/variant_default_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 14 | 15 | int main() 16 | { 17 | { 18 | constexpr variant v; 19 | 20 | STATIC_ASSERT( v.index() == 0 ); 21 | STATIC_ASSERT( get<0>(v) == 0 ); 22 | } 23 | 24 | { 25 | constexpr variant v; 26 | 27 | STATIC_ASSERT( v.index() == 0 ); 28 | STATIC_ASSERT( get<0>(v) == 0 ); 29 | } 30 | 31 | { 32 | constexpr variant v; 33 | 34 | STATIC_ASSERT( v.index() == 0 ); 35 | STATIC_ASSERT( get<0>(v) == 0 ); 36 | } 37 | 38 | { 39 | constexpr variant v; 40 | 41 | STATIC_ASSERT( v.index() == 0 ); 42 | STATIC_ASSERT( get<0>(v) == 0 ); 43 | } 44 | 45 | { 46 | constexpr variant v; 47 | 48 | STATIC_ASSERT( v.index() == 0 ); 49 | STATIC_ASSERT( get<0>(v) == 0 ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake variant2` 2 | # Copyright 2020, 2021 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.8...3.20) 7 | 8 | project(boost_variant2 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_variant2 INTERFACE) 11 | add_library(Boost::variant2 ALIAS boost_variant2) 12 | 13 | target_include_directories(boost_variant2 INTERFACE include) 14 | 15 | target_link_libraries(boost_variant2 16 | INTERFACE 17 | Boost::assert 18 | Boost::config 19 | Boost::mp11 20 | ) 21 | 22 | if(NOT CMAKE_VERSION VERSION_LESS 3.19 AND CMAKE_GENERATOR MATCHES "Visual Studio") 23 | 24 | file(GLOB_RECURSE boost_variant2_IDEFILES CONFIGURE_DEPENDS include/*.hpp) 25 | source_group(TREE ${PROJECT_SOURCE_DIR}/include FILES ${boost_variant2_IDEFILES} PREFIX "Header Files") 26 | list(APPEND boost_variant2_IDEFILES extra/boost_variant2.natvis) 27 | target_sources(boost_variant2 PRIVATE ${boost_variant2_IDEFILES}) 28 | 29 | endif() 30 | 31 | target_compile_features(boost_variant2 INTERFACE cxx_std_11) 32 | 33 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 34 | 35 | add_subdirectory(test) 36 | 37 | endif() 38 | -------------------------------------------------------------------------------- /test/variant_value_construct_cx_4.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !defined(__cpp_constexpr_dynamic_alloc) || __cpp_constexpr_dynamic_alloc < 201907L 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping test because __cpp_constexpr_dynamic_alloc < 201907L") 11 | int main() {} 12 | 13 | #elif defined(BOOST_MSVC) && BOOST_MSVC < 1950 14 | 15 | BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_MSVC < 1950") 16 | int main() {} 17 | 18 | #elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION < 180000 19 | 20 | BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_CLANG_VERSION < 180000") 21 | int main() {} 22 | 23 | #else 24 | 25 | using namespace boost::variant2; 26 | 27 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 28 | 29 | struct X 30 | { 31 | }; 32 | 33 | struct Y 34 | { 35 | constexpr ~Y() {} 36 | }; 37 | 38 | struct Z 39 | { 40 | ~Z() {} 41 | }; 42 | 43 | int main() 44 | { 45 | { 46 | constexpr variant v( X{} ); 47 | STATIC_ASSERT( v.index() == 0 ); 48 | } 49 | 50 | { 51 | constexpr variant v( Y{} ); 52 | STATIC_ASSERT( v.index() == 1 ); 53 | } 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /test/variant_derived_construct2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | struct expr: boost::variant2::variant 9 | { 10 | using variant::variant; 11 | }; 12 | 13 | int main() 14 | { 15 | using boost::variant2::get; 16 | 17 | { 18 | expr v{ true }; 19 | 20 | BOOST_TEST_EQ( v.index(), 0 ); 21 | BOOST_TEST_EQ( get<0>(v), true ); 22 | } 23 | 24 | { 25 | expr v{ 2 }; 26 | 27 | BOOST_TEST_EQ( v.index(), 1 ); 28 | BOOST_TEST_EQ( get<1>(v), 2 ); 29 | } 30 | 31 | { 32 | expr v{ 3.0 }; 33 | 34 | BOOST_TEST_EQ( v.index(), 2 ); 35 | BOOST_TEST_EQ( get<2>(v), 3.0 ); 36 | } 37 | 38 | { 39 | expr v( true ); 40 | 41 | BOOST_TEST_EQ( v.index(), 0 ); 42 | BOOST_TEST_EQ( get<0>(v), true ); 43 | } 44 | 45 | { 46 | expr v( 2 ); 47 | 48 | BOOST_TEST_EQ( v.index(), 1 ); 49 | BOOST_TEST_EQ( get<1>(v), 2 ); 50 | } 51 | 52 | { 53 | expr v( 3.0 ); 54 | 55 | BOOST_TEST_EQ( v.index(), 2 ); 56 | BOOST_TEST_EQ( get<2>(v), 3.0 ); 57 | } 58 | 59 | return boost::report_errors(); 60 | } 61 | -------------------------------------------------------------------------------- /test/variant_json_value_from.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | #if defined(BOOST_GCC) && BOOST_GCC < 50000 8 | # define BOOST_ALLOW_DEPRECATED 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | namespace json = boost::json; 19 | 20 | int main() 21 | { 22 | { 23 | monostate m; 24 | json::value w = json::value_from( m ); 25 | BOOST_TEST_EQ( w, json::value( nullptr ) ); 26 | } 27 | 28 | { 29 | variant v; 30 | json::value w = json::value_from( v ); 31 | BOOST_TEST_EQ( w, json::value( nullptr ) ); 32 | } 33 | 34 | { 35 | variant v( 17 ); 36 | json::value w = json::value_from( v ); 37 | BOOST_TEST_EQ( w, json::value( 17 ) ); 38 | } 39 | 40 | { 41 | variant v( "test" ); 42 | json::value w = json::value_from( v ); 43 | BOOST_TEST_EQ( w, json::value( "test" ) ); 44 | } 45 | 46 | return boost::report_errors(); 47 | } 48 | -------------------------------------------------------------------------------- /test/variant_json_value_to.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | 7 | #if defined(BOOST_GCC) && BOOST_GCC < 50000 8 | # define BOOST_ALLOW_DEPRECATED 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | namespace json = boost::json; 18 | 19 | int main() 20 | { 21 | { 22 | json::value v; 23 | auto r = json::try_value_to( v ); 24 | BOOST_TEST( r.has_value() ); 25 | } 26 | 27 | using V = variant; 28 | 29 | { 30 | json::value v; 31 | auto r = json::try_value_to( v ); 32 | BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V() ); 33 | } 34 | 35 | { 36 | json::value v( 12 ); 37 | auto r = json::try_value_to( v ); 38 | BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V(12) ); 39 | } 40 | 41 | { 42 | json::value v( "test" ); 43 | auto r = json::try_value_to( v ); 44 | BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V("test") ); 45 | } 46 | 47 | return boost::report_errors(); 48 | } 49 | -------------------------------------------------------------------------------- /test/variant_copy_construct_throw.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | struct X 20 | { 21 | static int instances; 22 | 23 | X() 24 | { 25 | ++instances; 26 | } 27 | 28 | X( X const& ) 29 | { 30 | throw std::runtime_error( "X(X const&)" ); 31 | } 32 | 33 | ~X() 34 | { 35 | --instances; 36 | } 37 | }; 38 | 39 | int X::instances = 0; 40 | 41 | void test() 42 | { 43 | X::instances = 0; 44 | 45 | { 46 | variant v1; 47 | 48 | BOOST_TEST_EQ( X::instances, 1 ); 49 | 50 | try 51 | { 52 | variant v2( v1 ); 53 | BOOST_TEST_EQ( X::instances, 2 ); 54 | } 55 | catch( std::exception const& ) 56 | { 57 | } 58 | 59 | BOOST_TEST_EQ( X::instances, 1 ); 60 | } 61 | 62 | BOOST_TEST_EQ( X::instances, 0 ); 63 | } 64 | 65 | int main() 66 | { 67 | test(); 68 | return boost::report_errors(); 69 | } 70 | -------------------------------------------------------------------------------- /test/variant_move_construct_throw.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | struct X 20 | { 21 | static int instances; 22 | 23 | X() 24 | { 25 | ++instances; 26 | } 27 | 28 | X( X const& ) 29 | { 30 | throw std::runtime_error( "X(X const&)" ); 31 | } 32 | 33 | ~X() 34 | { 35 | --instances; 36 | } 37 | }; 38 | 39 | int X::instances = 0; 40 | 41 | void test() 42 | { 43 | X::instances = 0; 44 | 45 | { 46 | variant v1; 47 | 48 | BOOST_TEST_EQ( X::instances, 1 ); 49 | 50 | try 51 | { 52 | variant v2( std::move( v1 ) ); 53 | BOOST_TEST_EQ( X::instances, 2 ); 54 | } 55 | catch( std::exception const& ) 56 | { 57 | } 58 | 59 | BOOST_TEST_EQ( X::instances, 1 ); 60 | } 61 | 62 | BOOST_TEST_EQ( X::instances, 0 ); 63 | } 64 | 65 | int main() 66 | { 67 | test(); 68 | return boost::report_errors(); 69 | } 70 | -------------------------------------------------------------------------------- /test/variant_uses_double_storage.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | using namespace boost::variant2; 9 | 10 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 11 | 12 | struct X1 13 | { 14 | }; 15 | 16 | STATIC_ASSERT( std::is_nothrow_move_constructible::value ); 17 | STATIC_ASSERT( std::is_trivially_destructible::value ); 18 | 19 | struct X2 20 | { 21 | ~X2() {} 22 | }; 23 | 24 | STATIC_ASSERT( std::is_nothrow_move_constructible::value ); 25 | STATIC_ASSERT( !std::is_trivially_destructible::value ); 26 | 27 | struct X3 28 | { 29 | X3( X3&& ) {} 30 | }; 31 | 32 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 33 | STATIC_ASSERT( std::is_trivially_destructible::value ); 34 | 35 | struct X4 36 | { 37 | ~X4() {} 38 | X4( X4&& ) {} 39 | }; 40 | 41 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 42 | STATIC_ASSERT( !std::is_trivially_destructible::value ); 43 | 44 | // 45 | 46 | STATIC_ASSERT( !variant::uses_double_storage() ); 47 | STATIC_ASSERT( !variant::uses_double_storage() ); 48 | STATIC_ASSERT( !variant::uses_double_storage() ); 49 | STATIC_ASSERT( variant::uses_double_storage() ); 50 | STATIC_ASSERT( variant::uses_double_storage() ); 51 | -------------------------------------------------------------------------------- /test/variant_visit_cx_2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017, 2024 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // http://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | 8 | #if !( defined(__cpp_constexpr) && __cpp_constexpr >= 201603L ) 9 | 10 | BOOST_PRAGMA_MESSAGE("Skipping constexpr visit test because __cpp_constexpr < 201603L") 11 | int main() {} 12 | 13 | #elif !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) 14 | 15 | BOOST_PRAGMA_MESSAGE("Skipping constexpr visit test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") 16 | int main() {} 17 | 18 | #else 19 | 20 | using namespace boost::variant2; 21 | 22 | struct F 23 | { 24 | constexpr int operator()( int x1, int x2 ) const 25 | { 26 | return x1 + x2; 27 | } 28 | 29 | constexpr int operator()( int x1, int x2, int x3 ) const 30 | { 31 | return x1 + x2 + x3; 32 | } 33 | }; 34 | 35 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 36 | 37 | int main() 38 | { 39 | { 40 | constexpr variant v1( 1 ); 41 | constexpr variant v2( '2' ); 42 | STATIC_ASSERT( visit( F(), v1, v2 ) == 1 + '2' ); 43 | } 44 | 45 | { 46 | constexpr variant v1( 1 ); 47 | constexpr variant v2( 2 ); 48 | constexpr variant v3( '3' ); 49 | STATIC_ASSERT( visit( F(), v1, v2, v3 ) == 1 + 2 + '3' ); 50 | } 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /doc/variant2/changelog.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | Copyright 2019-2025 Peter Dimov 3 | Distributed under the Boost Software License, Version 1.0. 4 | https://www.boost.org/LICENSE_1_0.txt 5 | //// 6 | 7 | [#changelog] 8 | # Revision History 9 | :idprefix: changelog_ 10 | 11 | ## Changes in 1.90.0 12 | 13 | * More functions have been marked as `constexpr`, including `~variant`. 14 | This didn't matter before {cpp}20, but does now. 15 | 16 | ## Changes in 1.88.0 17 | 18 | * Use the smallest appropriate unsigned type for the index. 19 | 20 | ## Changes in 1.83.0 21 | 22 | * Added `uses_double_storage()`. 23 | 24 | ## Changes in 1.81.0 25 | 26 | * Added support for `boost::json::value_from` and `boost::json::value_to`. 27 | 28 | ## Changes in 1.79.0 29 | 30 | * Added `operator<<` for `monostate`. 31 | 32 | ## Changes in 1.78.0 33 | 34 | * Added ``. 35 | * Added `unsafe_get`. 36 | * Added `visit_by_index`. 37 | * Added `operator<<`. 38 | 39 | ## Changes in 1.76.0 40 | 41 | * Improved generated code for the double buffered case. 42 | 43 | ## Changes in 1.74.0 44 | 45 | * Added support for derived types in `visit` 46 | * Improved compilation performance for many (hundreds of) alternatives. 47 | * Added support for `visit` 48 | 49 | ## Changes in 1.73.0 50 | 51 | * Added support for `std::hash`, `boost::hash`. 52 | * `variant` is now trivial when all types in `T...` are trivial. 53 | This improves performance by enabling it to be passed to, and returned 54 | from, functions in registers. 55 | 56 | ## Changes in 1.71.0 57 | 58 | After the Boost formal review, the implementation has been 59 | changed to provide the strong exception safety guarantee, 60 | instead of basic. `expected` has been removed. 61 | -------------------------------------------------------------------------------- /test/is_output_streamable.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | struct X 11 | { 12 | }; 13 | 14 | struct Y 15 | { 16 | }; 17 | 18 | std::ostream& operator<<( std::ostream& os, Y const& /*y*/ ) 19 | { 20 | os << "Y()"; 21 | return os; 22 | } 23 | 24 | int main() 25 | { 26 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable)); 27 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable)); 28 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable)); 29 | BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable)); 30 | BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable)); 31 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable)); 32 | 33 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable)); 34 | 35 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable>)); 36 | BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable>)); 37 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable>)); 38 | BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable>)); 39 | 40 | return boost::report_errors(); 41 | } 42 | -------------------------------------------------------------------------------- /test/variant_visit_derived.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017, 2020 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #if defined(_MSC_VER) 6 | # pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct X: boost::variant2::variant 16 | { 17 | #if BOOST_WORKAROUND( BOOST_MSVC, < 1940 ) 18 | 19 | template explicit X( T&& t ): variant( std::forward( t ) ) {}; 20 | 21 | #else 22 | 23 | using variant::variant; 24 | 25 | #endif 26 | }; 27 | 28 | template struct Y: boost::variant2::variant 29 | { 30 | using boost::variant2::variant::variant; 31 | }; 32 | 33 | int main() 34 | { 35 | { 36 | X v1( 1 ); 37 | X const v2( 3.14f ); 38 | 39 | BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 ); 40 | 41 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 ); 42 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) ); 43 | } 44 | 45 | { 46 | Y v1( 1 ); 47 | Y const v2( 3.14f ); 48 | 49 | BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 ); 50 | 51 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 ); 52 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) ); 53 | } 54 | 55 | return boost::report_errors(); 56 | } 57 | -------------------------------------------------------------------------------- /test/variant_convert_construct_throw.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | struct X 20 | { 21 | static int instances; 22 | 23 | X() 24 | { 25 | ++instances; 26 | } 27 | 28 | X( X const& ) 29 | { 30 | throw std::runtime_error( "X(X const&)" ); 31 | } 32 | 33 | ~X() 34 | { 35 | --instances; 36 | } 37 | }; 38 | 39 | int X::instances = 0; 40 | 41 | void test_copy() 42 | { 43 | X::instances = 0; 44 | 45 | { 46 | variant v1; 47 | 48 | BOOST_TEST_EQ( X::instances, 1 ); 49 | 50 | try 51 | { 52 | variant v2( v1 ); 53 | BOOST_TEST_EQ( X::instances, 2 ); 54 | } 55 | catch( std::exception const& ) 56 | { 57 | } 58 | 59 | BOOST_TEST_EQ( X::instances, 1 ); 60 | } 61 | 62 | BOOST_TEST_EQ( X::instances, 0 ); 63 | } 64 | 65 | void test_move() 66 | { 67 | X::instances = 0; 68 | 69 | { 70 | variant v1; 71 | 72 | BOOST_TEST_EQ( X::instances, 1 ); 73 | 74 | try 75 | { 76 | variant v2( std::move( v1 ) ); 77 | BOOST_TEST_EQ( X::instances, 2 ); 78 | } 79 | catch( std::exception const& ) 80 | { 81 | } 82 | 83 | BOOST_TEST_EQ( X::instances, 1 ); 84 | } 85 | 86 | BOOST_TEST_EQ( X::instances, 0 ); 87 | } 88 | 89 | int main() 90 | { 91 | test_copy(); 92 | test_move(); 93 | 94 | return boost::report_errors(); 95 | } 96 | -------------------------------------------------------------------------------- /test/variant_index_type.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Peter Dimov 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #if defined(_MSC_VER) 6 | # pragma warning( disable: 4503 ) // decorated name length exceeded 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace boost::mp11; 14 | 15 | template struct X 16 | { 17 | }; 18 | 19 | template using Xf = X< N::value >; 20 | 21 | template struct Y 22 | { 23 | Y() = default; 24 | Y( Y&& ) {} 25 | }; 26 | 27 | template using Yf = Y< N::value >; 28 | 29 | template struct Z 30 | { 31 | ~Z() {} 32 | }; 33 | 34 | template using Zf = Z< N::value >; 35 | 36 | template struct W 37 | { 38 | ~W() {} 39 | 40 | W() = default; 41 | W( W&& ) {} 42 | }; 43 | 44 | template using Wf = W< N::value >; 45 | 46 | template class F> void test() 47 | { 48 | using V = mp_rename< mp_transform, boost::variant2::variant >; 49 | 50 | constexpr std::size_t N = mp_size::value; 51 | 52 | using last_type = F>; 53 | 54 | { 55 | V v( last_type{} ); 56 | BOOST_TEST_EQ( v.index(), N-1 ); 57 | } 58 | 59 | { 60 | V v; 61 | BOOST_TEST_EQ( v.index(), 0 ); 62 | 63 | v.template emplace(); 64 | BOOST_TEST_EQ( v.index(), N-1 ); 65 | } 66 | } 67 | 68 | int main() 69 | { 70 | constexpr std::size_t N = LIST_SIZE; 71 | using L = mp_iota_c; 72 | 73 | static_assert( !boost::variant2::variant< X<0>, X<1> >::uses_double_storage(), "" ); 74 | test(); 75 | 76 | static_assert( boost::variant2::variant< Y<0>, Y<1> >::uses_double_storage(), "" ); 77 | test(); 78 | 79 | static_assert( !boost::variant2::variant< Z<0>, Z<1> >::uses_double_storage(), "" ); 80 | test(); 81 | 82 | static_assert( boost::variant2::variant< W<0>, W<1> >::uses_double_storage(), "" ); 83 | test(); 84 | 85 | return boost::report_errors(); 86 | } 87 | -------------------------------------------------------------------------------- /test/variant_emplace_type_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | int v; 16 | X() = default; 17 | constexpr explicit X( int v ): v( v ) {} 18 | constexpr operator int() const { return v; } 19 | }; 20 | 21 | struct Y 22 | { 23 | int v; 24 | constexpr Y(): v() {} 25 | constexpr explicit Y( int v ): v( v ) {} 26 | constexpr operator int() const { return v; } 27 | }; 28 | 29 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 30 | 31 | template constexpr A test( A const& a ) 32 | { 33 | V v; 34 | 35 | v.template emplace( a ); 36 | 37 | return get(v); 38 | } 39 | 40 | int main() 41 | { 42 | { 43 | constexpr auto w = test, int>( 1 ); 44 | STATIC_ASSERT( w == 1 ); 45 | } 46 | 47 | { 48 | constexpr auto w = test, X>( 1 ); 49 | STATIC_ASSERT( w == 1 ); 50 | } 51 | 52 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 53 | #else 54 | 55 | { 56 | constexpr auto w = test, Y>( 1 ); 57 | STATIC_ASSERT( w == 1 ); 58 | } 59 | 60 | #endif 61 | 62 | { 63 | constexpr auto w = test, int>( 1 ); 64 | STATIC_ASSERT( w == 1 ); 65 | } 66 | 67 | { 68 | constexpr auto w = test, float>( 3.0f ); 69 | STATIC_ASSERT( w == 3.0f ); 70 | } 71 | 72 | { 73 | constexpr auto w = test, float>( 3.0f ); 74 | STATIC_ASSERT( w == 3.0f ); 75 | } 76 | 77 | { 78 | constexpr auto w = test, X>( 1 ); 79 | STATIC_ASSERT( w == 1 ); 80 | } 81 | 82 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 83 | #else 84 | 85 | { 86 | constexpr auto w = test, Y>( 1 ); 87 | STATIC_ASSERT( w == 1 ); 88 | } 89 | 90 | #endif 91 | } 92 | -------------------------------------------------------------------------------- /test/variant_holds_alternative.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace boost::variant2; 14 | 15 | int main() 16 | { 17 | { 18 | variant v; 19 | BOOST_TEST( holds_alternative( v ) ); 20 | } 21 | 22 | { 23 | variant v; 24 | BOOST_TEST( holds_alternative( v ) ); 25 | BOOST_TEST( !holds_alternative( v ) ); 26 | } 27 | 28 | { 29 | variant v( 3.14f ); 30 | BOOST_TEST( !holds_alternative( v ) ); 31 | BOOST_TEST( holds_alternative( v ) ); 32 | } 33 | 34 | { 35 | variant v; 36 | BOOST_TEST( holds_alternative( v ) ); 37 | } 38 | 39 | { 40 | variant v( 3.14f ); 41 | BOOST_TEST( holds_alternative( v ) ); 42 | } 43 | 44 | { 45 | variant v; 46 | BOOST_TEST( holds_alternative( v ) ); 47 | BOOST_TEST( !holds_alternative( v ) ); 48 | BOOST_TEST( !holds_alternative( v ) ); 49 | } 50 | 51 | { 52 | variant v( 3.14f ); 53 | BOOST_TEST( !holds_alternative( v ) ); 54 | BOOST_TEST( holds_alternative( v ) ); 55 | BOOST_TEST( !holds_alternative( v ) ); 56 | } 57 | 58 | { 59 | variant v( "text" ); 60 | BOOST_TEST( !holds_alternative( v ) ); 61 | BOOST_TEST( !holds_alternative( v ) ); 62 | BOOST_TEST( holds_alternative( v ) ); 63 | } 64 | 65 | { 66 | variant v( 3.14f ); 67 | BOOST_TEST( holds_alternative( v ) ); 68 | BOOST_TEST( !holds_alternative( v ) ); 69 | } 70 | 71 | { 72 | variant v( "text" ); 73 | BOOST_TEST( !holds_alternative( v ) ); 74 | BOOST_TEST( holds_alternative( v ) ); 75 | } 76 | 77 | return boost::report_errors(); 78 | } 79 | -------------------------------------------------------------------------------- /test/variant_get_by_type_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | 12 | using namespace boost::variant2; 13 | 14 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 15 | 16 | #if BOOST_WORKAROUND(BOOST_GCC, < 50000) 17 | # define STATIC_ASSERT_IF(...) 18 | #else 19 | # define STATIC_ASSERT_IF(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 20 | #endif 21 | 22 | int main() 23 | { 24 | { 25 | constexpr variant v; 26 | 27 | STATIC_ASSERT( get(v) == 0 ); 28 | 29 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 30 | } 31 | 32 | { 33 | constexpr variant v( 1 ); 34 | 35 | STATIC_ASSERT( get(v) == 1 ); 36 | 37 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 38 | } 39 | 40 | { 41 | constexpr variant v; 42 | 43 | STATIC_ASSERT( get(v) == 0 ); 44 | 45 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 46 | STATIC_ASSERT_IF( get_if(&v) == nullptr ); 47 | } 48 | 49 | { 50 | constexpr variant v( 1 ); 51 | 52 | STATIC_ASSERT( get(v) == 1 ); 53 | 54 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 55 | STATIC_ASSERT_IF( get_if(&v) == nullptr ); 56 | } 57 | 58 | { 59 | constexpr variant v( 3.14f ); 60 | 61 | STATIC_ASSERT( get(v) == (float)3.14f ); // see FLT_EVAL_METHOD 62 | 63 | STATIC_ASSERT_IF( get_if(&v) == nullptr ); 64 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 65 | } 66 | 67 | { 68 | constexpr variant v; 69 | 70 | STATIC_ASSERT( get(v) == 0 ); 71 | 72 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 73 | } 74 | 75 | { 76 | constexpr variant v( 1 ); 77 | 78 | STATIC_ASSERT( get(v) == 1 ); 79 | 80 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 81 | } 82 | 83 | { 84 | constexpr variant v( 3.14f ); 85 | 86 | STATIC_ASSERT( get(v) == (float)3.14f ); 87 | 88 | STATIC_ASSERT_IF( get_if(&v) == &get(v) ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /test/variant_hash.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2020 Peter Dimov. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // http://www.boost.org/LICENSE_1_0.txt 5 | 6 | #if defined(_MSC_VER) 7 | # pragma warning( disable: 4244 ) // conversion from int to float, possible loss of data 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace boost::variant2; 18 | 19 | template class Hash, class T1, class T2, class T3> void test() 20 | { 21 | variant v1( in_place_index_t<0>{} ); 22 | std::size_t h1 = Hash()( v1 ); 23 | 24 | variant v2( in_place_index_t<1>{} ); 25 | std::size_t h2 = Hash()( v2 ); 26 | 27 | variant v3( in_place_index_t<2>{} ); 28 | std::size_t h3 = Hash()( v3 ); 29 | 30 | BOOST_TEST_NE( h1, h2 ); 31 | BOOST_TEST_NE( h1, h3 ); 32 | BOOST_TEST_NE( h2, h3 ); 33 | } 34 | 35 | template class Hash, class T> void test2() 36 | { 37 | variant v1( 0 ); 38 | std::size_t h1 = Hash()( v1 ); 39 | 40 | variant v2( 1 ); 41 | std::size_t h2 = Hash()( v2 ); 42 | 43 | variant v3( 2 ); 44 | std::size_t h3 = Hash()( v3 ); 45 | 46 | BOOST_TEST_NE( h1, h2 ); 47 | BOOST_TEST_NE( h1, h3 ); 48 | BOOST_TEST_NE( h2, h3 ); 49 | } 50 | 51 | struct X 52 | { 53 | int m = 0; 54 | }; 55 | 56 | std::size_t hash_value( X const& x ) 57 | { 58 | return boost::hash()( x.m ); 59 | } 60 | 61 | struct Y {}; // no hash support 62 | 63 | int main() 64 | { 65 | test(); 66 | test(); 67 | 68 | test(); 69 | test(); 70 | 71 | test>(); 72 | 73 | test2(); 74 | test2(); 75 | 76 | test2(); 77 | test2(); 78 | 79 | #if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) && ( !defined(_LIBCPP_STD_VER) || _LIBCPP_STD_VER > 11 ) 80 | 81 | BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled )); 82 | 83 | #endif 84 | 85 | return boost::report_errors(); 86 | } 87 | -------------------------------------------------------------------------------- /test/variant_lt_gt.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | }; 21 | 22 | inline bool operator<( X const&, X const& ) { return false; } 23 | inline bool operator>( X const&, X const& ) { return false; } 24 | inline bool operator<=( X const&, X const& ) { return false; } 25 | inline bool operator>=( X const&, X const& ) { return false; } 26 | 27 | #define TEST_EQ( v1, v2 ) \ 28 | BOOST_TEST_NOT( v1 < v2 ); \ 29 | BOOST_TEST_NOT( v1 > v2 ); \ 30 | BOOST_TEST( v1 <= v2 ); \ 31 | BOOST_TEST( v1 >= v2 ); 32 | 33 | #define TEST_LE( v1, v3 ) \ 34 | BOOST_TEST( v1 < v3 ); \ 35 | BOOST_TEST( v3 > v1 ); \ 36 | BOOST_TEST_NOT( v1 > v3 ); \ 37 | BOOST_TEST_NOT( v3 < v1 ); \ 38 | BOOST_TEST( v1 <= v3 ); \ 39 | BOOST_TEST( v3 >= v1 ); \ 40 | BOOST_TEST_NOT( v1 >= v3 ); \ 41 | BOOST_TEST_NOT( v3 <= v1 ); 42 | 43 | int main() 44 | { 45 | { 46 | variant v1, v2, v3( 1 ), v4( 1 ); 47 | 48 | TEST_EQ( v1, v2 ) 49 | TEST_LE( v1, v3 ) 50 | TEST_EQ( v3, v4 ) 51 | } 52 | 53 | { 54 | variant v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); 55 | 56 | TEST_EQ( v1, v2 ) 57 | TEST_LE( v1, v3 ) 58 | TEST_EQ( v3, v4 ) 59 | TEST_LE( v1, v5 ) 60 | TEST_LE( v3, v5 ) 61 | TEST_EQ( v5, v6 ) 62 | } 63 | 64 | { 65 | variant v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); 66 | 67 | TEST_EQ( v1, v2 ) 68 | TEST_LE( v1, v3 ) 69 | TEST_EQ( v3, v4 ) 70 | TEST_LE( v1, v5 ) 71 | TEST_LE( v3, v5 ) 72 | TEST_EQ( v5, v6 ) 73 | } 74 | 75 | { 76 | variant v1, v2; 77 | 78 | BOOST_TEST_NOT( v1 < v2 ); 79 | BOOST_TEST_NOT( v1 > v2 ); 80 | BOOST_TEST_NOT( v1 <= v2 ); 81 | BOOST_TEST_NOT( v1 >= v2 ); 82 | } 83 | 84 | { 85 | variant v1, v2; 86 | 87 | BOOST_TEST_NOT( v1 < v2 ); 88 | BOOST_TEST_NOT( v1 > v2 ); 89 | BOOST_TEST( v1 <= v2 ); 90 | BOOST_TEST( v1 >= v2 ); 91 | } 92 | 93 | return boost::report_errors(); 94 | } 95 | -------------------------------------------------------------------------------- /test/variant_value_assign_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | int v; 16 | X() = default; 17 | constexpr X( int v ): v( v ) {} 18 | constexpr operator int() const { return v; } 19 | }; 20 | 21 | struct Y 22 | { 23 | int v; 24 | constexpr Y(): v() {} 25 | constexpr Y( int v ): v( v ) {} 26 | constexpr operator int() const { return v; } 27 | }; 28 | 29 | enum E 30 | { 31 | v 32 | }; 33 | 34 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 35 | 36 | template constexpr A test( A const& a ) 37 | { 38 | V v; 39 | 40 | v = a; 41 | 42 | return get(v); 43 | } 44 | 45 | int main() 46 | { 47 | { 48 | constexpr auto w = test, int>( 1 ); 49 | STATIC_ASSERT( w == 1 ); 50 | } 51 | 52 | { 53 | constexpr auto w = test, X>( 1 ); 54 | STATIC_ASSERT( w == 1 ); 55 | } 56 | 57 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 58 | #else 59 | 60 | { 61 | constexpr auto w = test, Y>( 1 ); 62 | STATIC_ASSERT( w == 1 ); 63 | } 64 | 65 | #endif 66 | 67 | { 68 | constexpr auto w = test, int>( 1 ); 69 | STATIC_ASSERT( w == 1 ); 70 | } 71 | 72 | { 73 | constexpr auto w = test, float>( 3.0f ); 74 | STATIC_ASSERT( w == 3.0f ); 75 | } 76 | 77 | { 78 | constexpr auto w = test, float>( 3.0f ); 79 | STATIC_ASSERT( w == 3.0f ); 80 | } 81 | 82 | { 83 | constexpr auto w = test, X>( 1 ); 84 | STATIC_ASSERT( w == 1 ); 85 | } 86 | 87 | { 88 | constexpr auto w = test, X>( X(1) ); 89 | STATIC_ASSERT( w == 1 ); 90 | } 91 | 92 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 93 | #else 94 | 95 | { 96 | constexpr auto w = test, Y>( 1 ); 97 | STATIC_ASSERT( w == 1 ); 98 | } 99 | 100 | { 101 | constexpr auto w = test, Y>( Y(1) ); 102 | STATIC_ASSERT( w == 1 ); 103 | } 104 | 105 | #endif 106 | } 107 | -------------------------------------------------------------------------------- /test/variant_move_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | 12 | using namespace boost::variant2; 13 | 14 | struct X 15 | { 16 | int v; 17 | X() = default; 18 | constexpr X( int v ): v( v ) {} 19 | constexpr operator int() const { return v; } 20 | }; 21 | 22 | struct Y 23 | { 24 | int v; 25 | constexpr Y(): v() {} 26 | constexpr Y( int v ): v( v ) {} 27 | constexpr operator int() const { return v; } 28 | }; 29 | 30 | enum E 31 | { 32 | v 33 | }; 34 | 35 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 36 | 37 | template constexpr T test( V&& v ) 38 | { 39 | V v2( std::forward(v) ); 40 | return get( v2 ); 41 | } 42 | 43 | int main() 44 | { 45 | { 46 | constexpr auto w = test( variant( 1 ) ); 47 | STATIC_ASSERT( w == 1 ); 48 | } 49 | 50 | { 51 | constexpr auto w = test( variant( 1 ) ); 52 | STATIC_ASSERT( w == 1 ); 53 | } 54 | 55 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 56 | #else 57 | 58 | { 59 | constexpr auto w = test( variant( 1 ) ); 60 | STATIC_ASSERT( w == 1 ); 61 | } 62 | 63 | #endif 64 | 65 | { 66 | constexpr auto w = test( variant( 1 ) ); 67 | STATIC_ASSERT( w == 1 ); 68 | } 69 | 70 | { 71 | constexpr auto w = test( variant( 3.0f ) ); 72 | STATIC_ASSERT( w == 3.0f ); 73 | } 74 | 75 | { 76 | constexpr auto w = test( variant( 3.0f ) ); 77 | STATIC_ASSERT( w == 3.0f ); 78 | } 79 | 80 | { 81 | constexpr auto w = test( variant( 1 ) ); 82 | STATIC_ASSERT( w == 1 ); 83 | } 84 | 85 | { 86 | constexpr auto w = test( variant( X(1) ) ); 87 | STATIC_ASSERT( w == 1 ); 88 | } 89 | 90 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 91 | #else 92 | 93 | { 94 | constexpr auto w = test( variant( 1 ) ); 95 | STATIC_ASSERT( w == 1 ); 96 | } 97 | 98 | { 99 | constexpr auto w = test( variant( Y(1) ) ); 100 | STATIC_ASSERT( w == 1 ); 101 | } 102 | 103 | #endif 104 | } 105 | -------------------------------------------------------------------------------- /test/variant_trivial.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #if defined(_MSC_VER) && _MSC_VER < 1910 6 | # pragma warning(disable: 4503) // decorated name length exceeded 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | using namespace boost::mp11; 16 | 17 | // 18 | 19 | struct D 20 | { 21 | ~D() noexcept {} 22 | }; 23 | 24 | struct CC1 25 | { 26 | CC1( CC1 const& ) noexcept {} 27 | }; 28 | 29 | struct CC2 30 | { 31 | CC2( CC2 const& ) = delete; 32 | }; 33 | 34 | struct MC1 35 | { 36 | MC1( MC1 && ) noexcept {} 37 | }; 38 | 39 | struct MC2 40 | { 41 | MC2( MC2 && ) = delete; 42 | }; 43 | 44 | struct CA1 45 | { 46 | CA1& operator=( CA1 const& ) noexcept { return *this; } 47 | }; 48 | 49 | struct CA2 50 | { 51 | CA2& operator=( CA2 const& ) = delete; 52 | }; 53 | 54 | struct MA1 55 | { 56 | MA1& operator=( MA1 && ) noexcept { return *this; } 57 | }; 58 | 59 | struct MA2 60 | { 61 | MA2& operator=( MA2 && ) = delete; 62 | }; 63 | 64 | using namespace boost::variant2; 65 | namespace v2d = boost::variant2::detail; 66 | 67 | struct test 68 | { 69 | template void operator()( mp_list ) const noexcept 70 | { 71 | using U = mp_inherit; 72 | 73 | #if !BOOST_WORKAROUND( __GNUC__, < 5 ) 74 | 75 | BOOST_TEST_EQ( v2d::is_trivially_copy_constructible>::value, v2d::is_trivially_copy_constructible::value ); 76 | BOOST_TEST_EQ( v2d::is_trivially_copy_assignable>::value, std::is_trivially_destructible::value && v2d::is_trivially_copy_constructible::value && v2d::is_trivially_copy_assignable::value ); 77 | 78 | #endif 79 | 80 | BOOST_TEST_EQ( std::is_trivially_destructible>::value, std::is_trivially_destructible::value ); 81 | 82 | #if !BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000) 83 | 84 | BOOST_TEST_EQ( v2d::is_trivially_move_constructible>::value, v2d::is_trivially_move_constructible::value ); 85 | BOOST_TEST_EQ( v2d::is_trivially_move_assignable>::value, std::is_trivially_destructible::value && v2d::is_trivially_move_constructible::value && v2d::is_trivially_move_assignable::value ); 86 | 87 | #endif 88 | } 89 | }; 90 | 91 | int main() 92 | { 93 | mp_for_each< mp_power_set< mp_list > >( test() ); 94 | return boost::report_errors(); 95 | } 96 | -------------------------------------------------------------------------------- /test/variant_many_types.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2020 Peter Dimov. 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // https://www.boost.org/LICENSE_1_0.txt 5 | 6 | #if defined(_MSC_VER) 7 | # pragma warning( disable: 4503 ) // decorated name length exceeded 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace boost::mp11; 15 | 16 | template struct X 17 | { 18 | static int const value = I::value; 19 | int v_; 20 | }; 21 | 22 | template int const X::value; 23 | 24 | template struct Y 25 | { 26 | static int const value = I::value; 27 | int v_; 28 | 29 | Y() = default; 30 | Y( Y const& ) = default; 31 | 32 | explicit Y( int v ): v_( v ) {} 33 | 34 | Y& operator=( Y const& ) noexcept = default; 35 | 36 | Y& operator=( Y&& r ) noexcept 37 | { 38 | v_ = r.v_; 39 | return *this; 40 | } 41 | }; 42 | 43 | template int const Y::value; 44 | 45 | template struct Z 46 | { 47 | static int const value = I::value; 48 | int v_; 49 | 50 | ~Z() {} 51 | }; 52 | 53 | template int const Z::value; 54 | 55 | template struct F1 56 | { 57 | template void operator()( T ) const 58 | { 59 | int const i = T::value; 60 | 61 | T t{ i * 2 }; 62 | 63 | using boost::variant2::get; 64 | 65 | { 66 | V v( t ); 67 | 68 | BOOST_TEST_EQ( v.index(), i ); 69 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 70 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 71 | } 72 | 73 | { 74 | V const v( t ); 75 | 76 | BOOST_TEST_EQ( v.index(), i ); 77 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 78 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 79 | } 80 | 81 | { 82 | V v; 83 | 84 | v = t; 85 | 86 | BOOST_TEST_EQ( v.index(), i ); 87 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 88 | BOOST_TEST_EQ( get( v ).v_, t.v_ ); 89 | } 90 | } 91 | }; 92 | 93 | template void test() 94 | { 95 | mp_for_each( F1() ); 96 | } 97 | 98 | int main() 99 | { 100 | int const N = 32; 101 | 102 | using V = mp_rename, boost::variant2::variant>; 103 | 104 | test< mp_transform >(); 105 | test< mp_transform >(); 106 | test< mp_transform >(); 107 | 108 | return boost::report_errors(); 109 | } 110 | -------------------------------------------------------------------------------- /test/variant_eq_ne.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | }; 21 | 22 | inline bool operator==( X const&, X const& ) { return false; } 23 | inline bool operator!=( X const&, X const& ) { return false; } 24 | 25 | int main() 26 | { 27 | { 28 | variant v1, v2, v3( 1 ), v4( 1 ); 29 | 30 | BOOST_TEST( v1 == v2 ); 31 | BOOST_TEST_NOT( v1 != v2 ); 32 | 33 | BOOST_TEST( v1 != v3 ); 34 | BOOST_TEST_NOT( v1 == v3 ); 35 | 36 | BOOST_TEST( v3 == v4 ); 37 | BOOST_TEST_NOT( v3 != v4 ); 38 | } 39 | 40 | { 41 | variant v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); 42 | 43 | BOOST_TEST( v1 == v2 ); 44 | BOOST_TEST_NOT( v1 != v2 ); 45 | 46 | BOOST_TEST( v1 != v3 ); 47 | BOOST_TEST_NOT( v1 == v3 ); 48 | 49 | BOOST_TEST( v3 == v4 ); 50 | BOOST_TEST_NOT( v3 != v4 ); 51 | 52 | BOOST_TEST( v1 != v5 ); 53 | BOOST_TEST_NOT( v1 == v5 ); 54 | 55 | BOOST_TEST( v3 != v5 ); 56 | BOOST_TEST_NOT( v3 == v5 ); 57 | 58 | BOOST_TEST( v5 == v6 ); 59 | BOOST_TEST_NOT( v5 != v6 ); 60 | } 61 | 62 | { 63 | variant v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); 64 | 65 | BOOST_TEST( v1 == v2 ); 66 | BOOST_TEST_NOT( v1 != v2 ); 67 | 68 | BOOST_TEST( v1 != v3 ); 69 | BOOST_TEST_NOT( v1 == v3 ); 70 | 71 | BOOST_TEST( v3 == v4 ); 72 | BOOST_TEST_NOT( v3 != v4 ); 73 | 74 | BOOST_TEST( v1 != v5 ); 75 | BOOST_TEST_NOT( v1 == v5 ); 76 | 77 | BOOST_TEST( v3 != v5 ); 78 | BOOST_TEST_NOT( v3 == v5 ); 79 | 80 | BOOST_TEST( v5 == v6 ); 81 | BOOST_TEST_NOT( v5 != v6 ); 82 | } 83 | 84 | { 85 | variant v1, v2; 86 | 87 | BOOST_TEST_NOT( v1 == v2 ); 88 | BOOST_TEST_NOT( v1 != v2 ); 89 | } 90 | 91 | { 92 | variant v1, v2; 93 | 94 | BOOST_TEST( v1 == v2 ); 95 | BOOST_TEST_NOT( v1 != v2 ); 96 | } 97 | 98 | return boost::report_errors(); 99 | } 100 | -------------------------------------------------------------------------------- /test/variant_get_by_index_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | 12 | using namespace boost::variant2; 13 | 14 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 15 | 16 | #if BOOST_WORKAROUND(BOOST_GCC, < 50000) 17 | # define STATIC_ASSERT_IF(...) 18 | #else 19 | # define STATIC_ASSERT_IF(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 20 | #endif 21 | 22 | int main() 23 | { 24 | { 25 | constexpr variant v; 26 | 27 | STATIC_ASSERT( get<0>(v) == 0 ); 28 | 29 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 30 | } 31 | 32 | { 33 | constexpr variant v( 1 ); 34 | 35 | STATIC_ASSERT( get<0>(v) == 1 ); 36 | 37 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 38 | } 39 | 40 | { 41 | constexpr variant v; 42 | 43 | STATIC_ASSERT( get<0>(v) == 0 ); 44 | 45 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 46 | STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); 47 | } 48 | 49 | { 50 | constexpr variant v( 1 ); 51 | 52 | STATIC_ASSERT( get<0>(v) == 1 ); 53 | 54 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 55 | STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); 56 | } 57 | 58 | { 59 | constexpr variant v( 3.14f ); 60 | 61 | STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD 62 | 63 | STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); 64 | STATIC_ASSERT_IF( get_if<1>(&v) == &get<1>(v) ); 65 | } 66 | 67 | { 68 | constexpr variant v; 69 | 70 | STATIC_ASSERT( get<0>(v) == 0 ); 71 | 72 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 73 | STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); 74 | STATIC_ASSERT_IF( get_if<2>(&v) == nullptr ); 75 | } 76 | 77 | { 78 | constexpr variant v( 1 ); 79 | 80 | STATIC_ASSERT( get<0>(v) == 1 ); 81 | 82 | STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); 83 | STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); 84 | STATIC_ASSERT_IF( get_if<2>(&v) == nullptr ); 85 | } 86 | 87 | { 88 | constexpr variant v( 3.14f ); 89 | 90 | STATIC_ASSERT( get<2>(v) == (float)3.14f ); 91 | 92 | STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); 93 | STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); 94 | STATIC_ASSERT_IF( get_if<2>(&v) == &get<2>(v) ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /test/variant_copy_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | int v; 16 | X() = default; 17 | constexpr X( int v ): v( v ) {} 18 | constexpr operator int() const { return v; } 19 | }; 20 | 21 | struct Y 22 | { 23 | int v; 24 | constexpr Y(): v() {} 25 | constexpr Y( int v ): v( v ) {} 26 | constexpr operator int() const { return v; } 27 | }; 28 | 29 | enum E 30 | { 31 | v 32 | }; 33 | 34 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 35 | 36 | template constexpr T test( V const v ) 37 | { 38 | return get( v ); 39 | } 40 | 41 | int main() 42 | { 43 | { 44 | constexpr variant v( 1 ); 45 | constexpr auto w = test( v ); 46 | STATIC_ASSERT( w == 1 ); 47 | } 48 | 49 | { 50 | constexpr variant v( 1 ); 51 | constexpr auto w = test( v ); 52 | STATIC_ASSERT( w == 1 ); 53 | } 54 | 55 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 56 | #else 57 | 58 | { 59 | constexpr variant v( 1 ); 60 | constexpr auto w = test( v ); 61 | STATIC_ASSERT( w == 1 ); 62 | } 63 | 64 | #endif 65 | 66 | { 67 | constexpr variant v( 1 ); 68 | constexpr auto w = test( v ); 69 | STATIC_ASSERT( w == 1 ); 70 | } 71 | 72 | { 73 | constexpr variant v( 3.0f ); 74 | constexpr auto w = test( v ); 75 | STATIC_ASSERT( w == 3.0f ); 76 | } 77 | 78 | { 79 | constexpr variant v( 3.0f ); 80 | constexpr auto w = test( v ); 81 | STATIC_ASSERT( w == 3.0f ); 82 | } 83 | 84 | { 85 | constexpr variant v( 1 ); 86 | constexpr auto w = test( v ); 87 | STATIC_ASSERT( w == 1 ); 88 | } 89 | 90 | { 91 | constexpr variant v( X(1) ); 92 | constexpr auto w = test( v ); 93 | STATIC_ASSERT( w == 1 ); 94 | } 95 | 96 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 97 | #else 98 | 99 | { 100 | constexpr variant v( 1 ); 101 | constexpr auto w = test( v ); 102 | STATIC_ASSERT( w == 1 ); 103 | } 104 | 105 | { 106 | constexpr variant v( Y(1) ); 107 | constexpr auto w = test( v ); 108 | STATIC_ASSERT( w == 1 ); 109 | } 110 | 111 | #endif 112 | } 113 | -------------------------------------------------------------------------------- /test/variant_move_assign_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | 12 | using namespace boost::variant2; 13 | 14 | struct X 15 | { 16 | int v; 17 | X() = default; 18 | constexpr X( int v ): v( v ) {} 19 | constexpr operator int() const { return v; } 20 | }; 21 | 22 | struct Y 23 | { 24 | int v; 25 | constexpr Y(): v() {} 26 | constexpr Y( int v ): v( v ) {} 27 | constexpr operator int() const { return v; } 28 | }; 29 | 30 | enum E 31 | { 32 | v 33 | }; 34 | 35 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 36 | 37 | template constexpr T test( A&& a ) 38 | { 39 | V v; 40 | 41 | v = std::forward(a); 42 | 43 | return get(v); 44 | } 45 | 46 | int main() 47 | { 48 | { 49 | constexpr auto w = test, int>( variant( 1 ) ); 50 | STATIC_ASSERT( w == 1 ); 51 | } 52 | 53 | { 54 | constexpr auto w = test, X>( variant( 1 ) ); 55 | STATIC_ASSERT( w == 1 ); 56 | } 57 | 58 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 59 | #else 60 | 61 | { 62 | constexpr auto w = test, Y>( variant( 1 ) ); 63 | STATIC_ASSERT( w == 1 ); 64 | } 65 | 66 | #endif 67 | 68 | { 69 | constexpr auto w = test, int>( variant( 1 ) ); 70 | STATIC_ASSERT( w == 1 ); 71 | } 72 | 73 | { 74 | constexpr auto w = test, float>( variant( 3.0f ) ); 75 | STATIC_ASSERT( w == 3.0f ); 76 | } 77 | 78 | { 79 | constexpr auto w = test, float>( variant( 3.0f ) ); 80 | STATIC_ASSERT( w == 3.0f ); 81 | } 82 | 83 | { 84 | constexpr auto w = test, X>( variant( 1 ) ); 85 | STATIC_ASSERT( w == 1 ); 86 | } 87 | 88 | { 89 | constexpr auto w = test, X>( variant( X(1) ) ); 90 | STATIC_ASSERT( w == 1 ); 91 | } 92 | 93 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 94 | #else 95 | 96 | { 97 | constexpr auto w = test, Y>( variant( 1 ) ); 98 | STATIC_ASSERT( w == 1 ); 99 | } 100 | 101 | { 102 | constexpr auto w = test, Y>( variant( Y(1) ) ); 103 | STATIC_ASSERT( w == 1 ); 104 | } 105 | 106 | #endif 107 | } 108 | -------------------------------------------------------------------------------- /test/variant_visit_r.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data 11 | #endif 12 | 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct F1 19 | { 20 | template T1 operator()( T1 t1 ) const 21 | { 22 | return t1; 23 | } 24 | }; 25 | 26 | struct F2 27 | { 28 | template auto operator()( T1 t1, T2 t2 ) const -> decltype( t1 + t2 ) 29 | { 30 | return t1 + t2; 31 | } 32 | }; 33 | 34 | struct F3 35 | { 36 | template auto operator()( T1 t1, T2 t2, T3 t3 ) const -> decltype( t1 + t2 + t3 ) 37 | { 38 | return t1 + t2 + t3; 39 | } 40 | }; 41 | 42 | struct F4 43 | { 44 | template auto operator()( T1 t1, T2 t2, T3 t3, T4 t4 ) const -> decltype( t1 + t2 + t3 + t4 ) 45 | { 46 | return t1 + t2 + t3 + t4; 47 | } 48 | }; 49 | 50 | int main() 51 | { 52 | { 53 | BOOST_TEST_EQ( (visit( []{ return 3.14f; } )), 3 ); 54 | } 55 | 56 | { 57 | variant v( 1 ); 58 | 59 | BOOST_TEST_EQ( visit( F1(), v ), 1 ); 60 | BOOST_TEST_EQ( visit( F1(), v ), 1.0f ); 61 | } 62 | 63 | { 64 | variant const v( 3.125f ); 65 | 66 | BOOST_TEST_EQ( visit( F1(), v ), 3 ); 67 | BOOST_TEST_EQ( visit( F1(), v ), 3.125f ); 68 | } 69 | 70 | { 71 | variant v1( 1 ); 72 | variant const v2( 3.125f ); 73 | 74 | BOOST_TEST_EQ( visit( F2(), v1, v2 ), 4 ); 75 | BOOST_TEST_EQ( visit( F2(), v1, v2 ), 1 + 3.125f ); 76 | } 77 | 78 | { 79 | variant v1( 1 ); 80 | variant const v2( 3.14f ); 81 | variant v3( 6.28 ); 82 | 83 | BOOST_TEST_EQ( visit( F3(), v1, v2, v3 ), 10 ); 84 | BOOST_TEST_EQ( visit( F3(), v1, v2, v3 ), static_cast( 1 + 3.14f + 6.28 ) ); 85 | } 86 | 87 | { 88 | variant v1( 1 ); 89 | variant const v2( 3.14f ); 90 | variant v3( 6.28 ); 91 | variant const v4( 'A' ); 92 | 93 | BOOST_TEST_EQ( visit( F4(), v1, v2, v3, v4 ), 10 + 'A' ); 94 | BOOST_TEST_EQ( visit( F4(), v1, v2, v3, v4 ), static_cast( 1 + 3.14f + 6.28 + 'A' ) ); 95 | } 96 | 97 | return boost::report_errors(); 98 | } 99 | -------------------------------------------------------------------------------- /test/variant_eq_ne_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017, 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | using namespace boost::variant2; 11 | 12 | #if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) 13 | 14 | #include 15 | 16 | BOOST_PRAGMA_MESSAGE("Skipping constexpr op==, op!= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") 17 | 18 | int main() {} 19 | 20 | #else 21 | 22 | struct X 23 | { 24 | }; 25 | 26 | inline constexpr bool operator==( X const&, X const& ) { return false; } 27 | inline constexpr bool operator!=( X const&, X const& ) { return false; } 28 | 29 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 30 | 31 | int main() 32 | { 33 | { 34 | constexpr variant v1, v2, v3( 1 ), v4( 1 ); 35 | 36 | STATIC_ASSERT( v1 == v2 ); 37 | STATIC_ASSERT( !(v1 != v2) ); 38 | 39 | STATIC_ASSERT( v1 != v3 ); 40 | STATIC_ASSERT( !(v1 == v3) ); 41 | 42 | STATIC_ASSERT( v3 == v4 ); 43 | STATIC_ASSERT( !(v3 != v4) ); 44 | } 45 | 46 | { 47 | constexpr variant v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); 48 | 49 | STATIC_ASSERT( v1 == v2 ); 50 | STATIC_ASSERT( !(v1 != v2) ); 51 | 52 | STATIC_ASSERT( v1 != v3 ); 53 | STATIC_ASSERT( !(v1 == v3) ); 54 | 55 | STATIC_ASSERT( v3 == v4 ); 56 | STATIC_ASSERT( !(v3 != v4) ); 57 | 58 | STATIC_ASSERT( v1 != v5 ); 59 | STATIC_ASSERT( !(v1 == v5) ); 60 | 61 | STATIC_ASSERT( v3 != v5 ); 62 | STATIC_ASSERT( !(v3 == v5) ); 63 | 64 | STATIC_ASSERT( v5 == v6 ); 65 | STATIC_ASSERT( !(v5 != v6) ); 66 | } 67 | 68 | { 69 | constexpr variant v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); 70 | 71 | STATIC_ASSERT( v1 == v2 ); 72 | STATIC_ASSERT( !(v1 != v2) ); 73 | 74 | STATIC_ASSERT( v1 != v3 ); 75 | STATIC_ASSERT( !(v1 == v3) ); 76 | 77 | STATIC_ASSERT( v3 == v4 ); 78 | STATIC_ASSERT( !(v3 != v4) ); 79 | 80 | STATIC_ASSERT( v1 != v5 ); 81 | STATIC_ASSERT( !(v1 == v5) ); 82 | 83 | STATIC_ASSERT( v3 != v5 ); 84 | STATIC_ASSERT( !(v3 == v5) ); 85 | 86 | STATIC_ASSERT( v5 == v6 ); 87 | STATIC_ASSERT( !(v5 != v6) ); 88 | } 89 | 90 | { 91 | constexpr variant v1, v2; 92 | 93 | STATIC_ASSERT( !(v1 == v2) ); 94 | STATIC_ASSERT( !(v1 != v2) ); 95 | } 96 | 97 | { 98 | constexpr variant v1, v2; 99 | 100 | STATIC_ASSERT( v1 == v2 ); 101 | STATIC_ASSERT( !(v1 != v2) ); 102 | } 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /test/variant_lt_gt_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017, 2019 Peter Dimov 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | using namespace boost::variant2; 11 | 12 | #if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) 13 | 14 | #include 15 | 16 | BOOST_PRAGMA_MESSAGE("Skipping constexpr op<, op<= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") 17 | 18 | int main() {} 19 | 20 | #else 21 | 22 | struct X 23 | { 24 | }; 25 | 26 | inline constexpr bool operator<( X const&, X const& ) { return false; } 27 | inline constexpr bool operator>( X const&, X const& ) { return false; } 28 | inline constexpr bool operator<=( X const&, X const& ) { return false; } 29 | inline constexpr bool operator>=( X const&, X const& ) { return false; } 30 | 31 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 32 | 33 | #define TEST_EQ( v1, v2 ) \ 34 | STATIC_ASSERT( !(v1 < v2) ); \ 35 | STATIC_ASSERT( !(v1 > v2) ); \ 36 | STATIC_ASSERT( v1 <= v2 ); \ 37 | STATIC_ASSERT( v1 >= v2 ); 38 | 39 | #define TEST_LE( v1, v3 ) \ 40 | STATIC_ASSERT( v1 < v3 ); \ 41 | STATIC_ASSERT( v3 > v1 ); \ 42 | STATIC_ASSERT( !(v1 > v3) ); \ 43 | STATIC_ASSERT( !(v3 < v1) ); \ 44 | STATIC_ASSERT( v1 <= v3 ); \ 45 | STATIC_ASSERT( v3 >= v1 ); \ 46 | STATIC_ASSERT( !(v1 >= v3) ); \ 47 | STATIC_ASSERT( !(v3 <= v1) ); 48 | 49 | int main() 50 | { 51 | { 52 | constexpr variant v1, v2, v3( 1 ), v4( 1 ); 53 | 54 | TEST_EQ( v1, v2 ) 55 | TEST_LE( v1, v3 ) 56 | TEST_EQ( v3, v4 ) 57 | } 58 | 59 | { 60 | constexpr variant v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); 61 | 62 | TEST_EQ( v1, v2 ) 63 | TEST_LE( v1, v3 ) 64 | TEST_EQ( v3, v4 ) 65 | TEST_LE( v1, v5 ) 66 | TEST_LE( v3, v5 ) 67 | TEST_EQ( v5, v6 ) 68 | } 69 | 70 | { 71 | constexpr variant v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); 72 | 73 | TEST_EQ( v1, v2 ) 74 | TEST_LE( v1, v3 ) 75 | TEST_EQ( v3, v4 ) 76 | TEST_LE( v1, v5 ) 77 | TEST_LE( v3, v5 ) 78 | TEST_EQ( v5, v6 ) 79 | } 80 | 81 | { 82 | constexpr variant v1, v2; 83 | 84 | STATIC_ASSERT( !(v1 < v2) ); 85 | STATIC_ASSERT( !(v1 > v2) ); 86 | STATIC_ASSERT( !(v1 <= v2) ); 87 | STATIC_ASSERT( !(v1 >= v2) ); 88 | } 89 | 90 | { 91 | constexpr variant v1, v2; 92 | 93 | STATIC_ASSERT( !(v1 < v2) ); 94 | STATIC_ASSERT( !(v1 > v2) ); 95 | STATIC_ASSERT( v1 <= v2 ); 96 | STATIC_ASSERT( v1 >= v2 ); 97 | } 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /test/variant_value_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | constexpr operator int() const { return 2; } 16 | }; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | int main() 21 | { 22 | { 23 | constexpr variant v( 1 ); 24 | 25 | STATIC_ASSERT( v.index() == 0 ); 26 | STATIC_ASSERT( get<0>(v) == 1 ); 27 | } 28 | 29 | { 30 | constexpr variant v( 'a' ); 31 | 32 | STATIC_ASSERT( v.index() == 0 ); 33 | STATIC_ASSERT( get<0>(v) == 'a' ); 34 | } 35 | 36 | { 37 | constexpr variant v( X{} ); 38 | 39 | STATIC_ASSERT( v.index() == 0 ); 40 | STATIC_ASSERT( get<0>(v) == 2 ); 41 | } 42 | 43 | { 44 | constexpr variant v( 1 ); 45 | 46 | STATIC_ASSERT( v.index() == 0 ); 47 | STATIC_ASSERT( get<0>(v) == 1 ); 48 | } 49 | 50 | { 51 | constexpr variant v( 'a' ); 52 | 53 | STATIC_ASSERT( v.index() == 0 ); 54 | STATIC_ASSERT( get<0>(v) == 'a' ); 55 | } 56 | 57 | { 58 | constexpr variant v( X{} ); 59 | 60 | STATIC_ASSERT( v.index() == 0 ); 61 | STATIC_ASSERT( get<0>(v) == 2 ); 62 | } 63 | 64 | { 65 | constexpr variant v( 1 ); 66 | 67 | STATIC_ASSERT( v.index() == 0 ); 68 | STATIC_ASSERT( holds_alternative(v) ); 69 | STATIC_ASSERT( get<0>(v) == 1 ); 70 | } 71 | 72 | { 73 | constexpr variant v( 'a' ); 74 | 75 | STATIC_ASSERT( v.index() == 0 ); 76 | STATIC_ASSERT( holds_alternative(v) ); 77 | STATIC_ASSERT( get<0>(v) == 'a' ); 78 | } 79 | 80 | { 81 | constexpr variant v( 3.14f ); 82 | 83 | STATIC_ASSERT( v.index() == 1 ); 84 | STATIC_ASSERT( holds_alternative(v) ); 85 | STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD 86 | } 87 | 88 | { 89 | constexpr variant v( X{} ); 90 | 91 | STATIC_ASSERT( v.index() == 2 ); 92 | STATIC_ASSERT( holds_alternative(v) ); 93 | } 94 | 95 | { 96 | constexpr variant v( 3.14f ); 97 | 98 | STATIC_ASSERT( v.index() == 2 ); 99 | STATIC_ASSERT( holds_alternative(v) ); 100 | STATIC_ASSERT( get<2>(v) == (float)3.14f ); 101 | } 102 | 103 | { 104 | constexpr variant v( X{} ); 105 | 106 | STATIC_ASSERT( v.index() == 3 ); 107 | STATIC_ASSERT( holds_alternative(v) ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/variant_special.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #if defined(_MSC_VER) && _MSC_VER < 1910 6 | # pragma warning(disable: 4503) // decorated name length exceeded 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | using namespace boost::mp11; 16 | 17 | // 18 | 19 | using namespace boost::variant2; 20 | 21 | struct D 22 | { 23 | ~D() noexcept {} 24 | }; 25 | 26 | struct CC1 27 | { 28 | CC1( CC1 const& ) {} 29 | }; 30 | 31 | struct CC2 32 | { 33 | CC2( CC2 const& ) = delete; 34 | }; 35 | 36 | struct MC1 37 | { 38 | MC1( MC1 && ) {} 39 | }; 40 | 41 | struct MC2 42 | { 43 | MC2( MC2 && ) = delete; 44 | }; 45 | 46 | struct CA1 47 | { 48 | CA1& operator=( CA1 const& ) { return *this; } 49 | }; 50 | 51 | struct CA2 52 | { 53 | CA2& operator=( CA2 const& ) = delete; 54 | }; 55 | 56 | struct MA1 57 | { 58 | MA1& operator=( MA1 && ) { return *this; } 59 | }; 60 | 61 | struct MA2 62 | { 63 | MA2& operator=( MA2 && ) = delete; 64 | }; 65 | 66 | struct test 67 | { 68 | template void operator()( mp_list ) const noexcept 69 | { 70 | using U = mp_inherit; 71 | 72 | #if !BOOST_WORKAROUND( __GNUC__, < 5 ) 73 | 74 | BOOST_TEST_EQ( std::is_copy_constructible>::value, std::is_copy_constructible::value ); 75 | BOOST_TEST_EQ( std::is_nothrow_copy_constructible>::value, std::is_nothrow_copy_constructible::value ); 76 | 77 | #endif 78 | 79 | #if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) 80 | 81 | BOOST_TEST_EQ( std::is_move_constructible>::value, std::is_move_constructible::value ); 82 | 83 | #else 84 | 85 | BOOST_TEST_GE( std::is_move_constructible>::value, std::is_move_constructible::value ); 86 | 87 | #endif 88 | 89 | BOOST_TEST_EQ( std::is_nothrow_move_constructible>::value, std::is_nothrow_move_constructible::value ); 90 | 91 | BOOST_TEST_EQ( std::is_copy_assignable>::value, std::is_copy_constructible::value && std::is_copy_assignable::value ); 92 | BOOST_TEST_EQ( std::is_nothrow_copy_assignable>::value, std::is_nothrow_copy_constructible::value && std::is_copy_assignable::value ); 93 | 94 | BOOST_TEST_EQ( std::is_move_assignable>::value, std::is_move_constructible::value && std::is_move_assignable::value ); 95 | BOOST_TEST_EQ( std::is_nothrow_move_assignable>::value, std::is_nothrow_move_constructible::value && std::is_move_assignable::value ); 96 | } 97 | }; 98 | 99 | int main() 100 | { 101 | mp_for_each< mp_power_set< mp_list > >( test() ); 102 | return boost::report_errors(); 103 | } 104 | -------------------------------------------------------------------------------- /test/variant_copy_assign_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | int v; 16 | X() = default; 17 | constexpr X( int v ): v( v ) {} 18 | constexpr operator int() const { return v; } 19 | }; 20 | 21 | struct Y 22 | { 23 | int v; 24 | constexpr Y(): v() {} 25 | constexpr Y( int v ): v( v ) {} 26 | constexpr operator int() const { return v; } 27 | }; 28 | 29 | enum E 30 | { 31 | v 32 | }; 33 | 34 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 35 | 36 | template constexpr T test( A const& a ) 37 | { 38 | V v; 39 | 40 | v = a; 41 | 42 | return get(v); 43 | } 44 | 45 | int main() 46 | { 47 | { 48 | constexpr variant v( 1 ); 49 | constexpr auto w = test, int>( v ); 50 | STATIC_ASSERT( w == 1 ); 51 | } 52 | 53 | { 54 | constexpr variant v( 1 ); 55 | constexpr auto w = test, X>( v ); 56 | STATIC_ASSERT( w == 1 ); 57 | } 58 | 59 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 60 | #else 61 | 62 | { 63 | constexpr variant v( 1 ); 64 | constexpr auto w = test, Y>( v ); 65 | STATIC_ASSERT( w == 1 ); 66 | } 67 | 68 | #endif 69 | 70 | { 71 | constexpr variant v( 1 ); 72 | constexpr auto w = test, int>( v ); 73 | STATIC_ASSERT( w == 1 ); 74 | } 75 | 76 | { 77 | constexpr variant v( 3.0f ); 78 | constexpr auto w = test, float>( v ); 79 | STATIC_ASSERT( w == 3.0f ); 80 | } 81 | 82 | { 83 | constexpr variant v( 3.0f ); 84 | constexpr auto w = test, float>( v ); 85 | STATIC_ASSERT( w == 3.0f ); 86 | } 87 | 88 | { 89 | constexpr variant v( 1 ); 90 | constexpr auto w = test, X>( v ); 91 | STATIC_ASSERT( w == 1 ); 92 | } 93 | 94 | { 95 | constexpr variant v( X(1) ); 96 | constexpr auto w = test, X>( v ); 97 | STATIC_ASSERT( w == 1 ); 98 | } 99 | 100 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 101 | #else 102 | 103 | { 104 | constexpr variant v( 1 ); 105 | constexpr auto w = test, Y>( v ); 106 | STATIC_ASSERT( w == 1 ); 107 | } 108 | 109 | { 110 | constexpr variant v( Y(1) ); 111 | constexpr auto w = test, Y>( v ); 112 | STATIC_ASSERT( w == 1 ); 113 | } 114 | 115 | #endif 116 | } 117 | -------------------------------------------------------------------------------- /test/variant_default_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | X(); 21 | }; 22 | 23 | struct Y 24 | { 25 | Y() = delete; 26 | }; 27 | 28 | int main() 29 | { 30 | { 31 | variant v; 32 | 33 | BOOST_TEST_EQ( v.index(), 0 ); 34 | BOOST_TEST_EQ( get<0>(v), 0 ); 35 | } 36 | 37 | { 38 | variant v; 39 | 40 | BOOST_TEST_EQ( v.index(), 0 ); 41 | BOOST_TEST_EQ( get<0>(v), 0 ); 42 | } 43 | 44 | { 45 | variant v; 46 | 47 | BOOST_TEST_EQ( v.index(), 0 ); 48 | BOOST_TEST_EQ( get<0>(v), 0 ); 49 | } 50 | 51 | { 52 | variant v; 53 | 54 | BOOST_TEST_EQ( v.index(), 0 ); 55 | BOOST_TEST_EQ( get<0>(v), 0 ); 56 | } 57 | 58 | { 59 | variant v; 60 | 61 | BOOST_TEST_EQ( v.index(), 0 ); 62 | BOOST_TEST_EQ( get<0>(v), std::string() ); 63 | } 64 | 65 | { 66 | variant v; 67 | 68 | BOOST_TEST_EQ( v.index(), 0 ); 69 | BOOST_TEST_EQ( get<0>(v), std::string() ); 70 | } 71 | 72 | { 73 | variant v; 74 | 75 | BOOST_TEST_EQ( v.index(), 0 ); 76 | BOOST_TEST_EQ( get<0>(v), std::string() ); 77 | } 78 | 79 | { 80 | variant v; 81 | 82 | BOOST_TEST_EQ( v.index(), 0 ); 83 | BOOST_TEST_EQ( get<0>(v), std::string() ); 84 | } 85 | 86 | { 87 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 88 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 89 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 90 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 91 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 92 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible>)); 93 | 94 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible>)); 95 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible>)); 96 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible>)); 97 | 98 | BOOST_TEST_TRAIT_TRUE((std::is_default_constructible>)); 99 | BOOST_TEST_TRAIT_FALSE((std::is_default_constructible>)); 100 | } 101 | 102 | return boost::report_errors(); 103 | } 104 | -------------------------------------------------------------------------------- /test/variant_value_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | operator int() const { return 2; } 21 | }; 22 | 23 | int main() 24 | { 25 | { 26 | variant v( 1 ); 27 | 28 | BOOST_TEST_EQ( v.index(), 0 ); 29 | BOOST_TEST_EQ( get<0>(v), 1 ); 30 | } 31 | 32 | { 33 | variant v( 'a' ); 34 | 35 | BOOST_TEST_EQ( v.index(), 0 ); 36 | BOOST_TEST_EQ( get<0>(v), 'a' ); 37 | } 38 | 39 | { 40 | variant v( X{} ); 41 | 42 | BOOST_TEST_EQ( v.index(), 0 ); 43 | BOOST_TEST_EQ( get<0>(v), 2 ); 44 | } 45 | 46 | { 47 | variant v( 1 ); 48 | 49 | BOOST_TEST_EQ( v.index(), 0 ); 50 | BOOST_TEST_EQ( get<0>(v), 1 ); 51 | } 52 | 53 | { 54 | variant v( 'a' ); 55 | 56 | BOOST_TEST_EQ( v.index(), 0 ); 57 | BOOST_TEST_EQ( get<0>(v), 'a' ); 58 | } 59 | 60 | { 61 | variant v( X{} ); 62 | 63 | BOOST_TEST_EQ( v.index(), 0 ); 64 | BOOST_TEST_EQ( get<0>(v), 2 ); 65 | } 66 | 67 | { 68 | variant v( 1 ); 69 | 70 | BOOST_TEST_EQ( v.index(), 0 ); 71 | BOOST_TEST( holds_alternative(v) ); 72 | BOOST_TEST_EQ( get<0>(v), 1 ); 73 | } 74 | 75 | { 76 | variant v( 'a' ); 77 | 78 | BOOST_TEST_EQ( v.index(), 0 ); 79 | BOOST_TEST( holds_alternative(v) ); 80 | BOOST_TEST_EQ( get<0>(v), 'a' ); 81 | } 82 | 83 | { 84 | variant v( X{} ); 85 | 86 | BOOST_TEST_EQ( v.index(), 0 ); 87 | BOOST_TEST( holds_alternative(v) ); 88 | BOOST_TEST_EQ( get<0>(v), 2 ); 89 | } 90 | 91 | { 92 | variant v( 3.14f ); 93 | 94 | BOOST_TEST_EQ( v.index(), 1 ); 95 | BOOST_TEST( holds_alternative(v) ); 96 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 97 | } 98 | 99 | { 100 | variant v( "text" ); 101 | 102 | BOOST_TEST_EQ( v.index(), 2 ); 103 | BOOST_TEST( holds_alternative(v) ); 104 | BOOST_TEST_EQ( get<2>(v), std::string("text") ); 105 | } 106 | 107 | { 108 | variant v( 3.14f ); 109 | 110 | BOOST_TEST_EQ( v.index(), 2 ); 111 | BOOST_TEST( holds_alternative(v) ); 112 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 113 | } 114 | 115 | { 116 | variant v( "text" ); 117 | 118 | BOOST_TEST_EQ( v.index(), 3 ); 119 | BOOST_TEST( holds_alternative(v) ); 120 | BOOST_TEST_EQ( get<3>(v), std::string("text") ); 121 | } 122 | 123 | return boost::report_errors(); 124 | } 125 | -------------------------------------------------------------------------------- /test/variant_in_place_type_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace boost::variant2; 14 | 15 | struct X 16 | { 17 | constexpr X() = default; 18 | constexpr explicit X(int, int) {} 19 | template X( in_place_type_t ) = delete; 20 | }; 21 | 22 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 23 | 24 | int main() 25 | { 26 | { 27 | constexpr variant v( in_place_type_t{} ); 28 | 29 | STATIC_ASSERT( v.index() == 0 ); 30 | STATIC_ASSERT( get<0>(v) == 0 ); 31 | 32 | STATIC_ASSERT( holds_alternative(v) ); 33 | } 34 | 35 | { 36 | constexpr variant v( in_place_type_t{} ); 37 | 38 | STATIC_ASSERT( v.index() == 0 ); 39 | 40 | STATIC_ASSERT( holds_alternative(v) ); 41 | } 42 | 43 | { 44 | constexpr variant v( in_place_type_t{}, 1 ); 45 | 46 | STATIC_ASSERT( v.index() == 0 ); 47 | STATIC_ASSERT( get<0>(v) == 1 ); 48 | 49 | STATIC_ASSERT( holds_alternative(v) ); 50 | } 51 | 52 | { 53 | constexpr variant v( in_place_type_t{} ); 54 | 55 | STATIC_ASSERT( v.index() == 0 ); 56 | STATIC_ASSERT( get<0>(v) == 0 ); 57 | 58 | STATIC_ASSERT( holds_alternative(v) ); 59 | } 60 | 61 | { 62 | constexpr variant v( in_place_type_t{}, 1 ); 63 | 64 | STATIC_ASSERT( v.index() == 0 ); 65 | STATIC_ASSERT( get<0>(v) == 1 ); 66 | 67 | STATIC_ASSERT( holds_alternative(v) ); 68 | } 69 | 70 | { 71 | constexpr variant v( in_place_type_t{} ); 72 | 73 | STATIC_ASSERT( v.index() == 1 ); 74 | STATIC_ASSERT( get<1>(v) == 0 ); 75 | 76 | STATIC_ASSERT( holds_alternative(v) ); 77 | } 78 | 79 | { 80 | constexpr variant v( in_place_type_t{}, 3.14f ); 81 | 82 | STATIC_ASSERT( v.index() == 1 ); 83 | STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD 84 | 85 | STATIC_ASSERT( holds_alternative(v) ); 86 | } 87 | 88 | { 89 | constexpr variant v( in_place_type_t{}, 3.14f ); 90 | 91 | STATIC_ASSERT( v.index() == 2 ); 92 | STATIC_ASSERT( get<2>(v) == (float)3.14f ); 93 | 94 | STATIC_ASSERT( holds_alternative(v) ); 95 | } 96 | 97 | { 98 | constexpr variant v( in_place_type_t{} ); 99 | 100 | STATIC_ASSERT( v.index() == 4 ); 101 | 102 | STATIC_ASSERT( holds_alternative(v) ); 103 | } 104 | 105 | #if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 120000) 106 | 107 | // no idea why this fails on g++ 10/11 108 | 109 | #else 110 | 111 | { 112 | constexpr variant v( in_place_type_t{}, 0, 0 ); 113 | 114 | STATIC_ASSERT( v.index() == 4 ); 115 | 116 | STATIC_ASSERT( holds_alternative(v) ); 117 | } 118 | 119 | #endif 120 | } 121 | -------------------------------------------------------------------------------- /test/variant_in_place_index_construct_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace boost::variant2; 14 | 15 | struct X 16 | { 17 | constexpr X() = default; 18 | constexpr explicit X(int, int) {} 19 | X( in_place_index_t<0> ) = delete; 20 | }; 21 | 22 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 23 | 24 | int main() 25 | { 26 | { 27 | constexpr variant v( in_place_index_t<0>{} ); 28 | 29 | STATIC_ASSERT( v.index() == 0 ); 30 | STATIC_ASSERT( get<0>(v) == 0 ); 31 | } 32 | 33 | { 34 | constexpr variant v( in_place_index_t<0>{} ); 35 | 36 | STATIC_ASSERT( v.index() == 0 ); 37 | } 38 | 39 | { 40 | constexpr variant v( in_place_index_t<0>{}, 1 ); 41 | 42 | STATIC_ASSERT( v.index() == 0 ); 43 | STATIC_ASSERT( get<0>(v) == 1 ); 44 | } 45 | 46 | { 47 | constexpr variant v( in_place_index_t<0>{} ); 48 | 49 | STATIC_ASSERT( v.index() == 0 ); 50 | STATIC_ASSERT( get<0>(v) == 0 ); 51 | } 52 | 53 | { 54 | constexpr variant v( in_place_index_t<0>{}, 1 ); 55 | 56 | STATIC_ASSERT( v.index() == 0 ); 57 | STATIC_ASSERT( get<0>(v) == 1 ); 58 | } 59 | 60 | { 61 | constexpr variant v( in_place_index_t<1>{} ); 62 | 63 | STATIC_ASSERT( v.index() == 1 ); 64 | STATIC_ASSERT( get<1>(v) == 0 ); 65 | } 66 | 67 | { 68 | constexpr variant v( in_place_index_t<1>{}, 3.14f ); 69 | 70 | STATIC_ASSERT( v.index() == 1 ); 71 | STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD 72 | } 73 | 74 | { 75 | constexpr variant v( in_place_index_t<0>{}, 1 ); 76 | 77 | STATIC_ASSERT( v.index() == 0 ); 78 | STATIC_ASSERT( get<0>(v) == 1 ); 79 | } 80 | 81 | { 82 | constexpr variant v( in_place_index_t<1>{}, 1 ); 83 | 84 | STATIC_ASSERT( v.index() == 1 ); 85 | STATIC_ASSERT( get<1>(v) == 1 ); 86 | } 87 | 88 | { 89 | constexpr variant v( in_place_index_t<2>{}, 3.14f ); 90 | 91 | STATIC_ASSERT( v.index() == 2 ); 92 | STATIC_ASSERT( get<2>(v) == (float)3.14f ); 93 | } 94 | 95 | { 96 | constexpr variant v( in_place_index_t<3>{}, 3.14f ); 97 | 98 | STATIC_ASSERT( v.index() == 3 ); 99 | STATIC_ASSERT( get<3>(v) == (float)3.14f ); 100 | } 101 | 102 | { 103 | constexpr variant v( in_place_index_t<4>{} ); 104 | 105 | STATIC_ASSERT( v.index() == 4 ); 106 | } 107 | 108 | #if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 120000) 109 | 110 | // no idea why this fails on g++ 10/11 111 | 112 | #else 113 | 114 | { 115 | constexpr variant v( in_place_index_t<5>{}, 0, 0 ); 116 | 117 | STATIC_ASSERT( v.index() == 5 ); 118 | } 119 | 120 | #endif 121 | } 122 | -------------------------------------------------------------------------------- /test/variant_emplace_index_cx.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | 11 | using namespace boost::variant2; 12 | 13 | struct X 14 | { 15 | int v; 16 | X() = default; 17 | constexpr explicit X( int v ): v( v ) {} 18 | constexpr operator int() const { return v; } 19 | }; 20 | 21 | struct Y 22 | { 23 | int v; 24 | constexpr Y(): v() {} 25 | constexpr explicit Y( int v ): v( v ) {} 26 | constexpr operator int() const { return v; } 27 | }; 28 | 29 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 30 | 31 | template constexpr A test( A const& a ) 32 | { 33 | V v; 34 | 35 | v.template emplace( a ); 36 | 37 | return get(v); 38 | } 39 | 40 | int main() 41 | { 42 | { 43 | constexpr auto w = test, 0>( 1 ); 44 | STATIC_ASSERT( w == 1 ); 45 | } 46 | 47 | { 48 | constexpr auto w = test, 0>( 1 ); 49 | STATIC_ASSERT( w == 1 ); 50 | } 51 | 52 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 53 | #else 54 | 55 | { 56 | constexpr auto w = test, 0>( 1 ); 57 | STATIC_ASSERT( w == 1 ); 58 | } 59 | 60 | #endif 61 | 62 | { 63 | constexpr auto w = test, 0>( 1 ); 64 | STATIC_ASSERT( w == 1 ); 65 | } 66 | 67 | { 68 | constexpr auto w = test, 1>( 3.0f ); 69 | STATIC_ASSERT( w == 3.0f ); 70 | } 71 | 72 | { 73 | constexpr auto w = test, 0>( 1 ); 74 | STATIC_ASSERT( w == 1 ); 75 | } 76 | 77 | { 78 | constexpr auto w = test, 1>( 1 ); 79 | STATIC_ASSERT( w == 1 ); 80 | } 81 | 82 | { 83 | constexpr auto w = test, 2>( 2.0f ); 84 | STATIC_ASSERT( w == 2.0f ); 85 | } 86 | 87 | { 88 | constexpr auto w = test, 3>( 3.0f ); 89 | STATIC_ASSERT( w == 3.0f ); 90 | } 91 | 92 | { 93 | constexpr auto w = test, 4>( 4 ); 94 | STATIC_ASSERT( w == 4 ); 95 | } 96 | 97 | { 98 | constexpr auto w = test, 5>( 5 ); 99 | STATIC_ASSERT( w == 5 ); 100 | } 101 | 102 | #if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 103 | #else 104 | 105 | { 106 | constexpr auto w = test, 0>( 1 ); 107 | STATIC_ASSERT( w == 1 ); 108 | } 109 | 110 | { 111 | constexpr auto w = test, 1>( 1 ); 112 | STATIC_ASSERT( w == 1 ); 113 | } 114 | 115 | { 116 | constexpr auto w = test, 2>( 2.0f ); 117 | STATIC_ASSERT( w == 2.0f ); 118 | } 119 | 120 | { 121 | constexpr auto w = test, 3>( 3.0f ); 122 | STATIC_ASSERT( w == 3.0f ); 123 | } 124 | 125 | { 126 | constexpr auto w = test, 4>( 4 ); 127 | STATIC_ASSERT( w == 4 ); 128 | } 129 | 130 | { 131 | constexpr auto w = test, 5>( 5 ); 132 | STATIC_ASSERT( w == 5 ); 133 | } 134 | 135 | #endif 136 | } 137 | -------------------------------------------------------------------------------- /benchmark/benchmark2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Peter Dimov 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // 5 | // See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt 7 | 8 | #if defined(ONLY_V2) 9 | # define NO_BV 10 | # define NO_SV 11 | #endif 12 | 13 | #if defined(ONLY_BV) 14 | # define NO_V2 15 | # define NO_SV 16 | #endif 17 | 18 | #if defined(ONLY_SV) 19 | # define NO_V2 20 | # define NO_BV 21 | #endif 22 | 23 | #if !defined(NO_V2) 24 | #include 25 | #endif 26 | 27 | #if !defined(NO_BV) 28 | #include 29 | #endif 30 | 31 | #if !defined(NO_SV) 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | struct prefix 42 | { 43 | int v_; 44 | }; 45 | 46 | struct X1: prefix {}; 47 | struct X2: prefix {}; 48 | struct X3: prefix {}; 49 | struct X4: prefix {}; 50 | struct X5: prefix {}; 51 | struct X6: prefix {}; 52 | struct X7: prefix {}; 53 | struct X8: prefix {}; 54 | struct X9: prefix {}; 55 | struct X10: prefix {}; 56 | struct X11: prefix {}; 57 | struct X12: prefix {}; 58 | 59 | inline int get_value( prefix const& v ) 60 | { 61 | return v.v_; 62 | } 63 | 64 | #if !defined(NO_V2) 65 | 66 | template int get_value( boost::variant2::variant const& v ) 67 | { 68 | return visit( []( prefix const& x ) { return x.v_; }, v ); 69 | } 70 | 71 | #endif 72 | 73 | #if !defined(NO_BV) 74 | 75 | template int get_value( boost::variant const& v ) 76 | { 77 | return boost::apply_visitor( []( prefix const& x ) { return x.v_; }, v ); 78 | } 79 | 80 | #endif 81 | 82 | #if !defined(NO_SV) 83 | 84 | template int get_value( std::variant const& v ) 85 | { 86 | return visit( []( prefix const& x ) { return x.v_; }, v ); 87 | } 88 | 89 | #endif 90 | 91 | template void test_( int N ) 92 | { 93 | std::vector w; 94 | // lack of reserve is deliberate 95 | 96 | auto tp1 = std::chrono::high_resolution_clock::now(); 97 | 98 | for( int i = 0; i < N / 12; ++i ) 99 | { 100 | w.push_back( X1{ i } ); 101 | w.push_back( X2{ i } ); 102 | w.push_back( X3{ i } ); 103 | w.push_back( X4{ i } ); 104 | w.push_back( X5{ i } ); 105 | w.push_back( X6{ i } ); 106 | w.push_back( X7{ i } ); 107 | w.push_back( X8{ i } ); 108 | w.push_back( X9{ i } ); 109 | w.push_back( X10{ i } ); 110 | w.push_back( X11{ i } ); 111 | w.push_back( X12{ i } ); 112 | } 113 | 114 | unsigned long long s = 0; 115 | 116 | for( std::size_t i = 0, n = w.size(); i < n; ++i ) 117 | { 118 | s = s + get_value( w[ i ] ); 119 | } 120 | 121 | auto tp2 = std::chrono::high_resolution_clock::now(); 122 | 123 | std::cout << std::setw( 6 ) << std::chrono::duration_cast( tp2 - tp1 ).count() << " ms; S=" << s << "\n"; 124 | } 125 | 126 | template void test( int N ) 127 | { 128 | std::cout << "N=" << N << ":\n"; 129 | 130 | std::cout << " prefix: "; test_( N ); 131 | #if !defined(NO_V2) 132 | std::cout << " variant2: "; test_>( N ); 133 | #endif 134 | #if !defined(NO_BV) 135 | std::cout << "boost::variant: "; test_>( N ); 136 | #endif 137 | #if !defined(NO_SV) 138 | std::cout << " std::variant: "; test_>( N ); 139 | #endif 140 | 141 | std::cout << '\n'; 142 | } 143 | 144 | int main() 145 | { 146 | int const N = 100'000'000; 147 | 148 | test( N ); 149 | } 150 | -------------------------------------------------------------------------------- /test/variant_in_place_type_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | X() = default; 21 | template X( in_place_type_t ) = delete; 22 | }; 23 | 24 | int main() 25 | { 26 | { 27 | variant v( in_place_type_t{} ); 28 | 29 | BOOST_TEST_EQ( v.index(), 0 ); 30 | BOOST_TEST_EQ( get<0>(v), 0 ); 31 | 32 | BOOST_TEST( holds_alternative(v) ); 33 | } 34 | 35 | { 36 | variant v( in_place_type_t{} ); 37 | 38 | BOOST_TEST_EQ( v.index(), 0 ); 39 | 40 | BOOST_TEST( holds_alternative(v) ); 41 | } 42 | 43 | { 44 | variant v( in_place_type_t{}, 1 ); 45 | 46 | BOOST_TEST_EQ( v.index(), 0 ); 47 | BOOST_TEST_EQ( get<0>(v), 1 ); 48 | 49 | BOOST_TEST( holds_alternative(v) ); 50 | } 51 | 52 | { 53 | variant v( in_place_type_t{} ); 54 | 55 | BOOST_TEST_EQ( v.index(), 0 ); 56 | BOOST_TEST_EQ( get<0>(v), 0 ); 57 | 58 | BOOST_TEST( holds_alternative(v) ); 59 | } 60 | 61 | { 62 | variant v( in_place_type_t{}, 1 ); 63 | 64 | BOOST_TEST_EQ( v.index(), 0 ); 65 | BOOST_TEST_EQ( get<0>(v), 1 ); 66 | 67 | BOOST_TEST( holds_alternative(v) ); 68 | } 69 | 70 | { 71 | variant v( in_place_type_t{} ); 72 | 73 | BOOST_TEST_EQ( v.index(), 1 ); 74 | BOOST_TEST_EQ( get<1>(v), 0 ); 75 | 76 | BOOST_TEST( holds_alternative(v) ); 77 | } 78 | 79 | { 80 | variant v( in_place_type_t{}, 3.14f ); 81 | 82 | BOOST_TEST_EQ( v.index(), 1 ); 83 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 84 | 85 | BOOST_TEST( holds_alternative(v) ); 86 | } 87 | 88 | { 89 | variant v( in_place_type_t{}, 3.14f ); 90 | 91 | BOOST_TEST_EQ( v.index(), 2 ); 92 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 93 | 94 | BOOST_TEST( holds_alternative(v) ); 95 | } 96 | 97 | { 98 | variant v( in_place_type_t{}, "text" ); 99 | 100 | BOOST_TEST_EQ( v.index(), 4 ); 101 | BOOST_TEST_EQ( get<4>(v), std::string("text") ); 102 | 103 | BOOST_TEST( holds_alternative(v) ); 104 | } 105 | 106 | { 107 | variant v( in_place_type_t{}, 4, 'a' ); 108 | 109 | BOOST_TEST_EQ( v.index(), 4 ); 110 | BOOST_TEST_EQ( get<4>(v), std::string( 4, 'a' ) ); 111 | 112 | BOOST_TEST( holds_alternative(v) ); 113 | } 114 | 115 | { 116 | variant v( in_place_type_t{}, { 'a', 'b', 'c' } ); 117 | 118 | BOOST_TEST_EQ( v.index(), 4 ); 119 | BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); 120 | 121 | BOOST_TEST( holds_alternative(v) ); 122 | } 123 | 124 | { 125 | variant v( in_place_type_t{}, { 'a', 'b', 'c' }, std::allocator() ); 126 | 127 | BOOST_TEST_EQ( v.index(), 4 ); 128 | BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); 129 | 130 | BOOST_TEST( holds_alternative(v) ); 131 | } 132 | 133 | return boost::report_errors(); 134 | } 135 | -------------------------------------------------------------------------------- /test/variant_in_place_index_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X 19 | { 20 | X() = default; 21 | X( in_place_index_t<0> ) = delete; 22 | }; 23 | 24 | int main() 25 | { 26 | { 27 | variant v( in_place_index_t<0>{} ); 28 | 29 | BOOST_TEST_EQ( v.index(), 0 ); 30 | BOOST_TEST_EQ( get<0>(v), 0 ); 31 | } 32 | 33 | { 34 | variant v( in_place_index_t<0>{} ); 35 | 36 | BOOST_TEST_EQ( v.index(), 0 ); 37 | } 38 | 39 | { 40 | variant v( in_place_index_t<0>{}, 1 ); 41 | 42 | BOOST_TEST_EQ( v.index(), 0 ); 43 | BOOST_TEST_EQ( get<0>(v), 1 ); 44 | } 45 | 46 | { 47 | variant v( in_place_index_t<0>{} ); 48 | 49 | BOOST_TEST_EQ( v.index(), 0 ); 50 | BOOST_TEST_EQ( get<0>(v), 0 ); 51 | } 52 | 53 | { 54 | variant v( in_place_index_t<0>{}, 1 ); 55 | 56 | BOOST_TEST_EQ( v.index(), 0 ); 57 | BOOST_TEST_EQ( get<0>(v), 1 ); 58 | } 59 | 60 | { 61 | variant v( in_place_index_t<1>{} ); 62 | 63 | BOOST_TEST_EQ( v.index(), 1 ); 64 | BOOST_TEST_EQ( get<1>(v), 0 ); 65 | } 66 | 67 | { 68 | variant v( in_place_index_t<1>{}, 3.14f ); 69 | 70 | BOOST_TEST_EQ( v.index(), 1 ); 71 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 72 | } 73 | 74 | { 75 | variant v( in_place_index_t<0>{}, 1 ); 76 | 77 | BOOST_TEST_EQ( v.index(), 0 ); 78 | BOOST_TEST_EQ( get<0>(v), 1 ); 79 | } 80 | 81 | { 82 | variant v( in_place_index_t<1>{}, 1 ); 83 | 84 | BOOST_TEST_EQ( v.index(), 1 ); 85 | BOOST_TEST_EQ( get<1>(v), 1 ); 86 | } 87 | 88 | { 89 | variant v( in_place_index_t<2>{}, 3.14f ); 90 | 91 | BOOST_TEST_EQ( v.index(), 2 ); 92 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 93 | } 94 | 95 | { 96 | variant v( in_place_index_t<3>{}, 3.14f ); 97 | 98 | BOOST_TEST_EQ( v.index(), 3 ); 99 | BOOST_TEST_EQ( get<3>(v), 3.14f ); 100 | } 101 | 102 | { 103 | variant v( in_place_index_t<4>{}, "text" ); 104 | 105 | BOOST_TEST_EQ( v.index(), 4 ); 106 | BOOST_TEST_EQ( get<4>(v), std::string("text") ); 107 | } 108 | 109 | { 110 | variant v( in_place_index_t<5>{}, "text" ); 111 | 112 | BOOST_TEST_EQ( v.index(), 5 ); 113 | BOOST_TEST_EQ( get<5>(v), std::string("text") ); 114 | } 115 | 116 | { 117 | variant v( in_place_index_t<5>{}, 4, 'a' ); 118 | 119 | BOOST_TEST_EQ( v.index(), 5 ); 120 | BOOST_TEST_EQ( get<5>(v), std::string( 4, 'a' ) ); 121 | } 122 | 123 | { 124 | variant v( in_place_index_t<4>{}, { 'a', 'b', 'c' } ); 125 | 126 | BOOST_TEST_EQ( v.index(), 4 ); 127 | BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); 128 | } 129 | 130 | { 131 | variant v( in_place_index_t<5>{}, { 'a', 'b', 'c' }, std::allocator() ); 132 | 133 | BOOST_TEST_EQ( v.index(), 5 ); 134 | BOOST_TEST_EQ( get<5>(v), (std::string{ 'a', 'b', 'c' }) ); 135 | } 136 | 137 | return boost::report_errors(); 138 | } 139 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /test/variant_visit_by_index.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2017, 2021 Peter Dimov. 2 | // Distributed under the Boost Software License, Version 1.0. 3 | // https://www.boost.org/LICENSE_1_0.txt 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace boost::variant2; 12 | using boost::mp11::mp_int; 13 | 14 | struct X 15 | { 16 | }; 17 | 18 | struct F1 19 | { 20 | int operator()( X& ) const { return 1; } 21 | int operator()( X const& ) const { return 2; } 22 | int operator()( X&& ) const { return 3; } 23 | int operator()( X const&& ) const { return 4; } 24 | }; 25 | 26 | struct F2 27 | { 28 | mp_int<1> operator()( X& ) const { return {}; } 29 | mp_int<2> operator()( X const& ) const { return {}; } 30 | mp_int<3> operator()( X&& ) const { return {}; } 31 | mp_int<4> operator()( X const&& ) const { return {}; } 32 | }; 33 | 34 | int main() 35 | { 36 | { 37 | variant v; 38 | 39 | visit_by_index( v, 40 | []( int& x ){ BOOST_TEST_EQ( x, 0 ); }, 41 | []( int& ){ BOOST_ERROR( "incorrect alternative" ); }, 42 | []( float& ){ BOOST_ERROR( "incorrect alternative" ); } ); 43 | } 44 | 45 | { 46 | variant v( in_place_index_t<0>(), 1 ); 47 | 48 | visit_by_index( v, 49 | []( int const& x ){ BOOST_TEST_EQ( x, 1 ); }, 50 | []( int& ){ BOOST_ERROR( "incorrect alternative" ); }, 51 | []( float const& ){ BOOST_ERROR( "incorrect alternative" ); } ); 52 | } 53 | 54 | { 55 | variant const v( in_place_index_t<1>(), 2 ); 56 | 57 | visit_by_index( v, 58 | []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, 59 | []( int const& x ){ BOOST_TEST_EQ( x, 2 ); }, 60 | []( float const& ){ BOOST_ERROR( "incorrect alternative" ); } ); 61 | } 62 | 63 | { 64 | variant const v( 3.14f ); 65 | 66 | visit_by_index( v, 67 | []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, 68 | []( int const& ){ BOOST_ERROR( "incorrect alternative" ); }, 69 | []( float const& x ){ BOOST_TEST_EQ( x, 3.14f ); } ); 70 | } 71 | 72 | { 73 | variant const v( 7 ); 74 | 75 | auto r = visit_by_index( v, 76 | []( int const& x ) -> double { return x; }, 77 | []( float const& x ) -> double { return x; } ); 78 | 79 | BOOST_TEST_TRAIT_SAME( decltype(r), double ); 80 | BOOST_TEST_EQ( r, 7.0 ); 81 | } 82 | 83 | { 84 | variant const v( 2.0f ); 85 | 86 | auto r = visit_by_index( v, 87 | []( int const& x ) { return x + 0.0; }, 88 | []( float const& x ) { return x + 0.0; } ); 89 | 90 | BOOST_TEST_TRAIT_SAME( decltype(r), double ); 91 | BOOST_TEST_EQ( r, 2.0 ); 92 | } 93 | 94 | { 95 | variant const v( 3.0 ); 96 | 97 | auto r = visit_by_index( v, 98 | []( int const& x ) { return x; }, 99 | []( float const& x ) { return x; }, 100 | []( double const& x ) { return x; } ); 101 | 102 | BOOST_TEST_TRAIT_SAME( decltype(r), double ); 103 | BOOST_TEST_EQ( r, 3.0 ); 104 | } 105 | 106 | { 107 | variant v; 108 | variant const cv; 109 | 110 | F1 f1; 111 | 112 | BOOST_TEST_EQ( visit_by_index( v, f1 ), 1 ); 113 | BOOST_TEST_EQ( visit_by_index( cv, f1 ), 2 ); 114 | BOOST_TEST_EQ( visit_by_index( std::move( v ), f1 ), 3 ); 115 | BOOST_TEST_EQ( visit_by_index( std::move( cv ), f1 ), 4 ); 116 | 117 | F2 f2; 118 | 119 | BOOST_TEST_EQ( visit_by_index( v, f2 ), 1 ); 120 | BOOST_TEST_EQ( visit_by_index( cv, f2 ), 2 ); 121 | BOOST_TEST_EQ( visit_by_index( std::move( v ), f2 ), 3 ); 122 | BOOST_TEST_EQ( visit_by_index( std::move( cv ), f2 ), 4 ); 123 | } 124 | 125 | return boost::report_errors(); 126 | } 127 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2016-2021 Peter Dimov 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) 4 | 5 | version: 1.0.{build}-{branch} 6 | 7 | shallow_clone: true 8 | 9 | branches: 10 | only: 11 | - master 12 | - develop 13 | - /feature\/.*/ 14 | 15 | environment: 16 | matrix: 17 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 18 | TOOLSET: msvc-14.0 19 | ADDRMD: 32,64 20 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 21 | TOOLSET: msvc-14.1 22 | ADDRMD: 32,64 23 | CXXSTD: 14,17,latest 24 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 25 | TOOLSET: msvc-14.1 26 | ADDRMD: 32,64 27 | CXXSTD: 14,17,latest 28 | CXXFLAGS: /permissive- 29 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 30 | TOOLSET: clang-win 31 | ADDRMD: 64 32 | CXXSTD: 14,17,latest 33 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 34 | TOOLSET: clang-win 35 | ADDRMD: 64 36 | CXXSTD: 14,17,latest 37 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 38 | CMAKE: 1 39 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 40 | CMAKE_SUBDIR: 1 41 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 42 | CMAKE_INSTALL: 1 43 | 44 | install: 45 | - set BOOST_BRANCH=develop 46 | - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master 47 | - cd .. 48 | - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root 49 | - cd boost-root 50 | - git submodule update --init tools/boostdep 51 | - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\variant2\ 52 | - python tools/boostdep/depinst/depinst.py variant2 53 | - cmd /c bootstrap 54 | - b2 -d0 headers 55 | 56 | build: off 57 | 58 | test_script: 59 | - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% 60 | - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% 61 | - if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS% 62 | - if "%CMAKE%%CMAKE_SUBDIR%%CMAKE_INSTALL%" == "" b2 -j2 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker 63 | 64 | - if not "%CMAKE%" == "" mkdir __build__ && cd __build__ 65 | - if not "%CMAKE%" == "" cmake -DBUILD_TESTING=ON -DBOOST_INCLUDE_LIBRARIES=variant2 -DBoost_VERBOSE=ON .. 66 | - if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config Debug & ctest --output-on-failure --no-tests=error -j 3 -C Debug 67 | - if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config Release & ctest --output-on-failure --no-tests=error -j 3 -C Release 68 | - if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config MinSizeRel & ctest --output-on-failure --no-tests=error -j 3 -C MinSizeRel 69 | - if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config RelWithDebInfo & ctest --output-on-failure --no-tests=error -j 3 -C RelWithDebInfo 70 | 71 | - if not "%CMAKE_SUBDIR%" == "" cd libs/variant2/test/cmake_subdir_test && mkdir __build__ && cd __build__ 72 | - if not "%CMAKE_SUBDIR%" == "" cmake .. 73 | - if not "%CMAKE_SUBDIR%" == "" cmake --build . --config Debug && cmake --build . --target check --config Debug 74 | - if not "%CMAKE_SUBDIR%" == "" cmake --build . --config Release && cmake --build . --target check --config Release 75 | - if not "%CMAKE_SUBDIR%" == "" cmake --build . --config MinSizeRel && cmake --build . --target check --config MinSizeRel 76 | - if not "%CMAKE_SUBDIR%" == "" cmake --build . --config RelWithDebInfo && cmake --build . --target check --config RelWithDebInfo 77 | 78 | - if not "%CMAKE_INSTALL%" == "" mkdir __build__ && cd __build__ 79 | - if not "%CMAKE_INSTALL%" == "" cmake -DBOOST_INCLUDE_LIBRARIES=variant2 -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. 80 | - if not "%CMAKE_INSTALL%" == "" cmake --build . --target install --config Debug 81 | - if not "%CMAKE_INSTALL%" == "" cmake --build . --target install --config Release 82 | - if not "%CMAKE_INSTALL%" == "" cd ../libs/variant2/test/cmake_install_test && mkdir __build__ && cd __build__ 83 | - if not "%CMAKE_INSTALL%" == "" cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. 84 | - if not "%CMAKE_INSTALL%" == "" cmake --build . --config Debug && cmake --build . --target check --config Debug 85 | - if not "%CMAKE_INSTALL%" == "" cmake --build . --config Release && cmake --build . --target check --config Release 86 | -------------------------------------------------------------------------------- /benchmark/benchmark1.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Peter Dimov 2 | // 3 | // Distributed under the Boost Software License, Version 1.0. 4 | // 5 | // See accompanying file LICENSE_1_0.txt or copy at 6 | // http://www.boost.org/LICENSE_1_0.txt 7 | 8 | #if defined(ONLY_V2) 9 | # define NO_BV 10 | # define NO_SV 11 | #endif 12 | 13 | #if defined(ONLY_BV) 14 | # define NO_V2 15 | # define NO_SV 16 | #endif 17 | 18 | #if defined(ONLY_SV) 19 | # define NO_V2 20 | # define NO_BV 21 | #endif 22 | 23 | #if !defined(NO_V2) 24 | #include 25 | #endif 26 | 27 | #if !defined(NO_BV) 28 | #include 29 | #endif 30 | 31 | #if !defined(NO_SV) 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | template struct is_numeric: std::integral_constant::value || std::is_floating_point::value> 45 | { 46 | }; 47 | 48 | template struct have_addition: std::integral_constant::value && is_numeric::value> 49 | { 50 | }; 51 | 52 | template::value>> auto add( T const& t, U const& u ) 53 | { 54 | return t + u; 55 | } 56 | 57 | template::value>> double add( T const& /*t*/, U const& /*u*/ ) 58 | { 59 | throw std::logic_error( "Invalid addition" ); 60 | } 61 | 62 | inline double to_double( double const& v ) 63 | { 64 | return v; 65 | } 66 | 67 | #if !defined(NO_V2) 68 | 69 | template boost::variant2::variant operator+( boost::variant2::variant const& v1, boost::variant2::variant const& v2 ) 70 | { 71 | return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant { return add( x1, x2 ); }, v1, v2 ); 72 | } 73 | 74 | template double to_double( boost::variant2::variant const& v ) 75 | { 76 | return boost::variant2::get( v ); 77 | } 78 | 79 | #endif 80 | 81 | #if !defined(NO_BV) 82 | 83 | template boost::variant operator+( boost::variant const& v1, boost::variant const& v2 ) 84 | { 85 | return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant { return add( x1, x2 ); }, v1, v2 ); 86 | } 87 | 88 | template double to_double( boost::variant const& v ) 89 | { 90 | return boost::get( v ); 91 | } 92 | 93 | #endif 94 | 95 | #if !defined(NO_SV) 96 | 97 | template std::variant operator+( std::variant const& v1, std::variant const& v2 ) 98 | { 99 | return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant { return add( x1, x2 ); }, v1, v2 ); 100 | } 101 | 102 | template double to_double( std::variant const& v ) 103 | { 104 | return std::get( v ); 105 | } 106 | 107 | #endif 108 | 109 | template void test_( long long N ) 110 | { 111 | std::vector w; 112 | // lack of reserve is deliberate 113 | 114 | auto tp1 = std::chrono::high_resolution_clock::now(); 115 | 116 | for( long long i = 0; i < N; ++i ) 117 | { 118 | V v; 119 | 120 | if( i % 7 == 0 ) 121 | { 122 | v = i / 7; 123 | } 124 | else 125 | { 126 | v = i / 7.0; 127 | } 128 | 129 | w.push_back( v ); 130 | } 131 | 132 | V s = 0.0; 133 | 134 | for( long long i = 0; i < N; ++i ) 135 | { 136 | s = s + w[ i ]; 137 | } 138 | 139 | auto tp2 = std::chrono::high_resolution_clock::now(); 140 | 141 | std::cout << std::setw( 6 ) << std::chrono::duration_cast( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n"; 142 | } 143 | 144 | template void test( long long N ) 145 | { 146 | std::cout << "N=" << N << ":\n"; 147 | 148 | std::cout << " double: "; test_( N ); 149 | #if !defined(NO_V2) 150 | std::cout << " variant2: "; test_>( N ); 151 | #endif 152 | #if !defined(NO_BV) 153 | std::cout << "boost::variant: "; test_>( N ); 154 | #endif 155 | #if !defined(NO_SV) 156 | std::cout << " std::variant: "; test_>( N ); 157 | #endif 158 | 159 | std::cout << '\n'; 160 | } 161 | 162 | int main() 163 | { 164 | long long const N = 100'000'000LL; 165 | 166 | test( N ); 167 | test, std::map>( N ); 168 | } 169 | -------------------------------------------------------------------------------- /test/variant_move_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | X1() {} 23 | X1(X1 const&) {} 24 | X1(X1&&) {} 25 | }; 26 | 27 | inline bool operator==( X1, X1 ) { return true; } 28 | 29 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 30 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 31 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 32 | 33 | struct X2 34 | { 35 | X2() {} 36 | X2(X2 const&) {} 37 | X2(X2&&) {} 38 | }; 39 | 40 | inline bool operator==( X2, X2 ) { return true; } 41 | 42 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 43 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 44 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 45 | 46 | struct Y 47 | { 48 | Y( Y&& ) = delete; 49 | }; 50 | 51 | template static void test( V&& v ) 52 | { 53 | V v2( v ); 54 | V v3( std::move(v) ); 55 | 56 | BOOST_TEST_EQ( v2.index(), v3.index() ); 57 | BOOST_TEST( v2 == v3 ); 58 | } 59 | 60 | int main() 61 | { 62 | test( variant() ); 63 | test( variant(1) ); 64 | 65 | test( variant() ); 66 | test( variant(1) ); 67 | 68 | test( variant() ); 69 | test( variant(1) ); 70 | test( variant(3.14f) ); 71 | 72 | test( variant() ); 73 | test( variant(1) ); 74 | test( variant(3.14f) ); 75 | 76 | test( variant() ); 77 | test( variant("test") ); 78 | 79 | test( variant() ); 80 | test( variant("test") ); 81 | 82 | test( variant() ); 83 | test( variant(1) ); 84 | test( variant(3.14f) ); 85 | test( variant("test") ); 86 | 87 | test( variant() ); 88 | 89 | test( variant() ); 90 | test( variant(3.14f) ); 91 | 92 | test( variant() ); 93 | 94 | test( variant("test") ); 95 | 96 | test( variant() ); 97 | 98 | test( variant() ); 99 | 100 | test( variant() ); 101 | test( variant() ); 102 | test( variant() ); 103 | test( variant() ); 104 | 105 | { 106 | variant v; 107 | v.emplace(); 108 | 109 | test( std::move(v) ); 110 | } 111 | 112 | { 113 | variant v; 114 | v.emplace(); 115 | 116 | test( std::move(v) ); 117 | } 118 | 119 | { 120 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible>)); 121 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible>)); 122 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible>)); 123 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible>)); 124 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible>)); 125 | 126 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 127 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 128 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 129 | 130 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 131 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 132 | 133 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 134 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); 135 | 136 | BOOST_TEST_TRAIT_TRUE((std::is_move_constructible>)); 137 | 138 | #if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) 139 | 140 | BOOST_TEST_TRAIT_FALSE((std::is_move_constructible>)); 141 | 142 | #endif 143 | } 144 | 145 | return boost::report_errors(); 146 | } 147 | -------------------------------------------------------------------------------- /benchmark/benchmark2.md: -------------------------------------------------------------------------------- 1 | # benchmark2.cpp results 2 | 3 | ## VS 2017 15.9.7 64 bit (cl.exe 19.16, /EHsc /std:c++17) 4 | 5 | ### /Od 6 | 7 | #### Compile time 8 | 9 | ``` 10 | variant2 (-DONLY_V2): 1403 ms 11 | boost::variant (-DONLY_BV): 2972 ms 12 | std::variant (-DONLY_SV): 1057 ms 13 | ``` 14 | 15 | #### Run time 16 | 17 | ``` 18 | N=100000000: 19 | prefix: 7016 ms; S=416666583333336 20 | variant2: 24723 ms; S=416666583333336 21 | boost::variant: 60438 ms; S=416666583333336 22 | std::variant: 20707 ms; S=416666583333336 23 | ``` 24 | 25 | ### /O2 /DNDEBUG 26 | 27 | #### Compile time 28 | 29 | ``` 30 | variant2 (-DONLY_V2): 1778 ms 31 | boost::variant (-DONLY_BV): 3252 ms 32 | std::variant (-DONLY_SV): 1372 ms 33 | ``` 34 | 35 | #### Run time 36 | 37 | ``` 38 | N=100000000: 39 | prefix: 803 ms; S=416666583333336 40 | variant2: 2124 ms; S=416666583333336 41 | boost::variant: 6191 ms; S=416666583333336 42 | std::variant: 2193 ms; S=416666583333336 43 | ``` 44 | 45 | ## g++ 7.4.0 -std=c++17 (Cygwin 64 bit) 46 | 47 | ### -O0 48 | 49 | #### Compile time 50 | 51 | ``` 52 | variant2 (-DONLY_V2): 1739 ms 53 | boost::variant (-DONLY_BV): 3113 ms 54 | std::variant (-DONLY_SV): 1719 ms 55 | ``` 56 | 57 | #### Run time 58 | 59 | ``` 60 | N=100000000: 61 | prefix: 5163 ms; S=416666583333336 62 | variant2: 20628 ms; S=416666583333336 63 | boost::variant: 43308 ms; S=416666583333336 64 | std::variant: 42375 ms; S=416666583333336 65 | ``` 66 | 67 | ### -O1 68 | 69 | #### Compile time 70 | 71 | ``` 72 | variant2 (-DONLY_V2): 1484 ms 73 | boost::variant (-DONLY_BV): 2947 ms 74 | std::variant (-DONLY_SV): 1448 ms 75 | ``` 76 | 77 | #### Run time 78 | 79 | ``` 80 | N=100000000: 81 | prefix: 781 ms; S=416666583333336 82 | variant2: 1992 ms; S=416666583333336 83 | boost::variant: 2249 ms; S=416666583333336 84 | std::variant: 4843 ms; S=416666583333336 85 | ``` 86 | 87 | ### -O2 -DNDEBUG 88 | 89 | #### Compile time 90 | 91 | ``` 92 | variant2 (-DONLY_V2): 1547 ms 93 | boost::variant (-DONLY_BV): 2999 ms 94 | std::variant (-DONLY_SV): 1528 ms 95 | ``` 96 | 97 | #### Run time 98 | 99 | ``` 100 | N=100000000: 101 | prefix: 793 ms; S=416666583333336 102 | variant2: 1686 ms; S=416666583333336 103 | boost::variant: 1833 ms; S=416666583333336 104 | std::variant: 4340 ms; S=416666583333336 105 | ``` 106 | 107 | ### -O3 -DNDEBUG 108 | 109 | #### Compile time 110 | 111 | ``` 112 | variant2 (-DONLY_V2): 1595 ms 113 | boost::variant (-DONLY_BV): 3084 ms 114 | std::variant (-DONLY_SV): 1620 ms 115 | ``` 116 | 117 | #### Run time 118 | 119 | ``` 120 | N=100000000: 121 | prefix: 853 ms; S=416666583333336 122 | variant2: 1681 ms; S=416666583333336 123 | boost::variant: 1773 ms; S=416666583333336 124 | std::variant: 3989 ms; S=416666583333336 125 | ``` 126 | 127 | ## clang++ 5.0.1 -std=c++17 -stdlib=libc++ (Cygwin 64 bit) 128 | 129 | ### -O0 130 | 131 | #### Compile time 132 | 133 | ``` 134 | variant2 (-DONLY_V2): 1578 ms 135 | boost::variant (-DONLY_BV): 2623 ms 136 | std::variant (-DONLY_SV): 1508 ms 137 | ``` 138 | 139 | #### Run time 140 | 141 | ``` 142 | N=100000000: 143 | prefix: 4447 ms; S=416666583333336 144 | variant2: 16016 ms; S=416666583333336 145 | boost::variant: 42365 ms; S=416666583333336 146 | std::variant: 17817 ms; S=416666583333336 147 | ``` 148 | 149 | ### -O1 150 | 151 | #### Compile time 152 | 153 | ``` 154 | variant2 (-DONLY_V2): 1841 ms 155 | boost::variant (-DONLY_BV): 2919 ms 156 | std::variant (-DONLY_SV): 1776 ms 157 | ``` 158 | 159 | #### Run time 160 | 161 | ``` 162 | N=100000000: 163 | prefix: 1390 ms; S=416666583333336 164 | variant2: 5397 ms; S=416666583333336 165 | boost::variant: 23234 ms; S=416666583333336 166 | std::variant: 2807 ms; S=416666583333336 167 | ``` 168 | 169 | ### -O2 -DNDEBUG 170 | 171 | #### Compile time 172 | 173 | ``` 174 | variant2 (-DONLY_V2): 1766 ms 175 | boost::variant (-DONLY_BV): 2817 ms 176 | std::variant (-DONLY_SV): 1718 ms 177 | ``` 178 | 179 | #### Run time 180 | 181 | ``` 182 | N=100000000: 183 | prefix: 604 ms; S=416666583333336 184 | variant2: 1625 ms; S=416666583333336 185 | boost::variant: 2735 ms; S=416666583333336 186 | std::variant: 2664 ms; S=416666583333336 187 | ``` 188 | 189 | ### -O3 -DNDEBUG 190 | 191 | #### Compile time 192 | 193 | ``` 194 | variant2 (-DONLY_V2): 1720 ms 195 | boost::variant (-DONLY_BV): 2806 ms 196 | std::variant (-DONLY_SV): 1737 ms 197 | ``` 198 | 199 | #### Run time 200 | 201 | ``` 202 | N=100000000: 203 | prefix: 603 ms; S=416666583333336 204 | variant2: 1608 ms; S=416666583333336 205 | boost::variant: 2696 ms; S=416666583333336 206 | std::variant: 2668 ms; S=416666583333336 207 | ``` 208 | -------------------------------------------------------------------------------- /test/variant_visit.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace boost::variant2; 24 | using boost::mp11::mp_size_t; 25 | 26 | struct X 27 | { 28 | }; 29 | 30 | struct F 31 | { 32 | mp_size_t<1> operator()( X& ) const; 33 | mp_size_t<2> operator()( X const& ) const; 34 | mp_size_t<3> operator()( X&& ) const; 35 | mp_size_t<4> operator()( X const&& ) const; 36 | }; 37 | 38 | int main() 39 | { 40 | { 41 | BOOST_TEST_EQ( (visit( []{ return 5; } )), 5 ); 42 | } 43 | 44 | { 45 | variant v( 1 ); 46 | 47 | BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 1 ); 48 | 49 | visit( []( int x ){ BOOST_TEST_EQ( x, 1 ); }, v ); 50 | visit( []( int x ){ BOOST_TEST_EQ( x, 1 ); }, std::move(v) ); 51 | } 52 | 53 | { 54 | variant const v( 2 ); 55 | 56 | BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 2 ); 57 | 58 | visit( []( int x ){ BOOST_TEST_EQ( x, 2 ); }, v ); 59 | visit( []( int x ){ BOOST_TEST_EQ( x, 2 ); }, std::move(v) ); 60 | } 61 | 62 | { 63 | variant v( 3 ); 64 | 65 | BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 3 ); 66 | 67 | visit( []( int x ){ BOOST_TEST_EQ( x, 3 ); }, v ); 68 | visit( []( int x ){ BOOST_TEST_EQ( x, 3 ); }, std::move(v) ); 69 | } 70 | 71 | { 72 | variant const v( 4 ); 73 | 74 | BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 4 ); 75 | 76 | visit( []( int x ){ BOOST_TEST_EQ( x, 4 ); }, v ); 77 | visit( []( int x ){ BOOST_TEST_EQ( x, 4 ); }, std::move(v) ); 78 | } 79 | 80 | { 81 | variant v1( 1 ); 82 | variant const v2( 3.14f ); 83 | 84 | BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 ); 85 | 86 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 ); 87 | visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) ); 88 | } 89 | 90 | { 91 | variant v1( 1 ); 92 | variant const v2( 3.14f ); 93 | variant v3( 6.28 ); 94 | 95 | BOOST_TEST_EQ( (visit( []( int x1, float x2, double x3 ){ return (int)(x1 * 100) * 1000000 + (int)(x2 * 100) * 1000 + (int)(x3 * 100); }, v1, v2, v3 )), 100314628 ); 96 | 97 | visit( []( int x1, float x2, double x3 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); BOOST_TEST_EQ( x3, 6.28 ); }, v1, v2, v3 ); 98 | visit( []( int x1, float x2, double x3 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); BOOST_TEST_EQ( x3, 6.28 ); }, std::move(v1), std::move(v2), std::move(v3) ); 99 | } 100 | 101 | { 102 | variant v1( 1 ); 103 | variant const v2( 3.14f ); 104 | variant v3( 6.28 ); 105 | variant const v4( 'A' ); 106 | 107 | BOOST_TEST_EQ( (visit( []( int x1, float x2, double x3, char x4 ){ return (long long)(x1 * 100) * 100000000 + (long long)(x2 * 100) * 100000 + (long long)(x3 * 10000) + (int)x4; }, v1, v2, v3, v4 )), 10031462800 + 'A' ); 108 | 109 | visit( []( int x1, float x2, double x3, char x4 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); BOOST_TEST_EQ( x3, 6.28 ); BOOST_TEST_EQ( x4, 'A' ); }, v1, v2, v3, v4 ); 110 | visit( []( int x1, float x2, double x3, char x4 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); BOOST_TEST_EQ( x3, 6.28 ); BOOST_TEST_EQ( x4, 'A' ); }, std::move(v1), std::move(v2), std::move(v3), std::move(v4) ); 111 | } 112 | 113 | { 114 | variant v; 115 | variant const cv; 116 | 117 | BOOST_TEST_EQ( decltype(visit(F{}, v))::value, 1 ); 118 | BOOST_TEST_EQ( decltype(visit(F{}, cv))::value, 2 ); 119 | BOOST_TEST_EQ( decltype(visit(F{}, std::move(v)))::value, 3 ); 120 | 121 | #if !BOOST_WORKAROUND(BOOST_GCC, < 40900) 122 | 123 | // g++ 4.8 doesn't handle const&& particularly well 124 | BOOST_TEST_EQ( decltype(visit(F{}, std::move(cv)))::value, 4 ); 125 | 126 | #endif 127 | } 128 | 129 | return boost::report_errors(); 130 | } 131 | -------------------------------------------------------------------------------- /test/variant_copy_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace boost::variant2; 19 | 20 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 21 | 22 | struct X1 23 | { 24 | X1() {} 25 | X1(X1 const&) {} 26 | X1(X1&&) {} 27 | }; 28 | 29 | inline bool operator==( X1, X1 ) { return true; } 30 | 31 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 32 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 33 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 34 | 35 | struct X2 36 | { 37 | X2() {} 38 | X2(X2 const&) {} 39 | X2(X2&&) {} 40 | }; 41 | 42 | inline bool operator==( X2, X2 ) { return true; } 43 | 44 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 45 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 46 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 47 | 48 | struct Y 49 | { 50 | Y( Y const& ) = delete; 51 | }; 52 | 53 | struct D 54 | { 55 | ~D() {} 56 | }; 57 | 58 | inline bool operator==( D, D ) { return true; } 59 | 60 | template static void test( V const & v ) 61 | { 62 | V v2( v ); 63 | 64 | BOOST_TEST_EQ( v.index(), v2.index() ); 65 | BOOST_TEST( v == v2 ); 66 | 67 | BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible)); 68 | } 69 | 70 | int main() 71 | { 72 | test( variant() ); 73 | test( variant(1) ); 74 | 75 | test( variant() ); 76 | test( variant(1) ); 77 | 78 | test( variant() ); 79 | test( variant(1) ); 80 | test( variant(3.14f) ); 81 | 82 | test( variant() ); 83 | test( variant(1) ); 84 | test( variant(3.14f) ); 85 | 86 | test( variant() ); 87 | test( variant("test") ); 88 | 89 | test( variant() ); 90 | test( variant("test") ); 91 | 92 | test( variant() ); 93 | test( variant(1) ); 94 | test( variant(3.14f) ); 95 | test( variant("test") ); 96 | 97 | test( variant() ); 98 | 99 | test( variant() ); 100 | test( variant(3.14f) ); 101 | 102 | test( variant() ); 103 | 104 | test( variant("test") ); 105 | 106 | test( variant() ); 107 | 108 | test( variant() ); 109 | 110 | test( variant() ); 111 | test( variant() ); 112 | test( variant() ); 113 | test( variant() ); 114 | 115 | { 116 | variant v; 117 | v.emplace(); 118 | 119 | test( v ); 120 | } 121 | 122 | { 123 | variant v; 124 | v.emplace(); 125 | 126 | test( v ); 127 | } 128 | 129 | #if !BOOST_WORKAROUND( __GNUC__, < 5 ) 130 | 131 | test( variant() ); 132 | 133 | #endif 134 | 135 | { 136 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible>)); 137 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible>)); 138 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible>)); 139 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible>)); 140 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible>)); 141 | 142 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 143 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 144 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 145 | 146 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 147 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 148 | 149 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 150 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); 151 | 152 | BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible>)); 153 | 154 | #if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) 155 | 156 | BOOST_TEST_TRAIT_FALSE((std::is_copy_constructible>)); 157 | 158 | #endif 159 | } 160 | 161 | return boost::report_errors(); 162 | } 163 | -------------------------------------------------------------------------------- /test/variant_size.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | using namespace boost::mp11; 18 | 19 | template using var_size_t = mp_size_t::value>; 20 | 21 | int main() 22 | { 23 | BOOST_TEST_EQ( (variant_size>::value), 0 ); 24 | BOOST_TEST_EQ( (variant_size const>::value), 0 ); 25 | BOOST_TEST_EQ( (variant_size volatile>::value), 0 ); 26 | BOOST_TEST_EQ( (variant_size const volatile>::value), 0 ); 27 | 28 | BOOST_TEST_EQ( (variant_size&>::value), 0 ); 29 | BOOST_TEST_EQ( (variant_size const&>::value), 0 ); 30 | BOOST_TEST_EQ( (variant_size&&>::value), 0 ); 31 | BOOST_TEST_EQ( (variant_size const&&>::value), 0 ); 32 | 33 | BOOST_TEST_EQ( (variant_size>::value), 1 ); 34 | BOOST_TEST_EQ( (variant_size const>::value), 1 ); 35 | BOOST_TEST_EQ( (variant_size volatile>::value), 1 ); 36 | BOOST_TEST_EQ( (variant_size const volatile>::value), 1 ); 37 | 38 | BOOST_TEST_EQ( (variant_size&>::value), 1 ); 39 | BOOST_TEST_EQ( (variant_size const&>::value), 1 ); 40 | BOOST_TEST_EQ( (variant_size&&>::value), 1 ); 41 | BOOST_TEST_EQ( (variant_size const&&>::value), 1 ); 42 | 43 | BOOST_TEST_EQ( (variant_size>::value), 2 ); 44 | BOOST_TEST_EQ( (variant_size const>::value), 2 ); 45 | BOOST_TEST_EQ( (variant_size volatile>::value), 2 ); 46 | BOOST_TEST_EQ( (variant_size const volatile>::value), 2 ); 47 | 48 | BOOST_TEST_EQ( (variant_size&>::value), 2 ); 49 | BOOST_TEST_EQ( (variant_size const&>::value), 2 ); 50 | BOOST_TEST_EQ( (variant_size&&>::value), 2 ); 51 | BOOST_TEST_EQ( (variant_size const&&>::value), 2 ); 52 | 53 | BOOST_TEST_EQ( (variant_size>::value), 3 ); 54 | BOOST_TEST_EQ( (variant_size const>::value), 3 ); 55 | BOOST_TEST_EQ( (variant_size volatile>::value), 3 ); 56 | BOOST_TEST_EQ( (variant_size const volatile>::value), 3 ); 57 | 58 | BOOST_TEST_EQ( (variant_size&>::value), 3 ); 59 | BOOST_TEST_EQ( (variant_size const&>::value), 3 ); 60 | BOOST_TEST_EQ( (variant_size&&>::value), 3 ); 61 | BOOST_TEST_EQ( (variant_size const&&>::value), 3 ); 62 | 63 | BOOST_TEST_EQ( (variant_size>::value), 4 ); 64 | BOOST_TEST_EQ( (variant_size const>::value), 4 ); 65 | BOOST_TEST_EQ( (variant_size volatile>::value), 4 ); 66 | BOOST_TEST_EQ( (variant_size const volatile>::value), 4 ); 67 | 68 | BOOST_TEST_EQ( (variant_size&>::value), 4 ); 69 | BOOST_TEST_EQ( (variant_size const&>::value), 4 ); 70 | BOOST_TEST_EQ( (variant_size&&>::value), 4 ); 71 | BOOST_TEST_EQ( (variant_size const&&>::value), 4 ); 72 | 73 | variant_size(); 74 | variant_size(); 75 | variant_size(); 76 | variant_size(); 77 | 78 | variant_size(); 79 | variant_size(); 80 | variant_size(); 81 | variant_size(); 82 | 83 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 84 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 85 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 86 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 87 | 88 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 89 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 90 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 91 | BOOST_TEST_TRAIT_FALSE((mp_valid)); 92 | 93 | BOOST_TEST_TRAIT_TRUE((mp_valid>)); 94 | BOOST_TEST_TRAIT_TRUE((mp_valid const>)); 95 | BOOST_TEST_TRAIT_TRUE((mp_valid volatile>)); 96 | BOOST_TEST_TRAIT_TRUE((mp_valid const volatile>)); 97 | 98 | BOOST_TEST_TRAIT_TRUE((mp_valid&>)); 99 | BOOST_TEST_TRAIT_TRUE((mp_valid const&>)); 100 | BOOST_TEST_TRAIT_TRUE((mp_valid&&>)); 101 | BOOST_TEST_TRAIT_TRUE((mp_valid const&&>)); 102 | 103 | return boost::report_errors(); 104 | } 105 | -------------------------------------------------------------------------------- /test/variant_subset.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #if defined(_MSC_VER) 10 | # pragma warning( disable: 4702 ) // unreachable code 11 | #endif 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace boost::variant2; 21 | 22 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 23 | 24 | struct X1 25 | { 26 | int v; 27 | 28 | X1(): v(0) {} 29 | explicit X1(int v): v(v) {} 30 | X1(X1 const& r): v(r.v) {} 31 | X1(X1&& r): v(r.v) {} 32 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 33 | X1& operator=( X1&& r ) { v = r.v; return *this; } 34 | }; 35 | 36 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 37 | 38 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 39 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 40 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 41 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 42 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 43 | 44 | struct X2 45 | { 46 | int v; 47 | 48 | X2(): v(0) {} 49 | explicit X2(int v): v(v) {} 50 | X2(X2 const& r): v(r.v) {} 51 | X2(X2&& r): v(r.v) {} 52 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 53 | X2& operator=( X2&& r ) { v = r.v; return *this; } 54 | }; 55 | 56 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 57 | 58 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 59 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 60 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 61 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 62 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 63 | 64 | int main() 65 | { 66 | { 67 | variant v1( 1 ); 68 | 69 | variant v2 = v1.subset(); 70 | 71 | BOOST_TEST( holds_alternative( v2 ) ); 72 | BOOST_TEST_EQ( get( v1 ), get( v2 ) ); 73 | 74 | BOOST_TEST_THROWS( v1.subset(), bad_variant_access ); 75 | 76 | variant v3 = std::move(v1).subset(); 77 | 78 | BOOST_TEST( holds_alternative( v3 ) ); 79 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 80 | 81 | BOOST_TEST_THROWS( std::move(v1).subset(), bad_variant_access ); 82 | } 83 | 84 | { 85 | variant const v1( 1 ); 86 | 87 | variant v2 = v1.subset(); 88 | 89 | BOOST_TEST( holds_alternative( v2 ) ); 90 | BOOST_TEST_EQ( get( v1 ), get( v2 ) ); 91 | 92 | BOOST_TEST_THROWS( v1.subset(), bad_variant_access ); 93 | 94 | variant v3 = std::move(v1).subset(); 95 | 96 | BOOST_TEST( holds_alternative( v3 ) ); 97 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 98 | 99 | BOOST_TEST_THROWS( std::move(v1).subset(), bad_variant_access ); 100 | } 101 | 102 | { 103 | variant v1( 1 ); 104 | 105 | variant v2 = v1.subset(); 106 | 107 | BOOST_TEST( holds_alternative( v2 ) ); 108 | BOOST_TEST_EQ( get( v1 ), get( v2 ) ); 109 | 110 | variant v3 = std::move(v1).subset(); 111 | 112 | BOOST_TEST( holds_alternative( v3 ) ); 113 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 114 | } 115 | 116 | { 117 | variant v1( 1 ); 118 | 119 | variant v2 = v1.subset(); 120 | 121 | BOOST_TEST( holds_alternative( v2 ) ); 122 | BOOST_TEST_EQ( get( v1 ), get( v2 ) ); 123 | 124 | variant v3 = std::move(v1).subset(); 125 | 126 | BOOST_TEST( holds_alternative( v3 ) ); 127 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 128 | } 129 | 130 | { 131 | variant v1( "s1" ); 132 | 133 | variant v2 = v1.subset(); 134 | 135 | BOOST_TEST( holds_alternative( v2 ) ); 136 | BOOST_TEST_EQ( get( v1 ), get( v2 ) ); 137 | 138 | variant v3 = std::move(v1).subset(); 139 | 140 | BOOST_TEST( holds_alternative( v3 ) ); 141 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 142 | } 143 | 144 | { 145 | variant v1{ X1{1} }; 146 | 147 | variant v2 = v1.subset(); 148 | 149 | BOOST_TEST( holds_alternative( v2 ) ); 150 | BOOST_TEST_EQ( get( v1 ).v, get( v2 ).v ); 151 | 152 | variant v3 = std::move( v1 ).subset(); 153 | 154 | BOOST_TEST( holds_alternative( v3 ) ); 155 | BOOST_TEST_EQ( get( v2 ).v, get( v3 ).v ); 156 | } 157 | 158 | return boost::report_errors(); 159 | } 160 | -------------------------------------------------------------------------------- /test/variant_destroy.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | struct X1 19 | { 20 | static int instances; 21 | 22 | int v; 23 | 24 | X1(): v(0) { ++instances; } 25 | explicit X1(int v): v(v) { ++instances; } 26 | X1(X1 const& r): v(r.v) { ++instances; } 27 | X1(X1&& r): v(r.v) { ++instances; } 28 | 29 | ~X1() noexcept { --instances; } 30 | 31 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 32 | X1& operator=( X1&& r ) { v = r.v; return *this; } 33 | }; 34 | 35 | int X1::instances = 0; 36 | 37 | struct X2 38 | { 39 | static int instances; 40 | 41 | int v; 42 | 43 | X2(): v(0) { ++instances; } 44 | explicit X2(int v): v(v) { ++instances; } 45 | X2(X2 const& r): v(r.v) { ++instances; } 46 | X2(X2&& r): v(r.v) { ++instances; } 47 | 48 | ~X2() noexcept { --instances; } 49 | 50 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 51 | X2& operator=( X2&& r ) { v = r.v; return *this; } 52 | }; 53 | 54 | int X2::instances = 0; 55 | 56 | struct Y1 57 | { 58 | static int instances; 59 | 60 | int v; 61 | 62 | Y1() noexcept: v(0) { ++instances; } 63 | explicit Y1(int v) noexcept: v(v) { ++instances; } 64 | Y1(Y1 const& r) noexcept: v(r.v) { ++instances; } 65 | Y1(Y1&& r) noexcept: v(r.v) { ++instances; } 66 | 67 | ~Y1() noexcept { --instances; } 68 | 69 | Y1& operator=( Y1 const& r ) noexcept { v = r.v; return *this; } 70 | Y1& operator=( Y1&& r ) noexcept { v = r.v; return *this; } 71 | }; 72 | 73 | int Y1::instances = 0; 74 | 75 | struct Y2 76 | { 77 | static int instances; 78 | 79 | int v; 80 | 81 | Y2() noexcept: v(0) { ++instances; } 82 | explicit Y2(int v) noexcept: v(v) { ++instances; } 83 | Y2(Y2 const& r) noexcept: v(r.v) { ++instances; } 84 | Y2(Y2&& r) noexcept: v(r.v) { ++instances; } 85 | 86 | ~Y2() noexcept { --instances; } 87 | 88 | Y2& operator=( Y2 const& r ) noexcept { v = r.v; return *this; } 89 | Y2& operator=( Y2&& r ) noexcept { v = r.v; return *this; } 90 | }; 91 | 92 | int Y2::instances = 0; 93 | 94 | int main() 95 | { 96 | BOOST_TEST_EQ( Y1::instances, 0 ); 97 | 98 | { 99 | variant v; 100 | BOOST_TEST_EQ( Y1::instances, 1 ); 101 | 102 | { 103 | variant v2; 104 | BOOST_TEST_EQ( Y1::instances, 2 ); 105 | 106 | v = v2; 107 | BOOST_TEST_EQ( Y1::instances, 2 ); 108 | } 109 | 110 | BOOST_TEST_EQ( Y1::instances, 1 ); 111 | 112 | v = Y1{1}; 113 | BOOST_TEST_EQ( Y1::instances, 1 ); 114 | } 115 | 116 | BOOST_TEST_EQ( Y1::instances, 0 ); 117 | BOOST_TEST_EQ( Y2::instances, 0 ); 118 | 119 | { 120 | variant v; 121 | 122 | BOOST_TEST_EQ( Y1::instances, 1 ); 123 | BOOST_TEST_EQ( Y2::instances, 0 ); 124 | 125 | { 126 | variant v2; 127 | BOOST_TEST_EQ( Y1::instances, 2 ); 128 | BOOST_TEST_EQ( Y2::instances, 0 ); 129 | 130 | v = v2; 131 | BOOST_TEST_EQ( Y1::instances, 2 ); 132 | BOOST_TEST_EQ( Y2::instances, 0 ); 133 | 134 | v2 = Y2{1}; 135 | BOOST_TEST_EQ( Y1::instances, 1 ); 136 | BOOST_TEST_EQ( Y2::instances, 1 ); 137 | 138 | v = v2; 139 | BOOST_TEST_EQ( Y1::instances, 0 ); 140 | BOOST_TEST_EQ( Y2::instances, 2 ); 141 | } 142 | 143 | BOOST_TEST_EQ( Y1::instances, 0 ); 144 | BOOST_TEST_EQ( Y2::instances, 1 ); 145 | 146 | v.emplace<0>(); 147 | 148 | BOOST_TEST_EQ( Y1::instances, 1 ); 149 | BOOST_TEST_EQ( Y2::instances, 0 ); 150 | 151 | v.emplace(); 152 | 153 | BOOST_TEST_EQ( Y1::instances, 0 ); 154 | BOOST_TEST_EQ( Y2::instances, 1 ); 155 | } 156 | 157 | BOOST_TEST_EQ( Y1::instances, 0 ); 158 | BOOST_TEST_EQ( Y2::instances, 0 ); 159 | 160 | BOOST_TEST_EQ( X1::instances, 0 ); 161 | BOOST_TEST_EQ( X2::instances, 0 ); 162 | 163 | { 164 | variant v; 165 | 166 | BOOST_TEST_EQ( X1::instances, 1 ); 167 | BOOST_TEST_EQ( X2::instances, 0 ); 168 | 169 | { 170 | variant v2; 171 | BOOST_TEST_EQ( X1::instances, 2 ); 172 | BOOST_TEST_EQ( X2::instances, 0 ); 173 | 174 | v = v2; 175 | BOOST_TEST_EQ( X1::instances, 2 ); 176 | BOOST_TEST_EQ( X2::instances, 0 ); 177 | 178 | v2 = X2{1}; 179 | BOOST_TEST_EQ( X1::instances, 1 ); 180 | BOOST_TEST_EQ( X2::instances, 1 ); 181 | 182 | v = v2; 183 | BOOST_TEST_EQ( X1::instances, 0 ); 184 | BOOST_TEST_EQ( X2::instances, 2 ); 185 | } 186 | 187 | BOOST_TEST_EQ( X1::instances, 0 ); 188 | BOOST_TEST_EQ( X2::instances, 1 ); 189 | 190 | v.emplace<0>(); 191 | 192 | BOOST_TEST_EQ( X1::instances, 1 ); 193 | BOOST_TEST_EQ( X2::instances, 0 ); 194 | 195 | v.emplace(); 196 | 197 | BOOST_TEST_EQ( X1::instances, 0 ); 198 | BOOST_TEST_EQ( X2::instances, 1 ); 199 | } 200 | 201 | BOOST_TEST_EQ( X1::instances, 0 ); 202 | BOOST_TEST_EQ( X2::instances, 0 ); 203 | 204 | return boost::report_errors(); 205 | } 206 | -------------------------------------------------------------------------------- /test/variant_convert_construct.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | int v; 23 | 24 | X1(): v(0) {} 25 | explicit X1(int v): v(v) {} 26 | X1(X1 const& r): v(r.v) {} 27 | X1(X1&& r): v(r.v) {} 28 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 29 | X1& operator=( X1&& r ) { v = r.v; return *this; } 30 | }; 31 | 32 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 33 | 34 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 35 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 36 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 37 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 38 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 39 | 40 | struct X2 41 | { 42 | int v; 43 | 44 | X2(): v(0) {} 45 | explicit X2(int v): v(v) {} 46 | X2(X2 const& r): v(r.v) {} 47 | X2(X2&& r): v(r.v) {} 48 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 49 | X2& operator=( X2&& r ) { v = r.v; return *this; } 50 | }; 51 | 52 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 53 | 54 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 55 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 56 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 57 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 58 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 59 | 60 | int main() 61 | { 62 | { 63 | variant v( 1 ); 64 | 65 | variant v2( v ); 66 | 67 | BOOST_TEST( holds_alternative( v2 ) ); 68 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 69 | 70 | variant v3( std::move(v) ); 71 | 72 | BOOST_TEST( holds_alternative( v3 ) ); 73 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 74 | } 75 | 76 | { 77 | variant const v( 1 ); 78 | 79 | variant v2( v ); 80 | 81 | BOOST_TEST( holds_alternative( v2 ) ); 82 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 83 | 84 | variant v3( std::move(v) ); 85 | 86 | BOOST_TEST( holds_alternative( v3 ) ); 87 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 88 | } 89 | 90 | { 91 | variant v( 1 ); 92 | 93 | variant v2( v ); 94 | 95 | BOOST_TEST( holds_alternative( v2 ) ); 96 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 97 | 98 | variant v3( std::move(v) ); 99 | 100 | BOOST_TEST( holds_alternative( v3 ) ); 101 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 102 | } 103 | 104 | { 105 | variant const v( 1 ); 106 | 107 | variant v2( v ); 108 | 109 | BOOST_TEST( holds_alternative( v2 ) ); 110 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 111 | 112 | variant v3( std::move(v) ); 113 | 114 | BOOST_TEST( holds_alternative( v3 ) ); 115 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 116 | } 117 | 118 | { 119 | variant v( 3.14f ); 120 | 121 | variant v2( v ); 122 | 123 | BOOST_TEST( holds_alternative( v2 ) ); 124 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 125 | 126 | variant v3( std::move(v) ); 127 | 128 | BOOST_TEST( holds_alternative( v3 ) ); 129 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 130 | } 131 | 132 | { 133 | variant v( 3.15f ); 134 | 135 | variant v2( v ); 136 | 137 | BOOST_TEST( holds_alternative( v2 ) ); 138 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 139 | 140 | variant v3( std::move(v) ); 141 | 142 | BOOST_TEST( holds_alternative( v3 ) ); 143 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 144 | } 145 | 146 | { 147 | variant v( "s1" ); 148 | 149 | variant v2( v ); 150 | 151 | BOOST_TEST( holds_alternative( v2 ) ); 152 | BOOST_TEST_EQ( get( v ), get( v2 ) ); 153 | 154 | variant v3( std::move(v) ); 155 | 156 | BOOST_TEST( holds_alternative( v3 ) ); 157 | BOOST_TEST_EQ( get( v2 ), get( v3 ) ); 158 | } 159 | 160 | { 161 | variant v{ X1{1} }; 162 | 163 | variant v2( v ); 164 | 165 | BOOST_TEST( holds_alternative( v2 ) ); 166 | BOOST_TEST_EQ( get( v ).v, get( v2 ).v ); 167 | 168 | variant v3( std::move(v) ); 169 | 170 | BOOST_TEST( holds_alternative( v3 ) ); 171 | BOOST_TEST_EQ( get( v2 ).v, get( v3 ).v ); 172 | } 173 | 174 | return boost::report_errors(); 175 | } 176 | -------------------------------------------------------------------------------- /test/Jamfile: -------------------------------------------------------------------------------- 1 | # Boost.Variant2 Library Test Jamfile 2 | # 3 | # Copyright 2015-2019 Peter Dimov 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # See accompanying file LICENSE_1_0.txt or copy at 7 | # http://www.boost.org/LICENSE_1_0.txt 8 | 9 | import testing ; 10 | import-search /boost/config/checks ; 11 | import config : requires ; 12 | 13 | project 14 | : default-build 15 | 16 | extra 17 | 18 | : requirements 19 | 20 | /boost/variant2//boost_variant2 21 | /boost/core//boost_core 22 | /boost/container_hash//boost_container_hash 23 | 24 | msvc:on 25 | gcc:on 26 | clang:on 27 | 28 | ; 29 | 30 | run quick.cpp ; 31 | 32 | run variant_size.cpp ; 33 | run variant_alternative.cpp ; 34 | 35 | run variant_holds_alternative.cpp ; 36 | compile variant_holds_alternative_cx.cpp : msvc-14.0:no ; 37 | 38 | run variant_get_by_index.cpp ; 39 | compile variant_get_by_index_cx.cpp : msvc-14.0:no ; 40 | 41 | run variant_get_by_type.cpp ; 42 | compile variant_get_by_type_cx.cpp : msvc-14.0:no ; 43 | 44 | run variant_default_construct.cpp ; 45 | compile variant_default_construct_cx.cpp : msvc-14.0:no ; 46 | 47 | run variant_copy_construct.cpp ; 48 | compile variant_copy_construct_cx.cpp : msvc-14.0:no ; 49 | 50 | run variant_move_construct.cpp ; 51 | compile variant_move_construct_cx.cpp : [ requires cxx14_constexpr ] ; 52 | 53 | run variant_value_construct.cpp ; 54 | compile variant_value_construct_cx.cpp : msvc-14.0:no ; 55 | 56 | run variant_in_place_index_construct.cpp ; 57 | compile variant_in_place_index_construct_cx.cpp : msvc-14.0:no ; 58 | 59 | run variant_in_place_type_construct.cpp ; 60 | compile variant_in_place_type_construct_cx.cpp : msvc-14.0:no ; 61 | 62 | run variant_copy_assign.cpp ; 63 | compile variant_copy_assign_cx.cpp : [ requires cxx14_constexpr ] gcc-5:no gcc-6:no ; 64 | 65 | run variant_move_assign.cpp ; 66 | compile variant_move_assign_cx.cpp : [ requires cxx14_constexpr ] gcc-5:no gcc-6:no ; 67 | 68 | run variant_value_assign.cpp ; 69 | compile variant_value_assign_cx.cpp : [ requires cxx14_constexpr ] ; 70 | 71 | run variant_emplace_index.cpp ; 72 | compile variant_emplace_index_cx.cpp : [ requires cxx14_constexpr ] ; 73 | 74 | run variant_emplace_type.cpp ; 75 | compile variant_emplace_type_cx.cpp : [ requires cxx14_constexpr ] ; 76 | 77 | run variant_swap.cpp ; 78 | 79 | run variant_eq_ne.cpp ; 80 | compile variant_eq_ne_cx.cpp : [ requires cxx14_constexpr ] ; 81 | 82 | run variant_lt_gt.cpp ; 83 | compile variant_lt_gt_cx.cpp : [ requires cxx14_constexpr ] ; 84 | 85 | run variant_destroy.cpp ; 86 | run variant_visit.cpp ; 87 | 88 | run variant_convert_construct.cpp ; 89 | run variant_subset.cpp ; 90 | run variant_valueless.cpp ; 91 | 92 | run variant_copy_construct_throw.cpp ; 93 | run variant_move_construct_throw.cpp ; 94 | run variant_convert_construct_throw.cpp ; 95 | 96 | run variant_copy_assign_throw.cpp ; 97 | run variant_move_assign_throw.cpp ; 98 | 99 | local NX = 100 | off 101 | msvc:/wd4530 102 | msvc:/wd4577 103 | ; 104 | 105 | run variant_get_by_index.cpp throw_exception.cpp : : : $(NX) : variant_get_by_index_nx ; 106 | compile variant_get_by_index_cx.cpp : $(NX) msvc-14.0:no : variant_get_by_index_cx_nx ; 107 | 108 | run variant_get_by_type.cpp throw_exception.cpp : : : $(NX) : variant_get_by_type_nx ; 109 | compile variant_get_by_type_cx.cpp : $(NX) msvc-14.0:no : variant_get_by_type_cx_nx ; 110 | 111 | run variant_subset.cpp throw_exception.cpp : : : $(NX) : variant_subset_nx ; 112 | 113 | run variant_hash.cpp ; 114 | 115 | run variant_trivial.cpp ; 116 | run variant_special.cpp ; 117 | 118 | run variant_visit_derived.cpp ; 119 | 120 | run variant_many_types.cpp ; 121 | 122 | run variant_visit_r.cpp : : : 123 | gcc,windows:release 124 | gcc,cygwin:release 125 | ; 126 | 127 | compile variant_derived_construct.cpp ; 128 | 129 | run variant_visit_by_index.cpp ; 130 | 131 | run variant_ostream_insert.cpp ; 132 | run is_output_streamable.cpp ; 133 | 134 | local JSON = /boost/json//boost_json/off "msvc-14.0:no" "msvc-14.2:-wd5104" "norecover:static" ; 135 | 136 | run variant_json_value_from.cpp : : : $(JSON) ; 137 | run variant_json_value_to.cpp : : : $(JSON) ; 138 | 139 | compile variant_uses_double_storage.cpp ; 140 | 141 | run variant_derived_construct2.cpp ; 142 | 143 | compile variant_visit_cx.cpp : [ requires cxx14_constexpr ] ; 144 | compile variant_visit_cx_2.cpp : [ requires cxx14_constexpr ] ; 145 | compile variant_visit_r_cx.cpp : [ requires cxx14_constexpr ] ; 146 | 147 | local index-type-reqs = 148 | 149 | release 150 | msvc,32:no 151 | clang,linux:-ftemplate-depth=1024 # for Clang 3.x 152 | ; 153 | 154 | local list-sizes = 126 127 128 129 254 255 256 257 ; 155 | 156 | for local list-size in $(list-sizes) 157 | { 158 | run variant_index_type.cpp : : : $(index-type-reqs) LIST_SIZE=$(list-size) : variant_index_type_$(list-size) ; 159 | } 160 | 161 | compile variant_default_construct_cx_2.cpp ; 162 | compile variant_default_construct_cx_3.cpp ; 163 | compile variant_default_construct_cx_4.cpp ; 164 | compile variant_default_construct_cx_5.cpp ; 165 | 166 | compile variant_value_construct_cx_2.cpp ; 167 | compile variant_value_construct_cx_3.cpp ; 168 | compile variant_value_construct_cx_4.cpp ; 169 | -------------------------------------------------------------------------------- /test/variant_emplace_type.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | int v; 23 | 24 | X1(): v(0) {} 25 | explicit X1(int v): v(v) {} 26 | X1(X1 const& r): v(r.v) {} 27 | X1(X1&& r): v(r.v) {} 28 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 29 | X1& operator=( X1&& r ) { v = r.v; return *this; } 30 | }; 31 | 32 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 33 | 34 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 35 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 36 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 37 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 38 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 39 | 40 | struct X2 41 | { 42 | int v; 43 | 44 | X2(): v(0) {} 45 | explicit X2(int v): v(v) {} 46 | X2(X2 const& r): v(r.v) {} 47 | X2(X2&& r): v(r.v) {} 48 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 49 | X2& operator=( X2&& r ) { v = r.v; return *this; } 50 | }; 51 | 52 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 53 | 54 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 55 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 56 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 57 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 58 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 59 | 60 | struct Y1 61 | { 62 | }; 63 | 64 | struct Y2 65 | { 66 | ~Y2() {} 67 | }; 68 | 69 | struct Guard 70 | { 71 | explicit Guard(int) {} 72 | Guard(Guard&&) = delete; 73 | }; 74 | 75 | int main() 76 | { 77 | { 78 | variant v; 79 | BOOST_TEST_EQ( get<0>(v), 0 ); 80 | 81 | v.emplace( 1 ); 82 | BOOST_TEST_EQ( get<0>(v), 1 ); 83 | 84 | v.emplace(); 85 | BOOST_TEST_EQ( get<0>(v), 0 ); 86 | } 87 | 88 | { 89 | variant v; 90 | BOOST_TEST_EQ( v.index(), 0 ); 91 | BOOST_TEST_EQ( get<0>(v), 0 ); 92 | 93 | v.emplace( 1 ); 94 | BOOST_TEST_EQ( v.index(), 0 ); 95 | BOOST_TEST_EQ( get<0>(v), 1 ); 96 | 97 | v.emplace( 3.14f ); 98 | BOOST_TEST_EQ( v.index(), 1 ); 99 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 100 | 101 | v.emplace(); 102 | BOOST_TEST_EQ( v.index(), 1 ); 103 | BOOST_TEST_EQ( get<1>(v), 0 ); 104 | 105 | v.emplace(); 106 | BOOST_TEST_EQ( v.index(), 0 ); 107 | BOOST_TEST_EQ( get<0>(v), 0 ); 108 | } 109 | 110 | { 111 | variant v; 112 | BOOST_TEST_EQ( v.index(), 0 ); 113 | BOOST_TEST_EQ( get<0>(v), 0 ); 114 | 115 | v.emplace( 3.14f ); 116 | BOOST_TEST_EQ( v.index(), 2 ); 117 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 118 | 119 | v.emplace(); 120 | BOOST_TEST_EQ( v.index(), 2 ); 121 | BOOST_TEST_EQ( get<2>(v), 0 ); 122 | 123 | v.emplace( "s1" ); 124 | BOOST_TEST_EQ( v.index(), 3 ); 125 | BOOST_TEST_EQ( get<3>(v), std::string("s1") ); 126 | 127 | v.emplace( "s2" ); 128 | BOOST_TEST_EQ( v.index(), 3 ); 129 | BOOST_TEST_EQ( get<3>(v), std::string("s2") ); 130 | 131 | v.emplace(); 132 | BOOST_TEST_EQ( v.index(), 3 ); 133 | BOOST_TEST_EQ( get<3>(v), std::string() ); 134 | 135 | v.emplace( { 'a', 'b' } ); 136 | BOOST_TEST_EQ( v.index(), 3 ); 137 | BOOST_TEST_EQ( get<3>(v), (std::string{ 'a', 'b' }) ); 138 | 139 | v.emplace( { 'c', 'd' }, std::allocator() ); 140 | BOOST_TEST_EQ( v.index(), 3 ); 141 | BOOST_TEST_EQ( get<3>(v), (std::string{ 'c', 'd' }) ); 142 | } 143 | 144 | { 145 | variant v; 146 | BOOST_TEST_EQ( v.index(), 0 ); 147 | BOOST_TEST_EQ( get<0>(v).v, 0 ); 148 | 149 | v.emplace( 1 ); 150 | BOOST_TEST_EQ( v.index(), 0 ); 151 | BOOST_TEST_EQ( get<0>(v).v, 1 ); 152 | 153 | v.emplace( 2 ); 154 | BOOST_TEST_EQ( v.index(), 1 ); 155 | BOOST_TEST_EQ( get<1>(v).v, 2 ); 156 | 157 | v.emplace(); 158 | BOOST_TEST_EQ( v.index(), 0 ); 159 | BOOST_TEST_EQ( get<0>(v).v, 0 ); 160 | 161 | v.emplace( 4 ); 162 | BOOST_TEST_EQ( v.index(), 0 ); 163 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 164 | 165 | v.emplace(); 166 | 167 | BOOST_TEST_EQ( v.index(), 1 ); 168 | BOOST_TEST_EQ( get<1>(v).v, 0 ); 169 | 170 | v.emplace( 6 ); 171 | BOOST_TEST_EQ( v.index(), 1 ); 172 | BOOST_TEST_EQ( get<1>(v).v, 6 ); 173 | 174 | v.emplace( 3 ); 175 | BOOST_TEST_EQ( v.index(), 0 ); 176 | BOOST_TEST_EQ( get<0>(v).v, 3 ); 177 | 178 | v.emplace( 4 ); 179 | BOOST_TEST_EQ( v.index(), 0 ); 180 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 181 | } 182 | 183 | { 184 | variant v; 185 | v.emplace( 1 ); 186 | } 187 | 188 | { 189 | variant v; 190 | v.emplace( 1 ); 191 | } 192 | 193 | return boost::report_errors(); 194 | } 195 | -------------------------------------------------------------------------------- /test/variant_value_assign.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | int v; 23 | 24 | X1(): v(0) {} 25 | explicit X1(int v): v(v) {} 26 | X1(X1 const& r): v(r.v) {} 27 | X1(X1&& r): v(r.v) {} 28 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 29 | X1& operator=( X1&& r ) { v = r.v; return *this; } 30 | }; 31 | 32 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 33 | 34 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 35 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 36 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 37 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 38 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 39 | 40 | struct X2 41 | { 42 | int v; 43 | 44 | X2(): v(0) {} 45 | explicit X2(int v): v(v) {} 46 | X2(X2 const& r): v(r.v) {} 47 | X2(X2&& r): v(r.v) {} 48 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 49 | X2& operator=( X2&& r ) { v = r.v; return *this; } 50 | }; 51 | 52 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 53 | 54 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 55 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 56 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 57 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 58 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 59 | 60 | int main() 61 | { 62 | { 63 | variant v; 64 | BOOST_TEST_EQ( get<0>(v), 0 ); 65 | 66 | v = 1; 67 | BOOST_TEST_EQ( get<0>(v), 1 ); 68 | 69 | v = 2; 70 | BOOST_TEST_EQ( get<0>(v), 2 ); 71 | 72 | int w1 = 3; 73 | 74 | v = w1; 75 | BOOST_TEST_EQ( get<0>(v), 3 ); 76 | 77 | int const w2 = 4; 78 | 79 | v = w2; 80 | BOOST_TEST_EQ( get<0>(v), 4 ); 81 | 82 | v = std::move( w1 ); 83 | BOOST_TEST_EQ( get<0>(v), 3 ); 84 | 85 | v = std::move( w2 ); 86 | BOOST_TEST_EQ( get<0>(v), 4 ); 87 | } 88 | 89 | { 90 | variant v; 91 | BOOST_TEST_EQ( v.index(), 0 ); 92 | BOOST_TEST_EQ( get<0>(v), 0 ); 93 | 94 | v = 1; 95 | BOOST_TEST_EQ( v.index(), 0 ); 96 | BOOST_TEST_EQ( get<0>(v), 1 ); 97 | 98 | v = 3.14f; 99 | BOOST_TEST_EQ( v.index(), 1 ); 100 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 101 | 102 | float w1 = 3.15f; 103 | 104 | v = w1; 105 | BOOST_TEST_EQ( v.index(), 1 ); 106 | BOOST_TEST_EQ( get<1>(v), 3.15f ); 107 | 108 | int const w2 = 2; 109 | 110 | v = w2; 111 | BOOST_TEST_EQ( v.index(), 0 ); 112 | BOOST_TEST_EQ( get<0>(v), 2 ); 113 | 114 | v = std::move(w1); 115 | BOOST_TEST_EQ( v.index(), 1 ); 116 | BOOST_TEST_EQ( get<1>(v), 3.15f ); 117 | 118 | v = std::move(w2); 119 | BOOST_TEST_EQ( v.index(), 0 ); 120 | BOOST_TEST_EQ( get<0>(v), 2 ); 121 | } 122 | 123 | { 124 | variant v; 125 | BOOST_TEST_EQ( v.index(), 0 ); 126 | BOOST_TEST_EQ( get<0>(v), 0 ); 127 | 128 | v = 3.14f; 129 | BOOST_TEST_EQ( v.index(), 2 ); 130 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 131 | 132 | float const w1 = 3.15f; 133 | 134 | v = w1; 135 | BOOST_TEST_EQ( v.index(), 2 ); 136 | BOOST_TEST_EQ( get<2>(v), 3.15f ); 137 | 138 | variant v5( "s1" ); 139 | 140 | v = "s1"; 141 | BOOST_TEST_EQ( v.index(), 3 ); 142 | BOOST_TEST_EQ( get<3>(v), std::string("s1") ); 143 | 144 | std::string w2( "s2" ); 145 | 146 | v = w2; 147 | BOOST_TEST_EQ( v.index(), 3 ); 148 | BOOST_TEST_EQ( get<3>(v), std::string("s2") ); 149 | 150 | v = std::move(w1); 151 | BOOST_TEST_EQ( v.index(), 2 ); 152 | BOOST_TEST_EQ( get<2>(v), 3.15f ); 153 | 154 | v = std::move(w2); 155 | BOOST_TEST_EQ( v.index(), 3 ); 156 | BOOST_TEST_EQ( get<3>(v), std::string("s2") ); 157 | } 158 | 159 | { 160 | variant v; 161 | BOOST_TEST_EQ( v.index(), 0 ); 162 | BOOST_TEST_EQ( get<0>(v).v, 0 ); 163 | 164 | v = X1{1}; 165 | BOOST_TEST_EQ( v.index(), 0 ); 166 | BOOST_TEST_EQ( get<0>(v).v, 1 ); 167 | 168 | v = X2{2}; 169 | BOOST_TEST_EQ( v.index(), 1 ); 170 | BOOST_TEST_EQ( get<1>(v).v, 2 ); 171 | 172 | X1 w1{3}; 173 | 174 | v = w1; 175 | BOOST_TEST_EQ( v.index(), 0 ); 176 | BOOST_TEST_EQ( get<0>(v).v, 3 ); 177 | 178 | X1 const w2{4}; 179 | 180 | v = w2; 181 | BOOST_TEST_EQ( v.index(), 0 ); 182 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 183 | 184 | X2 w3{5}; 185 | 186 | v = w3; 187 | BOOST_TEST_EQ( v.index(), 1 ); 188 | BOOST_TEST_EQ( get<1>(v).v, 5 ); 189 | 190 | X2 const w4{6}; 191 | 192 | v = w4; 193 | BOOST_TEST_EQ( v.index(), 1 ); 194 | BOOST_TEST_EQ( get<1>(v).v, 6 ); 195 | 196 | v = std::move(w1); 197 | BOOST_TEST_EQ( v.index(), 0 ); 198 | BOOST_TEST_EQ( get<0>(v).v, 3 ); 199 | 200 | v = std::move(w2); 201 | BOOST_TEST_EQ( v.index(), 0 ); 202 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 203 | } 204 | 205 | return boost::report_errors(); 206 | } 207 | -------------------------------------------------------------------------------- /test/variant_copy_assign.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | int v; 23 | 24 | X1(): v(0) {} 25 | explicit X1(int v): v(v) {} 26 | X1(X1 const& r): v(r.v) {} 27 | X1(X1&& r): v(r.v) {} 28 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 29 | X1& operator=( X1&& r ) { v = r.v; return *this; } 30 | }; 31 | 32 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 33 | 34 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 35 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 36 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 37 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 38 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 39 | 40 | struct X2 41 | { 42 | int v; 43 | 44 | X2(): v(0) {} 45 | explicit X2(int v): v(v) {} 46 | X2(X2 const& r): v(r.v) {} 47 | X2(X2&& r): v(r.v) {} 48 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 49 | X2& operator=( X2&& r ) { v = r.v; return *this; } 50 | }; 51 | 52 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 53 | 54 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 55 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 56 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 57 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 58 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 59 | 60 | struct Y 61 | { 62 | Y& operator=( Y const& ) = delete; 63 | }; 64 | 65 | int main() 66 | { 67 | { 68 | variant v; 69 | BOOST_TEST_EQ( get<0>(v), 0 ); 70 | 71 | variant v2( 1 ); 72 | 73 | v = v2; 74 | BOOST_TEST_EQ( get<0>(v), 1 ); 75 | 76 | variant const v3( 2 ); 77 | 78 | v = v3; 79 | BOOST_TEST_EQ( get<0>(v), 2 ); 80 | } 81 | 82 | { 83 | variant v; 84 | BOOST_TEST_EQ( v.index(), 0 ); 85 | BOOST_TEST_EQ( get<0>(v), 0 ); 86 | 87 | variant v2( 1 ); 88 | 89 | v = v2; 90 | BOOST_TEST_EQ( v.index(), 0 ); 91 | BOOST_TEST_EQ( get<0>(v), 1 ); 92 | 93 | variant v3( 3.14f ); 94 | 95 | v = v3; 96 | BOOST_TEST_EQ( v.index(), 1 ); 97 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 98 | 99 | variant const v4( 3.15f ); 100 | 101 | v = v4; 102 | BOOST_TEST_EQ( v.index(), 1 ); 103 | BOOST_TEST_EQ( get<1>(v), 3.15f ); 104 | } 105 | 106 | { 107 | variant v; 108 | BOOST_TEST_EQ( v.index(), 0 ); 109 | BOOST_TEST_EQ( get<0>(v), 0 ); 110 | 111 | variant v2( in_place_index_t<1>{}, 1 ); 112 | 113 | v = v2; 114 | BOOST_TEST_EQ( v.index(), 1 ); 115 | BOOST_TEST_EQ( get<1>(v), 1 ); 116 | 117 | variant v3( 3.14f ); 118 | 119 | v = v3; 120 | BOOST_TEST_EQ( v.index(), 2 ); 121 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 122 | 123 | variant const v4( 3.15f ); 124 | 125 | v = v4; 126 | BOOST_TEST_EQ( v.index(), 2 ); 127 | BOOST_TEST_EQ( get<2>(v), 3.15f ); 128 | 129 | variant v5( "s1" ); 130 | 131 | v = v5; 132 | BOOST_TEST_EQ( v.index(), 3 ); 133 | BOOST_TEST_EQ( get<3>(v), std::string("s1") ); 134 | 135 | variant const v6( "s2" ); 136 | 137 | v = v6; 138 | BOOST_TEST_EQ( v.index(), 3 ); 139 | BOOST_TEST_EQ( get<3>(v), std::string("s2") ); 140 | } 141 | 142 | { 143 | variant v; 144 | BOOST_TEST_EQ( v.index(), 0 ); 145 | BOOST_TEST_EQ( get<0>(v).v, 0 ); 146 | 147 | variant v2( X1{1} ); 148 | 149 | v = v2; 150 | BOOST_TEST_EQ( v.index(), 0 ); 151 | BOOST_TEST_EQ( get<0>(v).v, 1 ); 152 | 153 | variant v3( in_place_index_t<1>{}, 2 ); 154 | 155 | v = v3; 156 | BOOST_TEST_EQ( v.index(), 1 ); 157 | BOOST_TEST_EQ( get<1>(v).v, 2 ); 158 | 159 | variant const v4( in_place_index_t<1>{}, 3 ); 160 | 161 | v = v4; 162 | BOOST_TEST_EQ( v.index(), 1 ); 163 | BOOST_TEST_EQ( get<1>(v).v, 3 ); 164 | 165 | variant const v5( in_place_index_t<0>{}, 4 ); 166 | 167 | v = v5; 168 | BOOST_TEST_EQ( v.index(), 0 ); 169 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 170 | } 171 | 172 | { 173 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable>)); 174 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable>)); 175 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable>)); 176 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable>)); 177 | 178 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 179 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 180 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 181 | 182 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 183 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 184 | 185 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 186 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable>)); 187 | 188 | BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable>)); 189 | BOOST_TEST_TRAIT_FALSE((std::is_copy_assignable>)); 190 | BOOST_TEST_TRAIT_FALSE((std::is_copy_assignable>)); 191 | } 192 | 193 | return boost::report_errors(); 194 | } 195 | -------------------------------------------------------------------------------- /test/variant_move_assign.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright 2017 Peter Dimov. 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. 5 | // 6 | // See accompanying file LICENSE_1_0.txt or copy at 7 | // http://www.boost.org/LICENSE_1_0.txt 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace boost::variant2; 17 | 18 | #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) 19 | 20 | struct X1 21 | { 22 | int v; 23 | 24 | X1(): v(0) {} 25 | explicit X1(int v): v(v) {} 26 | X1(X1 const& r): v(r.v) {} 27 | X1(X1&& r): v(r.v) {} 28 | X1& operator=( X1 const& r ) { v = r.v; return *this; } 29 | X1& operator=( X1&& r ) { v = r.v; return *this; } 30 | }; 31 | 32 | inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } 33 | 34 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 35 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 36 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 37 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 38 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 39 | 40 | struct X2 41 | { 42 | int v; 43 | 44 | X2(): v(0) {} 45 | explicit X2(int v): v(v) {} 46 | X2(X2 const& r): v(r.v) {} 47 | X2(X2&& r): v(r.v) {} 48 | X2& operator=( X2 const& r ) { v = r.v; return *this; } 49 | X2& operator=( X2&& r ) { v = r.v; return *this; } 50 | }; 51 | 52 | inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } 53 | 54 | STATIC_ASSERT( !std::is_nothrow_default_constructible::value ); 55 | STATIC_ASSERT( !std::is_nothrow_copy_constructible::value ); 56 | STATIC_ASSERT( !std::is_nothrow_move_constructible::value ); 57 | STATIC_ASSERT( !std::is_nothrow_copy_assignable::value ); 58 | STATIC_ASSERT( !std::is_nothrow_move_assignable::value ); 59 | 60 | struct Y 61 | { 62 | Y& operator=( Y&& ) = delete; 63 | }; 64 | 65 | int main() 66 | { 67 | { 68 | variant v; 69 | BOOST_TEST_EQ( get<0>(v), 0 ); 70 | 71 | variant v2( 1 ); 72 | 73 | v = std::move(v2); 74 | BOOST_TEST_EQ( get<0>(v), 1 ); 75 | 76 | variant v3( 2 ); 77 | 78 | v = std::move(v3); 79 | BOOST_TEST_EQ( get<0>(v), 2 ); 80 | } 81 | 82 | { 83 | variant v; 84 | BOOST_TEST_EQ( v.index(), 0 ); 85 | BOOST_TEST_EQ( get<0>(v), 0 ); 86 | 87 | variant v2( 1 ); 88 | 89 | v = std::move(v2); 90 | BOOST_TEST_EQ( v.index(), 0 ); 91 | BOOST_TEST_EQ( get<0>(v), 1 ); 92 | 93 | variant v3( 3.14f ); 94 | 95 | v = std::move(v3); 96 | BOOST_TEST_EQ( v.index(), 1 ); 97 | BOOST_TEST_EQ( get<1>(v), 3.14f ); 98 | 99 | variant v4( 3.15f ); 100 | 101 | v = std::move(v4); 102 | BOOST_TEST_EQ( v.index(), 1 ); 103 | BOOST_TEST_EQ( get<1>(v), 3.15f ); 104 | } 105 | 106 | { 107 | variant v; 108 | BOOST_TEST_EQ( v.index(), 0 ); 109 | BOOST_TEST_EQ( get<0>(v), 0 ); 110 | 111 | variant v2( in_place_index_t<1>{}, 1 ); 112 | 113 | v = std::move(v2); 114 | BOOST_TEST_EQ( v.index(), 1 ); 115 | BOOST_TEST_EQ( get<1>(v), 1 ); 116 | 117 | variant v3( 3.14f ); 118 | 119 | v = std::move(v3); 120 | BOOST_TEST_EQ( v.index(), 2 ); 121 | BOOST_TEST_EQ( get<2>(v), 3.14f ); 122 | 123 | variant v4( 3.15f ); 124 | 125 | v = std::move(v4); 126 | BOOST_TEST_EQ( v.index(), 2 ); 127 | BOOST_TEST_EQ( get<2>(v), 3.15f ); 128 | 129 | variant v5( "s1" ); 130 | 131 | v = std::move(v5); 132 | BOOST_TEST_EQ( v.index(), 3 ); 133 | BOOST_TEST_EQ( get<3>(v), std::string("s1") ); 134 | 135 | variant v6( "s2" ); 136 | 137 | v = std::move(v6); 138 | BOOST_TEST_EQ( v.index(), 3 ); 139 | BOOST_TEST_EQ( get<3>(v), std::string("s2") ); 140 | } 141 | 142 | { 143 | variant v; 144 | BOOST_TEST_EQ( v.index(), 0 ); 145 | BOOST_TEST_EQ( get<0>(v).v, 0 ); 146 | 147 | variant v2( X1{1} ); 148 | 149 | v = std::move(v2); 150 | BOOST_TEST_EQ( v.index(), 0 ); 151 | BOOST_TEST_EQ( get<0>(v).v, 1 ); 152 | 153 | variant v3( in_place_index_t<1>{}, 2 ); 154 | 155 | v = std::move(v3); 156 | BOOST_TEST_EQ( v.index(), 1 ); 157 | BOOST_TEST_EQ( get<1>(v).v, 2 ); 158 | 159 | variant v4( in_place_index_t<1>{}, 3 ); 160 | 161 | v = std::move(v4); 162 | BOOST_TEST_EQ( v.index(), 1 ); 163 | BOOST_TEST_EQ( get<1>(v).v, 3 ); 164 | 165 | variant v5( in_place_index_t<0>{}, 4 ); 166 | 167 | v = std::move(v5); 168 | BOOST_TEST_EQ( v.index(), 0 ); 169 | BOOST_TEST_EQ( get<0>(v).v, 4 ); 170 | } 171 | 172 | { 173 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable>)); 174 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable>)); 175 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable>)); 176 | BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable>)); 177 | 178 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 179 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 180 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 181 | 182 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 183 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 184 | 185 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 186 | BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable>)); 187 | 188 | BOOST_TEST_TRAIT_TRUE((std::is_move_assignable>)); 189 | BOOST_TEST_TRAIT_FALSE((std::is_move_assignable>)); 190 | BOOST_TEST_TRAIT_FALSE((std::is_move_assignable>)); 191 | } 192 | 193 | return boost::report_errors(); 194 | } 195 | --------------------------------------------------------------------------------