├── 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