diff options
Diffstat (limited to '')
98 files changed, 12819 insertions, 0 deletions
diff --git a/src/boost/libs/variant/CMakeLists.txt b/src/boost/libs/variant/CMakeLists.txt new file mode 100644 index 00000000..1984c195 --- /dev/null +++ b/src/boost/libs/variant/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright 2019 Mike Dev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# +# NOTE: CMake support for Boost.Variant is currently experimental at best +# and the interface is likely to change in the future + +cmake_minimum_required( VERSION 3.5 ) +project( BoostVariant LANGUAGES CXX ) + +add_library( boost_variant INTERFACE ) +add_library( Boost::variant ALIAS boost_variant ) + +target_include_directories( boost_variant INTERFACE include ) + +target_link_libraries( boost_variant + INTERFACE + Boost::assert + Boost::bind + Boost::config + Boost::container_hash + Boost::core + Boost::detail + Boost::integer + Boost::move + Boost::mpl + Boost::preprocessor + Boost::static_assert + Boost::throw_exception + Boost::type_index + Boost::type_traits + Boost::utility +) diff --git a/src/boost/libs/variant/README.md b/src/boost/libs/variant/README.md new file mode 100644 index 00000000..f66db24a --- /dev/null +++ b/src/boost/libs/variant/README.md @@ -0,0 +1,16 @@ +# [Boost.Variant](http://boost.org/libs/variant) +Boost.Variant, part of collection of the [Boost C++ Libraries](http://github.com/boostorg). It is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner. + +### Test results + +@ | Build | Tests coverage | More info +----------------|-------------- | -------------- |----------- +Develop branch: | [![Build Status](https://travis-ci.org/boostorg/variant.svg?branch=develop)](https://travis-ci.org/boostorg/variant) [![Build status](https://ci.appveyor.com/api/projects/status/bijfdoy7byfgc6e2/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/variant-ykfti/branch/develop) | [![Coverage Status](https://coveralls.io/repos/boostorg/variant/badge.png?branch=develop)](https://coveralls.io/r/apolukhin/variant?branch=develop) | [details...](http://www.boost.org/development/tests/develop/developer/variant.html) +Master branch: | [![Build Status](https://travis-ci.org/boostorg/variant.svg?branch=master)](https://travis-ci.org/boostorg/variant) [![Build status](https://ci.appveyor.com/api/projects/status/bijfdoy7byfgc6e2/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/variant-ykfti/branch/master) | [![Coverage Status](https://coveralls.io/repos/boostorg/variant/badge.png?branch=master)](https://coveralls.io/r/apolukhin/variant?branch=master) | [details...](http://www.boost.org/development/tests/master/developer/variant.html) + + +[Open Issues](https://svn.boost.org/trac/boost/query?status=!closed&component=variant) + +### License + +Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt). diff --git a/src/boost/libs/variant/index.html b/src/boost/libs/variant/index.html new file mode 100644 index 00000000..17fc68c6 --- /dev/null +++ b/src/boost/libs/variant/index.html @@ -0,0 +1,9 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=../../doc/html/variant.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="../../doc/html/variant.html">../../doc/html/variant.html</a> +</body> +</html> diff --git a/src/boost/libs/variant/meta/libraries.json b/src/boost/libs/variant/meta/libraries.json new file mode 100644 index 00000000..e0b9a598 --- /dev/null +++ b/src/boost/libs/variant/meta/libraries.json @@ -0,0 +1,17 @@ +{ + "key": "variant", + "name": "Variant", + "authors": [ + "Eric Friedman", + "Itay Maman" + ], + "description": "Safe, generic, stack-based discriminated union container.", + "category": [ + "Containers", + "Data" + ], + "maintainers": [ + "Antony Polukhin <antoshkka -at- gmail.com>", + "Eric Friedman <ericbrandon -at- gmail.com>" + ] +} diff --git a/src/boost/libs/variant/perf/Jamfile.v2 b/src/boost/libs/variant/perf/Jamfile.v2 new file mode 100644 index 00000000..302f2ef2 --- /dev/null +++ b/src/boost/libs/variant/perf/Jamfile.v2 @@ -0,0 +1,29 @@ +#============================================================================== +# Copyright (c) 2012-2019 Antony Polukhin +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#============================================================================== + +# performance tests +import testing ; +import path ; + +path-constant TEST_DIR : . ; + +project performance/test + : source-location ./ + : requirements +# <library>/boost/chrono//boost_chrono +# <library>/boost/system//boost_system + <link>static + <target-os>freebsd:<linkflags>"-lrt" + <target-os>linux:<linkflags>"-lrt" + <toolset>gcc:<cxxflags>-fvisibility=hidden + <toolset>intel-linux:<cxxflags>-fvisibility=hidden + <toolset>sun:<cxxflags>-xldscope=hidden + : default-build release + ; + +run move_perf.cpp : $(TEST_DIR) ; + diff --git a/src/boost/libs/variant/perf/move_perf.cpp b/src/boost/libs/variant/perf/move_perf.cpp new file mode 100644 index 00000000..efdd31d0 --- /dev/null +++ b/src/boost/libs/variant/perf/move_perf.cpp @@ -0,0 +1,236 @@ +// (C) Copyright Antony Polukhin 2012-2014. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/config for most recent version. + +// +// Testing variant performance rvalue copy/assign performance +// + +#define BOOST_ERROR_CODE_HEADER_ONLY +#define BOOST_CHRONO_HEADER_ONLY +#include <boost/chrono.hpp> + +#include <boost/variant.hpp> +#include <string> +#include <vector> + + struct scope { + typedef boost::chrono::steady_clock test_clock; + typedef boost::chrono::milliseconds duration_t; + test_clock::time_point start_; + const char* const message_; + + explicit scope(const char* const message) + : start_(test_clock::now()) + , message_(message) + {} + + ~scope() { + std::cout << message_ << " " << boost::chrono::duration_cast<duration_t>(test_clock::now() - start_) << std::endl; + } + }; + + + +static void do_test(bool do_count_cleanup_time = false) { + BOOST_STATIC_CONSTANT(std::size_t, c_run_count = 5000000); + typedef std::vector<char> str_t; + typedef boost::variant<int, str_t, float> var_t; + + const char hello1_c[] = "hello long word"; + const str_t hello1(hello1_c, hello1_c + sizeof(hello1_c)); + + const char hello2_c[] = "Helllloooooooooooooooooooooooooooooooo!!!!!!!!!!!!!"; + const str_t hello2(hello2_c, hello2_c + sizeof(hello2_c)); + + if (do_count_cleanup_time) { + std::cout << "#############################################\n"; + std::cout << "#############################################\n"; + std::cout << "NOW TIMES WITH DATA DESTRUCTION\n"; + std::cout << "#############################################\n"; + } + + std::vector<var_t> data_from, data_to; + data_from.resize(c_run_count, hello1); + data_to.reserve(c_run_count); + { + scope sc("boost::variant(const variant&) copying speed"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to.push_back(data_from[i]); + + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + data_from.resize(c_run_count, hello1); + data_to.clear(); + data_to.reserve(c_run_count); + { + scope sc("boost::variant(variant&&) moving speed"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to.push_back(boost::move(data_from[i])); + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + std::cout << "#############################################\n"; + + data_from.clear(); + data_from.resize(c_run_count, hello2); + data_to.clear(); + data_to.resize(c_run_count, hello2); + { + scope sc("boost::variant=(const variant&) copying speed on same types"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = data_from[i]; + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + data_from.resize(c_run_count, hello2); + data_to.clear(); + data_to.resize(c_run_count, hello2); + { + scope sc("boost::variant=(variant&&) moving speed on same types"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = boost::move(data_from[i]); + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + std::cout << "#############################################\n"; + + data_from.clear(); + data_from.resize(c_run_count, hello2); + + data_to.clear(); + data_to.resize(c_run_count, var_t(0)); + { + scope sc("boost::variant=(const variant&) copying speed on different types"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = data_from[i]; + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + data_from.resize(c_run_count, hello2); + data_to.clear(); + data_to.resize(c_run_count, var_t(0)); + { + scope sc("boost::variant=(variant&&) moving speed on different types"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = boost::move(data_from[i]); + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + std::cout << "#############################################\n"; + + data_from.clear(); + data_from.resize(c_run_count, var_t(0)); + + data_to.clear(); + data_to.resize(c_run_count, hello2); + { + scope sc("boost::variant=(const variant&) copying speed on different types II"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = data_from[i]; + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + data_from.resize(c_run_count, var_t(0)); + data_to.clear(); + data_to.resize(c_run_count, hello2); + { + scope sc("boost::variant=(variant&&) moving speed on different types II"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = boost::move(data_from[i]); + } + + if (do_count_cleanup_time) { + data_to.clear(); + data_from.clear(); + } + } + + + std::cout << "#############################################\n"; + + std::vector<str_t> s1(c_run_count, hello2); + data_to.clear(); + data_to.resize(c_run_count, var_t(0)); + + { + scope sc("boost::variant=(const T&) copying speed"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = s1[i]; + } + + if (do_count_cleanup_time) { + data_to.clear(); + s1.clear(); + } + } + + std::vector<str_t> s2(c_run_count, hello2); + data_to.clear(); + data_to.resize(c_run_count, var_t(0)); + { + scope sc("boost::variant=(T&&) moving speed"); + for (std::size_t i = 0; i < c_run_count; ++i) { + data_to[i] = boost::move(s2[i]); + } + + if (do_count_cleanup_time) { + data_to.clear(); + s2.clear(); + } + } +} + + +int main () { + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + std::cout << "# Running tests in C++11 mode (with rvalues).\n"; +#else + std::cout << "# Running tests in C++03 mode (without rvalues).\n"; +#endif + + do_test(false); + do_test(true); +} + + diff --git a/src/boost/libs/variant/test/Jamfile.v2 b/src/boost/libs/variant/test/Jamfile.v2 new file mode 100644 index 00000000..a2fe7383 --- /dev/null +++ b/src/boost/libs/variant/test/Jamfile.v2 @@ -0,0 +1,66 @@ +# Boost.Variant Library test Jamfile +# +# Copyright (C) 2003, Eric Friedman, Itay Maman. +# Copyright (C) 2013-2019 Antony Polukhin. +# +# Use, modification and distribution is subject to the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + +import testing ; + +local below-c++14 = 98 03 0x 11 ; + +project + : requirements + <toolset>msvc:<asynch-exceptions>on + ; +test-suite variant + : + [ run test1.cpp class_a.cpp : : : : variant_test1 ] + [ run test2.cpp : : : : variant_test2 ] + [ run test3.cpp : : : : variant_test3 ] + [ run test3.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : variant_test3_no_rtti ] + [ run test4.cpp class_a.cpp : : : : variant_test4 ] + [ run test5.cpp : : : : variant_test5 ] + [ run test6.cpp : : : : variant_test6 ] + [ run test7.cpp : : : : variant_test7 ] + [ run test8.cpp : : : : variant_test8 ] + [ run test9.cpp : : : : variant_test9 ] + [ run recursive_variant_test.cpp ] + [ run variant_reference_test.cpp ] + [ run variant_comparison_test.cpp ] + [ run variant_visit_internal_linkage.cpp : : : "<cxxstd>$(below-c++14)":<build>no ] + [ run variant_visit_test.cpp ] + [ run variant_get_test.cpp ] + [ compile-fail variant_rvalue_get_with_ampersand_test.cpp ] + [ compile-fail no_rvalue_to_nonconst_visitation.cpp ] + [ run variant_polymorphic_get_test.cpp ] + [ run variant_multivisit_test.cpp ] + [ run hash_variant_test.cpp ] + [ run rvalue_test.cpp ] + [ run variant_nonempty_check.cpp ] + [ run recursive_variant_test.cpp : : : <define>BOOST_NO_EXCEPTIONS + <toolset>gcc-4.3:<cxxflags>-fno-exceptions + <toolset>gcc-4.4:<cxxflags>-fno-exceptions + <toolset>gcc-4.5:<cxxflags>-fno-exceptions + <toolset>gcc-4.6:<cxxflags>-fno-exceptions + <toolset>gcc-4.7:<cxxflags>-fno-exceptions + <toolset>gcc-4.8:<cxxflags>-fno-exceptions + <toolset>clang:<cxxflags>-fno-exceptions + : variant_noexcept_test + ] + [ run recursive_variant_test.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : variant_no_rtti_test ] + [ run hash_recursive_variant_test.cpp ] + [ run variant_swap_test.cpp ] + [ run auto_visitors.cpp ] + [ run issue42.cpp ] + #[ run issue53.cpp ] + [ run overload_selection.cpp ] + [ run recursive_wrapper_move_test.cpp ] + [ run variant_over_joint_view_test.cpp ] + [ run const_ref_apply_visitor.cpp ] + ; + + diff --git a/src/boost/libs/variant/test/auto_visitors.cpp b/src/boost/libs/variant/test/auto_visitors.cpp new file mode 100644 index 00000000..13a2e5f5 --- /dev/null +++ b/src/boost/libs/variant/test/auto_visitors.cpp @@ -0,0 +1,380 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/auto_visitors.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2014-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" +#include "boost/variant/multivisitors.hpp" +#include "boost/lexical_cast.hpp" + +#include <boost/noncopyable.hpp> +#include <boost/core/ignore_unused.hpp> + +namespace has_result_type_tests { + template <class T> + struct wrap { + typedef T result_type; + }; + + struct s1 : wrap<int> {}; + struct s2 : wrap<int&> {}; + struct s3 : wrap<const int&> {}; + struct s4 {}; + struct s5 : wrap<int*> {}; + struct s6 : wrap<int**> {}; + struct s7 : wrap<const int*> {}; + struct s8 : wrap<boost::noncopyable> {}; + struct s9 : wrap<boost::noncopyable&> {}; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + struct s10 : wrap<boost::noncopyable&&> {}; +#endif + struct s11 : wrap<const boost::noncopyable&> {}; + struct s12 : wrap<const boost::noncopyable*> {}; + struct s13 : wrap<boost::noncopyable*> {}; + struct s14 { typedef int result_type; }; + struct s15 { typedef int& result_type; }; + struct s16 { typedef const int& result_type; }; +} + + +void test_has_result_type_triat() { + using namespace has_result_type_tests; + using boost::detail::variant::has_result_type; + + BOOST_TEST(has_result_type<s1>::value); + BOOST_TEST(has_result_type<s2>::value); + BOOST_TEST(has_result_type<s3>::value); + BOOST_TEST(!has_result_type<s4>::value); + BOOST_TEST(has_result_type<s5>::value); + BOOST_TEST(has_result_type<s6>::value); + BOOST_TEST(has_result_type<s7>::value); + BOOST_TEST(has_result_type<s8>::value); + BOOST_TEST(has_result_type<s9>::value); +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_TEST(has_result_type<s10>::value); +#endif + BOOST_TEST(has_result_type<s11>::value); + BOOST_TEST(has_result_type<s12>::value); + BOOST_TEST(has_result_type<s13>::value); + BOOST_TEST(has_result_type<s14>::value); + BOOST_TEST(has_result_type<s15>::value); + BOOST_TEST(has_result_type<s16>::value); +} + +struct lex_streamer_explicit: boost::static_visitor<std::string> { + template <class T> + const char* operator()(const T& ) { + return "10"; + } + + template <class T1, class T2> + const char* operator()(const T1& , const T2& ) { + return "100"; + } +}; + + +void run_explicit() +{ + typedef boost::variant<int, std::string, double> variant_type; + variant_type v2("10"), v1("100"); + + lex_streamer_explicit visitor_ref; + + // Must return instance of std::string + BOOST_TEST(boost::apply_visitor(visitor_ref, v2).c_str() == std::string("10")); + BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1).c_str() == std::string("100")); +} + + +// Most part of tests from this file require decltype(auto) + +#ifdef BOOST_NO_CXX14_DECLTYPE_AUTO + +void run() +{ + BOOST_TEST(true); +} + +void run2() +{ + BOOST_TEST(true); +} + + +void run3() +{ + BOOST_TEST(true); +} + +#else + +#include <iostream> + +struct lex_streamer { + template <class T> + std::string operator()(const T& val) const { + return boost::lexical_cast<std::string>(val); + } +}; + +struct lex_streamer_void { + template <class T> + void operator()(const T& val) const { + std::cout << val << std::endl; + } + + + template <class T1, class T2> + void operator()(const T1& val, const T2& val2) const { + std::cout << val << '+' << val2 << std::endl; + } + + + template <class T1, class T2, class T3> + void operator()(const T1& val, const T2& val2, const T3& val3) const { + std::cout << val << '+' << val2 << '+' << val3 << std::endl; + } +}; + + +struct lex_streamer2 { + std::string res; + + template <class T> + const char* operator()(const T& /*val*/) const { + return "fail"; + } + + template <class T1, class T2> + const char* operator()(const T1& /*v1*/, const T2& /*v2*/) const { + return "fail2"; + } + + + template <class T1, class T2, class T3> + const char* operator()(const T1& /*v1*/, const T2& /*v2*/, const T3& /*v3*/) const { + return "fail3"; + } + + template <class T> + std::string& operator()(const T& val) { + res = boost::lexical_cast<std::string>(val); + return res; + } + + + template <class T1, class T2> + std::string& operator()(const T1& v1, const T2& v2) { + res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2); + return res; + } + + + template <class T1, class T2, class T3> + std::string& operator()(const T1& v1, const T2& v2, const T3& v3) { + res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2) + + "+" + boost::lexical_cast<std::string>(v3); + return res; + } +}; + +#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES +# define BOOST_TEST_IF_HAS_VARIADIC(x) BOOST_TEST(x) +#else +# define BOOST_TEST_IF_HAS_VARIADIC(x) /**/ +#endif + +void run() +{ + typedef boost::variant<int, std::string, double> variant_type; + variant_type v1(1), v2("10"), v3(100.0); + lex_streamer lex_streamer_visitor; + + BOOST_TEST(boost::apply_visitor(lex_streamer(), v1) == "1"); + BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v1) == "1"); + BOOST_TEST(boost::apply_visitor(lex_streamer(), v2) == "10"); + BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v2) == "10"); + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v1) == "1"); + BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v2) == "10"); + + // Retun type must be the same in all instances, so this code does not compile + //boost::variant<int, short, unsigned> v_diff_types(1); + //BOOST_TEST(boost::apply_visitor([](auto v) { return v; }, v_diff_types) == 1); + + boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v1); + boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v2); + #endif + + lex_streamer2 visitor_ref; + BOOST_TEST(boost::apply_visitor(visitor_ref, v1) == "1"); + BOOST_TEST(boost::apply_visitor(visitor_ref, v2) == "10"); +#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES + std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1); + BOOST_TEST(ref_to_string == "1"); +#endif + lex_streamer_void lex_streamer_void_visitor; + boost::apply_visitor(lex_streamer_void(), v1); + boost::apply_visitor(lex_streamer_void(), v2); +#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES + boost::apply_visitor(lex_streamer_void_visitor)(v2); +#endif + + boost::ignore_unused(lex_streamer_visitor, visitor_ref, lex_streamer_void_visitor); +} + + +struct lex_combine { + template <class T1, class T2> + std::string operator()(const T1& v1, const T2& v2) const { + return boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2); + } + + + template <class T1, class T2, class T3> + std::string operator()(const T1& v1, const T2& v2, const T3& v3) const { + return boost::lexical_cast<std::string>(v1) + "+" + + boost::lexical_cast<std::string>(v2) + '+' + + boost::lexical_cast<std::string>(v3); + } +}; + +void run2() +{ + typedef boost::variant<int, std::string, double> variant_type; + variant_type v1(1), v2("10"), v3(100.0); + lex_combine lex_combine_visitor; + + BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2) == "1+10"); + BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1) == "10+1"); + BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_combine_visitor)(v2, v1) == "10+1"); + + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_TEST( + boost::apply_visitor( + [](auto v1, auto v2) { + return boost::lexical_cast<std::string>(v1) + "+" + + boost::lexical_cast<std::string>(v2); + } + , v1 + , v2 + ) == "1+10" + ); + BOOST_TEST( + boost::apply_visitor( + [](auto v1, auto v2) { + return boost::lexical_cast<std::string>(v1) + "+" + + boost::lexical_cast<std::string>(v2); + } + , v2 + , v1 + ) == "10+1" + ); + + boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v1, v2); + boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v2, v1); + #endif + + + lex_streamer2 visitor_ref; + BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10"); + BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1) == "10+1"); +#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES + std::string& ref_to_string = boost::apply_visitor(visitor_ref)(v1, v2); + BOOST_TEST(ref_to_string == "1+10"); +#endif + + boost::apply_visitor(lex_streamer_void(), v1, v2); + boost::apply_visitor(lex_streamer_void(), v2, v1); + + boost::ignore_unused(lex_combine_visitor, visitor_ref); +} + +#undef BOOST_TEST_IF_HAS_VARIADIC + +void run3() +{ +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + typedef boost::variant<int, std::string, double> variant_type; + variant_type v1(1), v2("10"), v3(100); + lex_combine lex_combine_visitor; + + BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2, v3) == "1+10+100"); + BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1, v3) == "10+1+100"); + BOOST_TEST(boost::apply_visitor(lex_combine_visitor)(v2, v1, v3) == "10+1+100"); + + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_TEST( + boost::apply_visitor( + [](auto v1, auto v2, auto v3) { + return boost::lexical_cast<std::string>(v1) + "+" + + boost::lexical_cast<std::string>(v2) + "+" + + boost::lexical_cast<std::string>(v3); + } + , v1 + , v2 + , v3 + ) == "1+10+100" + ); + BOOST_TEST( + boost::apply_visitor( + [](auto v1, auto v2, auto v3) { + return boost::lexical_cast<std::string>(v1) + "+" + + boost::lexical_cast<std::string>(v2) + "+" + + boost::lexical_cast<std::string>(v3); + } + , v3 + , v1 + , v3 + ) == "100+1+100" + ); + + boost::apply_visitor( + [](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; }, + v1, v2, v3 + ); + boost::apply_visitor( + [](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; }, + v2, v1, v3 + ); + #endif + + + lex_streamer2 visitor_ref; + BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10"); + BOOST_TEST(boost::apply_visitor(visitor_ref)(v2, v1) == "10+1"); + std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1, v2); + BOOST_TEST(ref_to_string == "1+10"); + + lex_streamer_void lex_streamer_void_visitor; + boost::apply_visitor(lex_streamer_void(), v1, v2, v1); + boost::apply_visitor(lex_streamer_void(), v2, v1, v1); + boost::apply_visitor(lex_streamer_void_visitor)(v2, v1, v1); +#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) +} +#endif + + +int main() +{ + run_explicit(); + run(); + run2(); + run3(); + test_has_result_type_triat(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/class_a.cpp b/src/boost/libs/variant/test/class_a.cpp new file mode 100644 index 00000000..7cb1ff81 --- /dev/null +++ b/src/boost/libs/variant/test/class_a.cpp @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/class_a.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <algorithm> // for std::swap +#include <sstream> +#include <iostream> +#include <assert.h> + +#include "class_a.h" + + +using namespace std; + +class_a::~class_a() +{ + assert(self_p_ == this); +} + +class_a::class_a(int n) +{ + n_ = n; + self_p_ = this; +} + +class_a::class_a(const class_a& other) +{ + n_ = other.n_; + self_p_ = this; +} + + +class_a& class_a::operator=(const class_a& rhs) +{ + class_a temp(rhs); + swap(temp); + + return *this; +} + +void class_a::swap(class_a& other) +{ + std::swap(n_, other.n_); +} + +int class_a::get() const +{ + return n_; +} + + + + +std::ostream& operator<<(std::ostream& strm, const class_a& a) +{ + return strm << "class_a(" << a.get() << ")"; +} diff --git a/src/boost/libs/variant/test/class_a.h b/src/boost/libs/variant/test/class_a.h new file mode 100644 index 00000000..097c2c40 --- /dev/null +++ b/src/boost/libs/variant/test/class_a.h @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/libs/test/class_a.h header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef _CLASSA_H_INC_ +#define _CLASSA_H_INC_ + + +#include <iosfwd> + +struct class_a +{ + ~class_a(); + class_a(int n = 5511); + class_a(const class_a& other); + + class_a& operator=(const class_a& rhs); + void swap(class_a& other); + + int get() const; + +private: + int n_; + class_a* self_p_; + +}; //Class_a + +std::ostream& operator<<(std::ostream& strm, const class_a& a); + + + +#endif //_CLASSA_H_INC_ diff --git a/src/boost/libs/variant/test/const_ref_apply_visitor.cpp b/src/boost/libs/variant/test/const_ref_apply_visitor.cpp new file mode 100644 index 00000000..72afff9e --- /dev/null +++ b/src/boost/libs/variant/test/const_ref_apply_visitor.cpp @@ -0,0 +1,417 @@ +// Copyright (c) 2017 Levon Tarakchyan +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" +#include "boost/variant/apply_visitor.hpp" +#include "boost/variant/multivisitors.hpp" +#include "boost/lexical_cast.hpp" + +#define lcs(val) boost::lexical_cast<std::string>(val) + +struct construction_logger +{ + int val_; + + construction_logger(int val) : val_(val) + { + std::cout << val_ << " constructed\n"; + } + + construction_logger(const construction_logger& cl) : + val_(cl.val_) + { + std::cout << val_ << " copy constructed\n"; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + construction_logger(construction_logger&& cl) : + val_(cl.val_) + { + std::cout << val_ << " move constructed\n"; + } +#endif + + friend std::ostream& operator << (std::ostream& os, const construction_logger& cl) + { + return os << cl.val_; + } + + friend std::istream& operator << (std::istream& is, construction_logger& cl) + { + return is >> cl.val_; + } +}; + +struct lex_streamer_explicit : boost::static_visitor<std::string> +{ + template <class T> + std::string operator()(const T& val) const + { + return lcs(val); + } + + template <class T, class V> + std::string operator()(const T& val, const V& val2) const + { + return lcs(val) + '+' + lcs(val2); + } + + template <class T, class V, class P, class S> + std::string operator()(const T& val, const V& val2, const P& val3, const S& val4) const + { + return lcs(val) + '+' + lcs(val2) + '+' + lcs(val3) + '+' + lcs(val4); + } +}; + +struct lvalue_rvalue_detector : boost::static_visitor<std::string> +{ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class T> + std::string operator()(T&&) const + { + return std::is_lvalue_reference<T>::value ? "lvalue reference" + : "rvalue reference"; + } + + template <class T, class V> + std::string operator()(T&& t, V&& v) const + { + return operator()(std::forward<T>(t)) + ", " + operator()(std::forward<V>(v)); + } + + template <class T, class V, class P> + std::string operator()(T&& t, V&& v, P&& p) const + { + return operator()(std::forward<T>(t), std::forward<V>(v)) + ", " + operator()(std::forward<P>(p)); + } + + template <class T, class V, class P, class S> + std::string operator()(T&& t, V&& v, P&& p, S&& s) const + { + return operator()(std::forward<T>(t), std::forward<V>(v), std::forward<P>(p)) + ", " + operator()(std::forward<S>(s)); + } +#else + template <class T> + std::string operator()(T&) const + { + return "lvalue reference"; + } + + template <class T, class V> + std::string operator()(T&, V&) const + { + return "lvalue reference, lvalue reference"; + } + + template <class T, class V, class P> + std::string operator()(T&, V&, P&) const + { + return "lvalue reference, lvalue reference, lvalue reference"; + } + + template <class T, class V, class P, class S> + std::string operator()(T&, V&, P&, S&) const + { + return "lvalue reference, lvalue reference, lvalue reference, lvalue reference"; + } +#endif +}; + +typedef boost::variant<construction_logger, std::string> variant_type; + +void test_const_ref_parameter(const variant_type& test_var) +{ + std::cout << "Testing const lvalue reference visitable\n"; + + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var) == "lvalue reference"); +} + +void test_const_ref_parameter2(const variant_type& test_var, const variant_type& test_var2) +{ + std::cout << "Testing const lvalue reference visitable\n"; + + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2) == "lvalue reference, lvalue reference"); +} + +void test_const_ref_parameter4(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3, const variant_type& test_var4) +{ + std::cout << "Testing const lvalue reference visitable with multivisitor\n"; + + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), test_var, test_var2, test_var3, test_var4) + == "lvalue reference, lvalue reference, lvalue reference, lvalue reference"); +} + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + +void test_rvalue_parameter(variant_type&& test_var) +{ + std::cout << "Testing rvalue visitable\n"; + + const auto expected_val = lcs(test_var); + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var)) == "rvalue reference"); +} + +void test_rvalue_parameter2(variant_type&& test_var, variant_type&& test_var2) +{ + std::cout << "Testing rvalue visitable\n"; + + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2)) == "rvalue reference, rvalue reference"); +} + +void test_rvalue_parameter4(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3, variant_type&& test_var4) +{ +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing rvalue visitable with multivisitor\n"; + + auto result = boost::apply_visitor(lvalue_rvalue_detector(), std::move(test_var), std::move(test_var2), std::move(test_var3), std::move(test_var4)); + std::cout << "result: " << result << std::endl; + BOOST_TEST(result == "rvalue reference, rvalue reference, rvalue reference, rvalue reference"); +#else + (void)test_var; + (void)test_var2; + (void)test_var3; + (void)test_var4; +#endif +} + +#endif + +#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO + +#define FORWARD(x) std::forward<decltype(x)>(x) + +void test_cpp14_visitor(const variant_type& test_var) +{ + std::cout << "Testing const lvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, test_var) == "lvalue reference"); +} + +void test_cpp14_mutable_visitor(const variant_type& test_var) +{ + std::cout << "Testing const lvalue visitable for c++14 with inline mutable lambda\n"; + + BOOST_TEST(boost::apply_visitor([](auto&& v) mutable -> auto { return lvalue_rvalue_detector()(FORWARD(v)); }, test_var) == "lvalue reference"); +} + +void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2) +{ + std::cout << "Testing const lvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, test_var, test_var2) + == "lvalue reference, lvalue reference"); +} + +void test_cpp14_visitor(const variant_type& test_var, const variant_type& test_var2, const variant_type& test_var3) +{ +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing const lvalue visitable for c++14\n"; + + auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); }, + test_var, test_var2, test_var3); + std::cout << "result: " << result << std::endl; + BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference"); +#else + (void)test_var; + (void)test_var2; + (void)test_var3; +#endif +} + +void test_cpp14_visitor(variant_type& test_var) +{ + std::cout << "Testing lvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto& v) { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference"); +} + +void test_cpp14_mutable_visitor(variant_type& test_var) +{ + std::cout << "Testing lvalue visitable for c++14 with inline mutable lambda\n"; + + BOOST_TEST(boost::apply_visitor([](auto& v) mutable -> auto { return lvalue_rvalue_detector()(v); }, test_var) == "lvalue reference"); +} + +void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2) +{ + std::cout << "Testing lvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto& v, auto& vv) { return lvalue_rvalue_detector()(v, vv); }, test_var, test_var2) + == "lvalue reference, lvalue reference"); +} + +void test_cpp14_visitor(variant_type& test_var, variant_type& test_var2, variant_type& test_var3) +{ +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing lvalue visitable for c++14\n"; + + auto result = boost::apply_visitor([](auto& v, auto& t, auto& p) { return lvalue_rvalue_detector()(v, t, p); }, + test_var, test_var2, test_var3); + std::cout << "result: " << result << std::endl; + BOOST_TEST(result == "lvalue reference, lvalue reference, lvalue reference"); +#else + (void)test_var; + (void)test_var2; + (void)test_var3; +#endif +} + +void test_cpp14_visitor(variant_type&& test_var) +{ + std::cout << "Testing rvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto&& v) { return lvalue_rvalue_detector()(FORWARD(v)); }, std::move(test_var)) == "rvalue reference"); +} + +void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2) +{ + std::cout << "Testing rvalue visitable for c++14\n"; + + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& vv) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(vv)); }, std::move(test_var), std::move(test_var2)) + == "rvalue reference, rvalue reference"); +} + +void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2, variant_type&& test_var3) +{ +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing rvalue visitable for c++14\n"; + + auto result = boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); }, + std::move(test_var), std::move(test_var2), std::move(test_var3)); + std::cout << "result: " << result << std::endl; + BOOST_TEST(result == "rvalue reference, rvalue reference, rvalue reference"); +#else + (void)test_var; + (void)test_var2; + (void)test_var3; +#endif +} + +#endif + +void run_const_lvalue_ref_tests() +{ + const variant_type v1(1), v2(2), v3(3), v4(4); + test_const_ref_parameter(v1); + test_const_ref_parameter2(v1, v2); + test_const_ref_parameter4(v1, v2, v3, v4); +} + +void run_rvalue_ref_tests() +{ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + variant_type v1(10), v2(20), v3(30); + test_rvalue_parameter(boost::move(v1)); + test_rvalue_parameter2(boost::move(v2), boost::move(v3)); + + variant_type vv1(100), vv2(200), vv3(300), vv4(400); + test_rvalue_parameter4(boost::move(vv1), boost::move(vv2), boost::move(vv3), boost::move(vv4)); +#endif +} + +void run_mixed_tests() +{ + variant_type v1(1), v2(2); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + std::cout << "Testing lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10)) == "lvalue reference, rvalue reference"); + + std::cout << "Testing rvalue + lvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1) == "rvalue reference, lvalue reference"); + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing rvalue + lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), variant_type(10), v1, variant_type(20)) == "rvalue reference, lvalue reference, rvalue reference"); + + std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, variant_type(10), v2, variant_type(20)) == "lvalue reference, rvalue reference, lvalue reference, rvalue reference"); +#endif + +#endif // #ifndef BOOST_NO_CXX11_REF_QUALIFIERS + +#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + std::cout << "Testing lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, v1) == "lvalue reference, lvalue reference"); + + std::cout << "Testing rvalue + lvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1) == "lvalue reference, lvalue reference"); + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing rvalue + lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), static_cast<const variant_type&>(variant_type(10)), v1, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference"); + + std::cout << "Testing lvalue + rvalue + lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor(lvalue_rvalue_detector(), v1, static_cast<const variant_type&>(variant_type(10)), v2, static_cast<const variant_type&>(variant_type(20))) == "lvalue reference, lvalue reference, lvalue reference, lvalue reference"); +#endif +#endif +} + +void run_cpp14_mixed_tests() +{ +#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO + variant_type v1(1), v2(2); + + std::cout << "Testing lvalue + rvalue visitable\n"; + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); }, + v1, variant_type(10)) == "lvalue reference, rvalue reference"); + + std::cout << "Testing rvalue + lvalue visitable\n"; + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t)); }, + variant_type(10), v1) == "rvalue reference, lvalue reference"); + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + std::cout << "Testing rvalue + lvalue + lvalue visitable\n"; + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); }, + variant_type(10), v1, v2) == "rvalue reference, lvalue reference, lvalue reference"); + + std::cout << "Testing lvalue + rvalue + lvalue visitable\n"; + BOOST_TEST(boost::apply_visitor([](auto&& v, auto&& t, auto&& p) { return lvalue_rvalue_detector()(FORWARD(v), FORWARD(t), FORWARD(p)); }, + v1, variant_type(10), v2) == "lvalue reference, rvalue reference, lvalue reference"); +#endif +#endif +} + +void run_cpp14_tests() +{ +#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO + variant_type const c1(10), c2(20), c3(30); + variant_type v1(10), v2(20), v3(30); + + test_cpp14_visitor(c1); + test_cpp14_mutable_visitor(c1); + test_cpp14_visitor(c2, c3); + test_cpp14_visitor(c1, c2, c3); + + test_cpp14_visitor(v1); + test_cpp14_mutable_visitor(v1); + test_cpp14_visitor(v2, v3); + test_cpp14_visitor(v1, v2, v3); + + test_cpp14_visitor(boost::move(v1)); + test_cpp14_visitor(boost::move(v2), boost::move(v3)); + + variant_type vv1(100), vv2(200), vv3(300); + test_cpp14_visitor(boost::move(vv1), boost::move(vv2), boost::move(vv3)); +#endif +} + + + +int main() +{ + run_const_lvalue_ref_tests(); + run_rvalue_ref_tests(); + run_mixed_tests(); + run_cpp14_mixed_tests(); + run_cpp14_tests(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/hash_recursive_variant_test.cpp b/src/boost/libs/variant/test/hash_recursive_variant_test.cpp new file mode 100644 index 00000000..c6d5ef30 --- /dev/null +++ b/src/boost/libs/variant/test/hash_recursive_variant_test.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2016 +// Mikhail Maximov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" +#include "boost/core/lightweight_test.hpp" + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) +// Test is based on reported issues: +// https://svn.boost.org/trac/boost/ticket/12508 +// https://svn.boost.org/trac/boost/ticket/12645 +// Following hash function was not found at compile time, +// because boost::variant construction from boost::recursive_variant_ +// was forbidden. + +#include <unordered_set> + +#include "boost/variant.hpp" + +struct hash; + +using int_t = int; + +template <typename T> +using basic_set_t = std::unordered_set<T, hash>; + +using value_t = boost::make_recursive_variant< + int_t, + basic_set_t<boost::recursive_variant_> +>::type; + +using set_t = basic_set_t<value_t>; + +struct hash +{ + size_t operator()(const value_t&) const + { + return 0; + } +}; + +void run() +{ + set_t s; + int_t i = 3; + value_t v = i; + auto emplace_result = s.emplace(v); // raises error above + BOOST_TEST(emplace_result.second); + v = s; + const set_t& check_set = boost::get<set_t>(v); + BOOST_TEST(!check_set.empty()); + for (const auto& check_v : check_set) { + BOOST_TEST(s.find(check_v) != s.end()); + } + for (const auto& check_v : s) { + BOOST_TEST(check_set.find(check_v) != check_set.end()); + } +} + +#else // !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) +// if no unordered_set and template aliases - does nothing +void run() {} +#endif + +int main() +{ + run(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/hash_variant_test.cpp b/src/boost/libs/variant/test/hash_variant_test.cpp new file mode 100644 index 00000000..3d4a03d9 --- /dev/null +++ b/src/boost/libs/variant/test/hash_variant_test.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2011-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" + +#include "boost/config.hpp" +#include "boost/variant.hpp" +#include "boost/functional/hash/hash.hpp" + +#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) + +#include <unordered_set> + +void test_std_hash() { + std::unordered_set<boost::variant<int, bool> > us; + us.insert(1); + us.insert(true); + BOOST_TEST(us.size() == 2); +} + +#else +void test_std_hash() {} +#endif + + +void run() { + typedef boost::variant<bool, int, unsigned int, char> variant_type; + boost::hash<variant_type> hasher; + + variant_type bool_variant1 = true; + variant_type bool_variant2 = false; + variant_type int_variant = 1; + variant_type char_variant1 = '\1'; + variant_type char_variant2 = '\2'; + variant_type uint_variant = static_cast<unsigned int>(1); + + BOOST_TEST(hasher(bool_variant1) != hasher(bool_variant2)); + BOOST_TEST(hasher(bool_variant1) == hasher(bool_variant1)); + BOOST_TEST(hasher(int_variant) != hasher(uint_variant)); + BOOST_TEST(hasher(char_variant1) != hasher(uint_variant)); + BOOST_TEST(hasher(char_variant1) != hasher(char_variant2)); + BOOST_TEST(hasher(char_variant1) == hasher(char_variant1)); + BOOST_TEST(hasher(char_variant2) == hasher(char_variant2)); +} + +int main() { + run(); + test_std_hash(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/issue42.cpp b/src/boost/libs/variant/test/issue42.cpp new file mode 100644 index 00000000..5a1feaa6 --- /dev/null +++ b/src/boost/libs/variant/test/issue42.cpp @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/issue42.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2018-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Test case from https://github.com/boostorg/variant/issues/42 + +#include <boost/variant.hpp> +#include <map> +#include <memory> +#include <vector> + + + +#ifdef BOOST_NO_CXX11_SMART_PTR + template <class T> struct shared_ptr_like {}; + typedef shared_ptr_like<boost::recursive_variant_> ptr_t; +#else + typedef std::shared_ptr<boost::recursive_variant_> ptr_t; +#endif + +template <class F> +class func{}; + +int main() { + typedef boost::make_recursive_variant< + int, + ptr_t + >::type node; + + node x = 1; + (void)x; + + + typedef boost::make_recursive_variant< + std::string, int, double, bool, + ptr_t, + std::map<const std::string, boost::recursive_variant_>, + std::vector<boost::recursive_variant_> + >::type node2; + + node2 x2 = 1; + (void)x2; + + + typedef boost::make_recursive_variant< + int, + func<boost::recursive_variant_(*)(boost::recursive_variant_&, const boost::recursive_variant_&)>, + boost::recursive_variant_&(*)(boost::recursive_variant_, boost::recursive_variant_*), + ptr_t + >::type node3; + + node3 x3 = func<node3(*)(node3&, const node3&)>(); + (void)x3; +} diff --git a/src/boost/libs/variant/test/issue53.cpp b/src/boost/libs/variant/test/issue53.cpp new file mode 100644 index 00000000..06124b82 --- /dev/null +++ b/src/boost/libs/variant/test/issue53.cpp @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/issue53.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Test case from https://github.com/boostorg/variant/issues/53 + +#include <boost/variant.hpp> +#include <boost/thread/lock_guard.hpp> // this line was causing problems on MSVC + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +struct spanac {}; + +struct ceapa{ + double a,b; +}; + +typedef boost::variant<spanac, ceapa> var_t; + +struct visitor_t : public boost::static_visitor<bool> { + bool operator() (const spanac&) const { + return true; + } + + bool operator() (const ceapa&) const { + return false; + } + +private: + double a, b; +}; + +var_t get(int k) { + if (k) + return spanac(); + else + return ceapa(); +} + +int main(int argc, const char** argv) { + visitor_t v; + + bool result = boost::apply_visitor(v, get(argc - 1)); + (void)result; +} + +#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +int main() {} + +#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES diff --git a/src/boost/libs/variant/test/jobs.h b/src/boost/libs/variant/test/jobs.h new file mode 100644 index 00000000..9b965554 --- /dev/null +++ b/src/boost/libs/variant/test/jobs.h @@ -0,0 +1,335 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/libs/test/jobs.h header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef _JOBSH_INC_ +#define _JOBSH_INC_ + +#include <algorithm> +#include <iostream> +#include <sstream> +#include <string> +#include <typeinfo> +#include <vector> + +#include "boost/variant/variant_fwd.hpp" +#include "boost/variant/get.hpp" +#include "boost/variant/apply_visitor.hpp" +#include "boost/variant/static_visitor.hpp" + +#include "boost/type_index.hpp" +#include "boost/detail/workaround.hpp" +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) +# pragma warn -lvc +#endif + +struct to_text : boost::static_visitor<std::string> +{ +private: // NO_FUNCTION_TEMPLATE_ORDERING workaround + + template < BOOST_VARIANT_ENUM_PARAMS(typename U) > + std::string to_text_impl( + const boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) >& operand, long + ) const + { + std::ostringstream ost; + ost << "[V] " << boost::apply_visitor(to_text(), operand); + + return ost.str(); + } + + template <typename Value> + std::string to_text_impl(const Value& operand, int) const + { + std::ostringstream ost; + ost << "[V] " << operand; + + return ost.str(); + } + +public: + + template <typename T> + std::string operator()(const T& operand) const + { + return to_text_impl(operand, 1L); + } + +}; + +struct total_sizeof : boost::static_visitor<int> +{ + total_sizeof() : total_(0) { } + + template<class Value> + int operator()(const Value&) const + { + total_ += sizeof(Value); + return total_; + } + + int result() const + { + return total_; + } + + mutable int total_; + +}; // total_sizeof + + + +//Function object: sum_int +//Description: Compute total sum of a series of numbers, (when called successively) +//Use sizeof(T) if applied with a non-integral type +struct sum_int : boost::static_visitor<int> +{ + + sum_int() : total_(0) { } + + + template<int n> + struct int_to_type + { + BOOST_STATIC_CONSTANT(int, value = n); + }; + + //Integral type - add numerical value + template<typename T> + void add(T t, int_to_type<true> ) const + { + total_ += t; + } + + //Other types - add sizeof<T> + template<typename T> + void add(T& , int_to_type<false> ) const + { + total_ += sizeof(T); + } + + template<typename T> + int operator()(const T& t) const + { + //Int_to_type is used to select the correct add() overload + add(t, int_to_type<boost::is_integral<T>::value>()); + return total_; + } + + int result() const + { + return total_; + } + +private: + mutable int total_; + +}; //sum_int + + + + + + +//Function object: sum_double +//Description: Compute total sum of a series of numbers, (when called successively) +//Accpetable input types: float, double (Other types are silently ignored) +struct sum_double : boost::static_visitor<double> +{ + + sum_double() : total_(0) { } + + void operator()(float value) const + { + total_ += value; + } + + void operator()(double value) const + { + total_ += value; + } + + template<typename T> + void operator()(const T&) const + { + //Do nothing + } + + double result() const + { + return total_; + } + +private: + mutable double total_; + +}; //sum_double + + + +struct int_printer : boost::static_visitor<std::string> +{ + + int_printer(std::string prefix_s = "") : prefix_s_(prefix_s) { } + int_printer(const int_printer& other) : prefix_s_(other.prefix_s_) + { + ost_ << other.str(); + } + + std::string operator()(int x) const + { + ost_ << prefix_s_ << x; + return str(); + } + + std::string operator()(const std::vector<int>& x) const + { + ost_ << prefix_s_; + + //Use another Int_printer object for printing a list of all integers + int_printer job(","); + ost_ << std::for_each(x.begin(), x.end(), job).str(); + + return str(); + } + + std::string str() const + { + return ost_.str(); + } + +private: + std::string prefix_s_; + mutable std::ostringstream ost_; +}; //int_printer + + +struct int_adder : boost::static_visitor<> +{ + + int_adder(int rhs) : rhs_(rhs) { } + + result_type operator()(int& lhs) const + { + lhs += rhs_; + } + + template<typename T> + result_type operator()(const T& ) const + { + //Do nothing + } + + int rhs_; +}; //int_adder + + + +template<typename T> +struct spec +{ + typedef T result; +}; + +template<typename VariantType, typename S> +inline void verify(VariantType& var, spec<S>, std::string str = "") +{ + const VariantType& cvar = var; + + BOOST_TEST(boost::apply_visitor(total_sizeof(), cvar) == sizeof(S)); + BOOST_TEST(cvar.type() == boost::typeindex::type_id<S>()); + + // + // Check get<>() + // + BOOST_TEST(boost::get<S>(&var)); + BOOST_TEST(boost::get<S>(&cvar)); + + const S* ptr1 = 0; + const S* ptr2 = 0; + try + { + S& r = boost::get<S>(var); + ptr1 = &r; + } + catch(const boost::bad_get& ) + { + BOOST_ERROR( "get<S> failed unexpectedly" ); + } + + try + { + const S& cr = boost::get<S>(cvar); + ptr2 = &cr; + } + catch(const boost::bad_get& ) + { + BOOST_ERROR( "get<S> const failed unexpectedly" ); + } + + BOOST_TEST(ptr1 != 0 && ptr2 == ptr1); + + // + // Check string content + // + if(str.length() > 0) + { + std::string temp = boost::apply_visitor(to_text(), cvar); + std::cout << "temp = " << temp << ", str = " << str << std::endl; + BOOST_TEST(temp == str); + } +} + + +template<typename VariantType, typename S> +inline void verify_not(VariantType& var, spec<S>) +{ + const VariantType& cvar = var; + + BOOST_TEST(cvar.type() != boost::typeindex::type_id<S>()); + + // + // Check get<>() + // + BOOST_TEST(!boost::get<S>(&var)); + BOOST_TEST(!boost::get<S>(&cvar)); + + const S* ptr1 = 0; + const S* ptr2 = 0; + try + { + S& r = boost::get<S>(var); // should throw + BOOST_ERROR( "get<S> passed unexpectedly" ); + + ptr1 = &r; + } + catch(const boost::bad_get& ) + { + // do nothing except pass-through + } + + try + { + const S& cr = boost::get<S>(var); // should throw + BOOST_ERROR( "get<S> const passed unexpectedly" ); + + ptr2 = &cr; + } + catch(const boost::bad_get& ) + { + // do nothing except pass-through + } + + BOOST_TEST(ptr1 == 0 && ptr2 == 0); +} + + +#endif //_JOBSH_INC_ diff --git a/src/boost/libs/variant/test/no_rvalue_to_nonconst_visitation.cpp b/src/boost/libs/variant/test/no_rvalue_to_nonconst_visitation.cpp new file mode 100644 index 00000000..e13b7f2c --- /dev/null +++ b/src/boost/libs/variant/test/no_rvalue_to_nonconst_visitation.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2017-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" +#include "boost/variant.hpp" + +struct foo {}; + +struct some_user_provided_visitor_for_lvalues: boost::static_visitor<void> { + void operator()(foo& ) const {} + void operator()(int ) const {} +}; + +int main() { + boost::apply_visitor( + some_user_provided_visitor_for_lvalues(), + boost::variant<int, foo>(foo()) + ); + +#ifdef __GNUC__ +# if __GNUC__ < 5 && __GNUC_MINOR__ < 8 +# error This test does not pass on GCC < 4.8 because of the incomplete C++11 support +# endif +#endif + +#ifdef BOOST_MSVC +# error Temporaries/rvalues could bind to non-const lvalues on MSVC compilers +#endif +} diff --git a/src/boost/libs/variant/test/overload_selection.cpp b/src/boost/libs/variant/test/overload_selection.cpp new file mode 100644 index 00000000..e18dd7ed --- /dev/null +++ b/src/boost/libs/variant/test/overload_selection.cpp @@ -0,0 +1,215 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_get_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2016-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// This test suite was created to cover issues reported in: +// https://svn.boost.org/trac/boost/ticket/5871 +// https://svn.boost.org/trac/boost/ticket/11602 + +#include "boost/variant/variant.hpp" +#include "boost/variant/recursive_variant.hpp" +#include "boost/core/lightweight_test.hpp" + +#include <string> +#include <list> + +struct A{}; +struct B{}; +struct C{}; +struct D{}; + + +bool foo(const boost::variant<A, B>& ) { + return false; +} + +bool foo(const boost::variant<C, D>& ) { + return true; +} + +void test_overload_selection_variant_constructor() { + D d; + BOOST_TEST(foo(d)); + + boost::variant<B, A> v; + BOOST_TEST(!foo(v)); +} + +// Pre msvc-14.0 could not dustinguish between multiple assignment operators: +// warning C4522: 'assignment_tester' : multiple assignment operators specified +// error C2666: variant::operator =' : 3 overloads have similar conversions +// Old versions of GCC have same issue: +// error: variant::operator=(const T&) cannot be overloaded +#if (defined(__GNUC__) && (__GNUC__ < 4)) || (defined(_MSC_VER) && _MSC_VER < 1900) + +void test_overload_selection_variant_assignment() { + BOOST_TEST(true); +} + +#else + +struct assignment_tester: boost::variant<C, D>, boost::variant<B, A> { + using boost::variant<B, A>::operator=; + using boost::variant<C, D>::operator=; +}; + +void test_overload_selection_variant_assignment() { + A a; + assignment_tester tester; + tester = a; + const int which0 = static_cast< boost::variant<B, A>& >(tester).which(); + BOOST_TEST(which0 == 1); + + boost::variant<A, B> b; + b = B(); + tester = b; + const int which1 = static_cast< boost::variant<B, A>& >(tester).which(); + BOOST_TEST(which1 == 0); +} + +#endif + +typedef boost::variant<int> my_variant; + +struct convertible { + operator my_variant() const { + return my_variant(); + } +}; + +void test_implicit_conversion_operator() { + // https://svn.boost.org/trac/boost/ticket/8555 + my_variant y = convertible(); + BOOST_TEST(y.which() == 0); +} + +struct X: boost::variant< int > {}; +class V1: public boost::variant<float,double> {}; + +struct AB: boost::variant<A, B> {}; + +void test_derived_from_variant_construction() { + // https://svn.boost.org/trac/boost/ticket/7120 + X x; + boost::variant<X> y(x); + BOOST_TEST(y.which() == 0); + + // https://svn.boost.org/trac/boost/ticket/10278 + boost::variant<V1, std::string> v2 = V1(); + BOOST_TEST(v2.which() == 0); + + // https://svn.boost.org/trac/boost/ticket/12155 + AB ab; + boost::variant<AB, C> ab_c(ab); + BOOST_TEST(ab_c.which() == 0); + + boost::variant<A, B> a_b(ab); + BOOST_TEST(a_b.which() == 0); + + boost::variant<B, C, A> b_c_a1(static_cast<boost::variant<A, B>& >(ab)); + BOOST_TEST(b_c_a1.which() == 2); + + +// Following conversion seems harmful as it may lead to slicing: +// boost::variant<B, C, A> b_c_a(ab); +// BOOST_TEST(b_c_a.which() == 2); +} + +void test_derived_from_variant_assignment() { + // https://svn.boost.org/trac/boost/ticket/7120 + X x; + boost::variant<X> y; + y = x; + BOOST_TEST(y.which() == 0); + + // https://svn.boost.org/trac/boost/ticket/10278 + boost::variant<V1, std::string> v2; + v2 = V1(); + BOOST_TEST(v2.which() == 0); + + // https://svn.boost.org/trac/boost/ticket/12155 + AB ab; + boost::variant<AB, C> ab_c; + ab_c = ab; + BOOST_TEST(ab_c.which() == 0); + + boost::variant<A, B> a_b; + a_b = ab; + BOOST_TEST(a_b.which() == 0); + + boost::variant<B, C, A> b_c_a1; + b_c_a1 = static_cast<boost::variant<A, B>& >(ab); + BOOST_TEST(b_c_a1.which() == 2); + + +// Following conversion seems harmful as it may lead to slicing: +// boost::variant<B, C, A> b_c_a; +// b_c_a = ab; +// BOOST_TEST(b_c_a.which() == 2); +} + + +// http://thread.gmane.org/gmane.comp.lib.boost.devel/267757 +struct info { + struct nil_ {}; + + typedef + boost::variant< + nil_ + , std::string + , boost::recursive_wrapper<info> + , boost::recursive_wrapper<std::pair<info, info> > + , boost::recursive_wrapper<std::list<info> > + > + value_type; + value_type v; + + inline void test_on_incomplete_types() { + info i0; + i0.v = "Hello"; + BOOST_TEST(i0.v.which() == 1); + + info::value_type v0 = "Hello"; + BOOST_TEST(v0.which() == 1); + + info::value_type v1("Hello"); + BOOST_TEST(v1.which() == 1); + + info::value_type v2 = i0; + BOOST_TEST(v2.which() == 2); + + info::value_type v3(i0); + BOOST_TEST(v3.which() == 2); + + v0 = v3; + BOOST_TEST(v0.which() == 2); + + v3 = v1; + BOOST_TEST(v3.which() == 1); + + v3 = nil_(); + BOOST_TEST(v3.which() == 0); + } +}; + + + +int main() +{ + test_overload_selection_variant_constructor(); + test_overload_selection_variant_assignment(); + test_implicit_conversion_operator(); + test_derived_from_variant_construction(); + test_derived_from_variant_assignment(); + info().test_on_incomplete_types(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/recursive_variant_test.cpp b/src/boost/libs/variant/test/recursive_variant_test.cpp new file mode 100644 index 00000000..5df5dd1c --- /dev/null +++ b/src/boost/libs/variant/test/recursive_variant_test.cpp @@ -0,0 +1,364 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/recursive_variant_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 Eric Friedman, Itay Maman +// Copyright (c) 2013-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// This file is used in two test cases: +// +// 1) recursive_variant_test.cpp that tests recursive usage of variant +// +// 2) variant_noexcept_test that tests Boost.Variant ability to compile +// and work with disabled exceptions + + +#include "boost/core/lightweight_test.hpp" + +#include "boost/variant.hpp" +#include "boost/mpl/vector.hpp" +#include "boost/mpl/copy.hpp" + +#include <iostream> +#include <sstream> +#include <vector> +#include <map> +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) +#include <tuple> +#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + +struct printer + : boost::static_visitor<std::string> +{ + template <BOOST_VARIANT_ENUM_PARAMS(typename T)> + std::string operator()( + const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &var) const + { + return boost::apply_visitor( printer(), var ); + } + + template <typename T> + std::string operator()(const std::vector<T>& vec) const + { + std::ostringstream ost; + + ost << "( "; + + typename std::vector<T>::const_iterator it = vec.begin(); + for (; it != vec.end(); ++it) + ost << printer()( *it ); + + ost << ") "; + + return ost.str(); + } + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + template <int...> struct indices {}; + template <typename... Ts, int... Is> + std::string operator()(const std::tuple<Ts...>& tup, indices<Is...>) const + { + std::ostringstream ost; + ost << "( "; + int a[] = {0, (ost << printer()( std::get<Is>(tup) ), 0)... }; + (void)a; + ost << ") "; + return ost.str(); + } + + template <int N, int... Is> + struct make_indices : make_indices<N-1, N-1, Is...> {}; + template <int... Is> + struct make_indices<0, Is...> : indices<Is...> {}; + template <typename... Ts> + std::string operator()(const std::tuple<Ts...>& tup) const + { + return printer()(tup, make_indices<sizeof...(Ts)>()); + } +#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + + template <typename T> + std::string operator()(const T& operand) const + { + std::ostringstream ost; + ost << operand << ' '; + return ost.str(); + } +}; + +void test_recursive_variant() +{ + typedef boost::make_recursive_variant< + int + , std::vector<boost::recursive_variant_> + >::type var1_t; + + std::vector<var1_t> vec1; + vec1.push_back(3); + vec1.push_back(5); + vec1.push_back(vec1); + vec1.push_back(7); + + var1_t var1(vec1); + std::string result1( printer()(var1) ); + + std::cout << "result1: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) "); + + std::vector<var1_t> vec1_copy = vec1; + vec1_copy.erase(vec1_copy.begin() + 2); + vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy); + var1 = vec1_copy; + result1 = printer()(var1); + std::cout << "result1+: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) "); + + // Uses move construction on compilers with rvalue references support + result1 = printer()( + var1_t( + std::vector<var1_t>(vec1_copy) + ) + ); + std::cout << "result1++: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) "); + + + var1_t vec1_another_copy(vec1_copy); + vec1_copy[2].swap(vec1_another_copy); + result1 = printer()( + var1_t(vec1_copy) + ); + std::cout << "result1+++1: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) "); + + result1 = printer()(vec1_another_copy); + std::cout << "result1++2: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 7 ) "); + + vec1_copy[2].swap(vec1_copy[2]); + result1 = printer()( + var1_t(vec1_copy) + ); + std::cout << "result1.2: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) "); + + typedef boost::make_recursive_variant< + boost::variant<int, double> + , std::vector<boost::recursive_variant_> + >::type var2_t; + + std::vector<var2_t> vec2; + vec2.push_back(boost::variant<int, double>(3)); + vec2.push_back(boost::variant<int, double>(3.5)); + vec2.push_back(vec2); + vec2.push_back(boost::variant<int, double>(7)); + + var2_t var2(vec2); + std::string result2( printer()(var2) ); + + std::cout << "result2: " << result2 << '\n'; + BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) "); + + typedef boost::make_recursive_variant< + int + , std::vector< + boost::variant< + double + , std::vector<boost::recursive_variant_> + > + > + >::type var3_t; + + typedef boost::variant<double, std::vector<var3_t> > var4_t; + + std::vector<var3_t> vec3; + vec3.push_back(3); + vec3.push_back(5); + std::vector<var4_t> vec4; + vec4.push_back(3.5); + vec4.push_back(vec3); + vec3.push_back(vec4); + vec3.push_back(7); + + var4_t var4(vec3); + std::string result3( printer()(var4) ); + + std::cout << "result2: " << result3 << '\n'; + BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) "); + + typedef boost::make_recursive_variant< + double, + std::vector<var1_t> + >::type var5_t; + + std::vector<var5_t> vec5; + vec5.push_back(3.5); + vec5.push_back(vec1); + vec5.push_back(17.25); + + std::string result5( printer()(vec5) ); + + std::cout << "result5: " << result5 << '\n'; + BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) "); + + typedef boost::make_recursive_variant< + int, + std::map<int, boost::recursive_variant_> + >::type var6_t; + var6_t var6; + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) + typedef boost::make_recursive_variant< + int, + std::tuple<int, boost::recursive_variant_> + >::type var7_t; + var7_t var7 = 0; // !!! Do not replace with `var7_t var7{0}` or `var7_t var7(0)` !!! + var7 = std::tuple<int, var7_t>(1, var7); + var7 = std::tuple<int, var7_t>(2, var7); + + std::string result7( printer()(var7) ); + + std::cout << "result7: " << result7 << '\n'; + BOOST_TEST(result7 == "( 2 ( 1 0 ) ) "); +#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) +} + +void test_recursive_variant_over() +{ + typedef boost::make_recursive_variant_over< + boost::mpl::vector< + int + , std::vector<boost::recursive_variant_> + > + >::type var1_t; + + std::vector<var1_t> vec1; + vec1.push_back(3); + vec1.push_back(5); + vec1.push_back(vec1); + vec1.push_back(7); + + var1_t var1(vec1); + std::string result1( printer()(var1) ); + + std::cout << "result1: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 ) 7 ) "); + + std::vector<var1_t> vec1_copy = vec1; + vec1_copy.erase(vec1_copy.begin() + 2); + vec1_copy.insert(vec1_copy.begin() + 2, vec1_copy); + var1 = vec1_copy; + result1 = printer()(var1); + std::cout << "result1+: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) "); + + // Uses move construction on compilers with rvalue references support + result1 = printer()( + var1_t( + std::vector<var1_t>(vec1_copy) + ) + ); + std::cout << "result1++: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 7 ) 7 ) "); + + + var1_t vec1_another_copy(vec1_copy); + vec1_copy[2].swap(vec1_another_copy); + result1 = printer()( + var1_t(vec1_copy) + ); + std::cout << "result1+++1: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 ( 3 5 ( 3 5 7 ) 7 ) 7 ) "); + + result1 = printer()(vec1_another_copy); + std::cout << "result1++2: " << result1 << '\n'; + BOOST_TEST(result1 == "( 3 5 7 ) "); + + typedef boost::make_recursive_variant_over< + boost::mpl::vector< + boost::make_variant_over<boost::mpl::vector<int, double> >::type + , std::vector<boost::recursive_variant_> + > + >::type var2_t; + + std::vector<var2_t> vec2; + vec2.push_back(boost::variant<int, double>(3)); + vec2.push_back(boost::variant<int, double>(3.5)); + vec2.push_back(vec2); + vec2.push_back(boost::variant<int, double>(7)); + + var2_t var2(vec2); + std::string result2( printer()(var2) ); + + std::cout << "result2: " << result2 << '\n'; + BOOST_TEST(result2 == "( 3 3.5 ( 3 3.5 ) 7 ) "); + + typedef boost::make_recursive_variant_over< + boost::mpl::vector< + int + , std::vector< + boost::make_variant_over< + boost::mpl::vector< + double + , std::vector<boost::recursive_variant_> + > + >::type + > + > + >::type var3_t; + + typedef boost::make_variant_over< + boost::mpl::copy< + boost::mpl::vector< + double + , std::vector<var3_t> + > + >::type + >::type var4_t; + + std::vector<var3_t> vec3; + vec3.push_back(3); + vec3.push_back(5); + std::vector<var4_t> vec4; + vec4.push_back(3.5); + vec4.push_back(vec3); + vec3.push_back(vec4); + vec3.push_back(7); + + var4_t var3(vec3); + std::string result3( printer()(var3) ); + + std::cout << "result2: " << result3 << '\n'; + BOOST_TEST(result3 == "( 3 5 ( 3.5 ( 3 5 ) ) 7 ) "); + + typedef boost::make_recursive_variant_over< + boost::mpl::vector< + double + , std::vector<var1_t> + > + >::type var5_t; + + std::vector<var5_t> vec5; + vec5.push_back(3.5); + vec5.push_back(vec1); + vec5.push_back(17.25); + + std::string result5( printer()(vec5) ); + + std::cout << "result5: " << result5 << '\n'; + BOOST_TEST(result5 == "( 3.5 ( 3 5 ( 3 5 ) 7 ) 17.25 ) "); +} + +int main() +{ + test_recursive_variant(); + test_recursive_variant_over(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/recursive_wrapper_move_test.cpp b/src/boost/libs/variant/test/recursive_wrapper_move_test.cpp new file mode 100644 index 00000000..58041ec2 --- /dev/null +++ b/src/boost/libs/variant/test/recursive_wrapper_move_test.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2017 +// Mikhail Maximov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" +#include "boost/core/lightweight_test.hpp" + +#ifdef __cpp_inheriting_constructors +// Test is based on reported issue: +// https://svn.boost.org/trac/boost/ticket/12680 +// GCC 6 crashed, trying to determine is boost::recursive_wrapper<Node> +// is_noexcept_move_constructible + +#include <string> +#include <iterator> + +#include <boost/variant.hpp> +#include <boost/array.hpp> + +struct Leaf { }; +struct Node; + +typedef boost::variant<Leaf, boost::recursive_wrapper<Node>> TreeBase; + +struct Tree : TreeBase { + using TreeBase::TreeBase; + + template <typename Iter> + static Tree Create(Iter /*first*/, Iter /*last*/) { return Leaf{}; } +}; + +struct Node { + Tree left, right; +}; + + +// Test from https://svn.boost.org/trac/boost/ticket/7120 +template<class Node> +struct node1_type; + +struct var_type; + +using var_base = boost::variant<int, + boost::recursive_wrapper<node1_type<var_type>> +>; + +template<class Node> +struct node1_type { + boost::array<Node, 1> children; +}; + +struct var_type : var_base { + using var_base::var_base; +}; + +void run() { + std::string input{"abracadabra"}; + const Tree root = Tree::Create(input.begin(), input.end()); + (void)root; // prevents unused variable warning + + var_type v1 = 1; + (void)v1; +} + +#else // #!ifdef __cpp_inheriting_constructors +// if compiler does not support inheriting constructors - does nothing +void run() {} +#endif + +int main() +{ + run(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/rvalue_test.cpp b/src/boost/libs/variant/test/rvalue_test.cpp new file mode 100644 index 00000000..9fcdee58 --- /dev/null +++ b/src/boost/libs/variant/test/rvalue_test.cpp @@ -0,0 +1,332 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/rvalue_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2012-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" +#include "boost/type_traits/is_nothrow_move_assignable.hpp" +#include "boost/mpl/bool.hpp" + +#include <boost/blank.hpp> +#include <boost/swap.hpp> + +namespace swap_ambiguouty_test_ns { + struct A {}; + struct B {}; + + void swap_ambiguouty_test() { + // If boost::blank is not used, then it compiles. + typedef boost::variant<boost::blank, A, B> Variant; + Variant v1, v2; + swap(v1, v2); + } +} // namespace swap_ambiguouty_test_ns + +// Most part of tests from this file require rvalue references support + +class move_copy_conting_class { +public: + static unsigned int moves_count; + static unsigned int copy_count; + + move_copy_conting_class(){} + move_copy_conting_class(BOOST_RV_REF(move_copy_conting_class) ) { + ++ moves_count; + } + + move_copy_conting_class& operator=(BOOST_RV_REF(move_copy_conting_class) ) { + ++ moves_count; + return *this; + } + + move_copy_conting_class(const move_copy_conting_class&) { + ++ copy_count; + } + move_copy_conting_class& operator=(BOOST_COPY_ASSIGN_REF(move_copy_conting_class) ) { + ++ copy_count; + return *this; + } +}; + +unsigned int move_copy_conting_class::moves_count = 0; +unsigned int move_copy_conting_class::copy_count = 0; + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + +void run() +{ + // Making sure that internals of Boost.Move do not interfere with + // internals of Boost.Variant and in case of C++03 or C++98 compilation + // is still possible. + typedef boost::variant<int, move_copy_conting_class> variant_I_type; + variant_I_type v1, v2; + v1 = move_copy_conting_class(); + v2 = v1; + v2 = boost::move(v1); + v1.swap(v2); + + move_copy_conting_class val; + v2 = boost::move(val); + v2 = 10; + + variant_I_type v3(boost::move(val)); + variant_I_type v4(boost::move(v1)); +} + +void run1() +{ + BOOST_TEST(true); +} + +void run_move_only() +{ + BOOST_TEST(true); +} + +void run_moves_are_noexcept() +{ + BOOST_TEST(true); +} + + +void run_const_rvalues() +{ + BOOST_TEST(true); +} + + +#else + + +void run() +{ + typedef boost::variant<int, move_copy_conting_class> variant_I_type; + variant_I_type v1, v2; + + // Assuring that `move_copy_conting_class` was not created + BOOST_TEST(move_copy_conting_class::copy_count == 0); + BOOST_TEST(move_copy_conting_class::moves_count == 0); + + v1 = move_copy_conting_class(); + // Assuring that `move_copy_conting_class` was moved at least once + BOOST_TEST(move_copy_conting_class::moves_count != 0); + + unsigned int total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count; + move_copy_conting_class var; + v1 = 0; + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v1 = var; + // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator + BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count); + + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v2 = boost::move(v1); + // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied + BOOST_TEST(move_copy_conting_class::moves_count != 0); + BOOST_TEST(move_copy_conting_class::copy_count == 0); + + v1 = move_copy_conting_class(); + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v2 = boost::move(v1); + // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied + BOOST_TEST(move_copy_conting_class::moves_count != 0); + BOOST_TEST(move_copy_conting_class::copy_count == 0); + total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count; + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v1 = v2; + // Assuring that move assignment operator moves/copyes value not more times than copy assignment operator + BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count); + + + typedef boost::variant<move_copy_conting_class, int> variant_II_type; + variant_II_type v3; + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v1 = boost::move(v3); + // Assuring that `move_copy_conting_class` in v3 was moved at least once (v1 and v3 have different types) + BOOST_TEST(move_copy_conting_class::moves_count != 0); + + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + v2 = boost::move(v1); + // Assuring that `move_copy_conting_class` in v1 was moved at least once (v1 and v3 have different types) + BOOST_TEST(move_copy_conting_class::moves_count != 0); + + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + variant_I_type v5(boost::move(v1)); + // Assuring that `move_copy_conting_class` in v1 was moved at least once and was not copied + BOOST_TEST(move_copy_conting_class::moves_count != 0); + BOOST_TEST(move_copy_conting_class::copy_count == 0); + + total_count = move_copy_conting_class::moves_count + move_copy_conting_class::copy_count; + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + variant_I_type v6(v1); + // Assuring that move constructor moves/copyes value not more times than copy constructor + BOOST_TEST(total_count <= move_copy_conting_class::moves_count + move_copy_conting_class::copy_count); +} + +void run1() +{ + move_copy_conting_class::moves_count = 0; + move_copy_conting_class::copy_count = 0; + + move_copy_conting_class c1; + typedef boost::variant<int, move_copy_conting_class> variant_I_type; + variant_I_type v1(boost::move(c1)); + + // Assuring that `move_copy_conting_class` was not copyied + BOOST_TEST(move_copy_conting_class::copy_count == 0); + BOOST_TEST(move_copy_conting_class::moves_count > 0); +} + +struct move_only_structure { + move_only_structure(){} + move_only_structure(move_only_structure&&){} + move_only_structure& operator=(move_only_structure&&) { return *this; } + +private: + move_only_structure(const move_only_structure&); + move_only_structure& operator=(const move_only_structure&); +}; + +struct visitor_returning_move_only_type: boost::static_visitor<move_only_structure> { + template <class T> + move_only_structure operator()(const T&) const { + return move_only_structure(); + } +}; + +void run_move_only() +{ + move_only_structure mo; + boost::variant<int, move_only_structure > vi, vi2(static_cast<move_only_structure&&>(mo)); + BOOST_TEST(vi.which() == 0); + BOOST_TEST(vi2.which() == 1); + + vi = 10; + vi2 = 10; + BOOST_TEST(vi.which() == 0); + BOOST_TEST(vi2.which() == 0); + + vi = static_cast<move_only_structure&&>(mo); + vi2 = static_cast<move_only_structure&&>(mo); + BOOST_TEST(vi.which() == 1); + + boost::variant<move_only_structure, int > rvi (1); + BOOST_TEST(rvi.which() == 1); + rvi = static_cast<move_only_structure&&>(mo); + BOOST_TEST(rvi.which() == 0); + rvi = 1; + BOOST_TEST(rvi.which() == 1); + rvi = static_cast<boost::variant<int, move_only_structure >&&>(vi2); + BOOST_TEST(rvi.which() == 0); + + move_only_structure from_visitor = boost::apply_visitor(visitor_returning_move_only_type(), vi); + (void)from_visitor; +} + +void run_moves_are_noexcept() { +#if !defined(BOOST_NO_CXX11_NOEXCEPT) && (!defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || __GNUC_MINOR__ >= 8) + typedef boost::variant<int, short, double> variant_noexcept_t; + BOOST_TEST(boost::is_nothrow_move_assignable<variant_noexcept_t>::value); + BOOST_TEST(boost::is_nothrow_move_constructible<variant_noexcept_t>::value); + + typedef boost::variant<int, short, double, move_only_structure> variant_except_t; + BOOST_TEST(!boost::is_nothrow_move_assignable<variant_except_t>::value); + BOOST_TEST(!boost::is_nothrow_move_constructible<variant_except_t>::value); +#endif +} + +inline const std::string get_string() { return "test"; } +inline const boost::variant<int, std::string> get_variant() { return std::string("test"); } +inline const boost::variant<std::string, int> get_variant2() { return std::string("test"); } + +void run_const_rvalues() +{ + typedef boost::variant<int, std::string> variant_t; + const variant_t v1(get_string()); + const variant_t v2(get_variant()); + const variant_t v3(get_variant2()); + + variant_t v4, v5, v6, v7; + v4 = get_string(); + v5 = get_variant(); + v6 = get_variant2(); + v7 = boost::move(v1); +} + +#endif + +struct nothrow_copyable_throw_movable { + nothrow_copyable_throw_movable(){} + nothrow_copyable_throw_movable(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT {} + nothrow_copyable_throw_movable& operator=(const nothrow_copyable_throw_movable&) BOOST_NOEXCEPT { return *this; } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nothrow_copyable_throw_movable(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) {} + nothrow_copyable_throw_movable& operator=(nothrow_copyable_throw_movable&&) BOOST_NOEXCEPT_IF(false) { return *this; } +#endif +}; + +// This test is created to cover the following situation: +// https://svn.boost.org/trac/boost/ticket/8772 +void run_tricky_compilation_test() +{ + boost::variant<int, nothrow_copyable_throw_movable> v; + v = nothrow_copyable_throw_movable(); +} + +template <typename T> +struct is_container : boost::mpl::false_ {}; + +template <typename T> +struct is_container<boost::variant<T> > : is_container<T> {}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct is_container<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > + : boost::mpl::bool_<is_container<T0>::value + || is_container<boost::variant<BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)> >::value> +{}; + +void run_is_container_compilation_test() +{ + BOOST_TEST((!is_container<boost::variant<double, int> >::value)); + BOOST_TEST((!is_container<boost::variant<double, int, char> >::value)); + BOOST_TEST((!is_container<boost::variant<double, int, char, float> >::value)); +} + +int main() +{ + swap_ambiguouty_test_ns::swap_ambiguouty_test(); + run(); + run1(); + run_move_only(); + run_moves_are_noexcept(); + run_tricky_compilation_test(); + run_const_rvalues(); + run_is_container_compilation_test(); + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ > 6) +# ifdef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES + BOOST_TEST(false && + "Something wrong with macro definitions. GCC-4.7+ is known to work with variadic templates" + ); +# endif +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/test1.cpp b/src/boost/libs/variant/test/test1.cpp new file mode 100644 index 00000000..b7b9494c --- /dev/null +++ b/src/boost/libs/variant/test/test1.cpp @@ -0,0 +1,150 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test1.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#ifdef BOOST_MSVC +#pragma warning(disable:4244) // conversion from const int to const short +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include "class_a.h" +#include "jobs.h" + +#include <iostream> +#include <string> +#include <vector> + + + +void run() +{ + + using boost::apply_visitor; + using boost::variant; + using std::string; + using std::vector; + using std::cout; + using std::endl; + + typedef variant< char*, string, short > t_var0; + typedef variant< int, string, double > t_var1; + typedef variant< short, const char* > t_var2; + typedef variant< string, char > t_var3; + typedef variant< unsigned short, const char* > t_var4; + typedef variant< unsigned short, const char*, t_var2 > t_var5; + typedef variant< unsigned short, const char*, t_var5 > t_var6; + typedef variant< class_a, const void* > t_var7; + typedef variant< t_var6, int > t_var8; + typedef variant< t_var8, unsigned short > t_var9; + typedef variant< char, unsigned char > t_var10; + typedef variant< short, int, vector<int>, long> t_var11; + + t_var1 v1; + t_var0 v0; + t_var2 v2; + t_var3 v3; + t_var4 v4; + t_var5 v5; + t_var6 v6; + t_var7 v7; + t_var8 v8; + t_var9 v9; + t_var10 v10; + t_var11 v11; + + + // + // Check assignment rules + // + + v2 = 4; + v4 = v2; + verify(v4, spec<unsigned short>()); + + v2 = "abc"; + v4 = v2; + verify(v4, spec<const char*>(), "[V] abc"); + + v5 = "def"; + verify(v5, spec<const char*>(), "[V] def"); + + v5 = v2; + verify(v5, spec<t_var2>(), "[V] [V] abc"); + + v6 = 58; + verify(v6, spec<unsigned short>(), "[V] 58"); + + v6 = v5; + verify(v6, spec<t_var5>(), "[V] [V] [V] abc"); + + v8 = v2; + verify(v8, spec<t_var6>(), "[V] [V] abc"); + + v8 = v6; + verify(v8, spec<t_var6>(), "[V] [V] [V] [V] abc"); + + v7 = v2; + verify(v7, spec<const void*>()); + + v7 = 199; + verify(v7, spec<class_a>(), "[V] class_a(199)"); + + v2 = 200; + v7 = v2; + verify(v7, spec<class_a>(), "[V] class_a(200)"); + + + + // + // Check sizes of held values + // + total_sizeof ts; + + v1 = 5.9; + apply_visitor(ts, v1); + + v1 = 'B'; + apply_visitor(ts, v1); + + v1 = 3.4f; + apply_visitor(ts, v1); + + BOOST_TEST(ts.result() == sizeof(int) + sizeof(double)*2); + + v11 = 5; + string res_s = apply_visitor(int_printer(), v11); + BOOST_TEST(res_s == "5"); + + // + // A variant object holding an std::vector + // + vector<int> int_vec_1; + int_vec_1.push_back(512); + int_vec_1.push_back(256); + int_vec_1.push_back(128); + int_vec_1.push_back(64); + + v11 = int_vec_1; + res_s = apply_visitor(int_printer(), v11); + BOOST_TEST(res_s == ",512,256,128,64"); +} + + + +int main() +{ + run(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/test2.cpp b/src/boost/libs/variant/test/test2.cpp new file mode 100644 index 00000000..12e31836 --- /dev/null +++ b/src/boost/libs/variant/test/test2.cpp @@ -0,0 +1,149 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test2.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#ifdef BOOST_MSVC +#pragma warning(disable:4244) // conversion from 'const int' to 'const short' +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include "jobs.h" + +#include <cassert> +#include <iostream> +#include <algorithm> +#include <cstring> + +using boost::apply_visitor; + +struct short_string +{ + BOOST_STATIC_CONSTANT(size_t, e_limit = 101); + + short_string() : len_(0) + { + buffer_[0] = '\0'; + } + + short_string(const char* src) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::strlen; +#endif // BOOST_NO_STDC_NAMESPACE + + size_t limit = this->e_limit; // avoid warnings on some compilers + size_t src_len = strlen(src); + + len_ = (std::min)(src_len, limit-1); + std::copy(src, src + len_, buffer_); + buffer_[len_] = '\0'; + } + + short_string(const short_string& other) : len_(other.len_) + { + std::copy(other.buffer_, other.buffer_ + e_limit, buffer_); + } + + void swap(short_string& other) + { + char temp[e_limit]; + + std::copy(buffer_, buffer_ + e_limit, temp); + std::copy(other.buffer_, other.buffer_ + e_limit, buffer_); + std::copy(temp, temp + e_limit, other.buffer_); + + std::swap(len_, other.len_); + } + + short_string& operator=(const short_string& rhs) + { + short_string temp(rhs); + swap(temp); + + return *this; + } + + operator const char*() const + { + return buffer_; + } + + +private: + char buffer_[e_limit]; + size_t len_; +}; //short_string + + +std::ostream& operator<<(std::ostream& out, const short_string& s) +{ + out << static_cast<const char*>(s); + return out; +} + + + +void run() +{ + using boost::variant; + + variant<short, short_string> v0; + variant<char, const char*> v1; + variant<short_string, char > v2; + + // + // Default construction + // + verify(v0, spec<short>()); + verify(v1, spec<char>()); + verify(v2, spec<short_string>()); + + // + // Implicit conversion to bounded type + // + v1 = "I am v1"; + verify(v1, spec<const char*>(), "[V] I am v1"); + + v2 = "I am v2"; + verify(v2, spec<short_string>(), "[V] I am v2"); + + // + // Variant-to-variant assignment + // + + v0 = v1; + verify(v0, spec<short_string>(), "[V] I am v1"); + + v1 = v0; + verify(v1, spec<const char*>(), "[V] I am v1"); + + const int n0 = 88; + v1 = n0; + v0 = v1; + + // + // Implicit conversion to bounded type + // + verify(v0, spec<short>(), "[V] 88"); + verify(v1, spec<char>(), "[V] X"); +} + + +int main() +{ + run(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test3.cpp b/src/boost/libs/variant/test/test3.cpp new file mode 100644 index 00000000..27f0f589 --- /dev/null +++ b/src/boost/libs/variant/test/test3.cpp @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test3.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include <iostream> +#include <sstream> +#include <string> + +///////////////////////////////////////////////////////////////////// + +using boost::variant; +using boost::recursive_wrapper; +using std::cout; +using std::endl; + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// + +struct Add; +struct Sub; + +typedef variant<int, recursive_wrapper<Add>, recursive_wrapper<Sub> > Expr; + +struct Sub +{ + Sub(); + Sub(const Expr& l, const Expr& r); + Sub(const Sub& other); + + Expr lhs_; + Expr rhs_; +}; + +struct Add +{ + Add() { } + Add(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { } + Add(const Add& other) : lhs_(other.lhs_), rhs_(other.rhs_) { } + + Expr lhs_; + Expr rhs_; +}; + +Sub::Sub() { } +Sub::Sub(const Expr& l, const Expr& r) : lhs_(l), rhs_(r) { } +Sub::Sub(const Sub& other) : lhs_(other.lhs_), rhs_(other.rhs_) { } + + +// +// insert-to operators +// +std::ostream& operator<<(std::ostream& out, const Sub& a); + +std::ostream& operator<<(std::ostream& out, const Add& a) +{ + out << '(' << a.lhs_ << '+' << a.rhs_ << ')'; + return out; +} + +std::ostream& operator<<(std::ostream& out, const Sub& a) +{ + out << '(' << a.lhs_ << '-' << a.rhs_ << ')'; + return out; +} + +// +// Expression evaluation visitor +// +struct Calculator : boost::static_visitor<int> +{ + Calculator() { } + + int operator()(Add& x) const + { + Calculator calc; + int n1 = boost::apply_visitor(calc, x.lhs_); + int n2 = boost::apply_visitor(calc, x.rhs_); + + return n1 + n2; + } + + int operator()(Sub& x) const + { + return boost::apply_visitor(Calculator(), x.lhs_) + - boost::apply_visitor(Calculator(), x.rhs_); + } + + int operator()(Expr& x) const + { + Calculator calc; + return boost::apply_visitor(calc, x); + } + + int operator()(int x) const + { + return x; + } + +}; // Calculator + + +///////////////////////////////////////////////////////////////////// + + +int main() +{ + + int n = 13; + Expr e1( Add(n, Sub(Add(40,2),Add(10,4))) ); //n + (40+2)-(10+14) = n+28 + + std::ostringstream e1_str; + e1_str << e1; + + BOOST_TEST(e1.type() == boost::typeindex::type_id<Add>()); + BOOST_TEST(e1_str.str() == "(13+((40+2)-(10+4)))"); + + //Evaluate expression + int res = boost::apply_visitor(Calculator(), e1); + BOOST_TEST(res == n + 28); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test4.cpp b/src/boost/libs/variant/test/test4.cpp new file mode 100644 index 00000000..bef83b36 --- /dev/null +++ b/src/boost/libs/variant/test/test4.cpp @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test4.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#ifdef BOOST_MSVC +#pragma warning(disable:4244) // conversion from 'const int' to 'const short' +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include "jobs.h" + +#include <string> + +struct class_a; + +using boost::variant; + +typedef variant<std::string, class_a, float> var_type_1; +typedef variant<std::string, class_a, short> var_type_2; + +#include "class_a.h" + +int main() +{ + using namespace boost; + + var_type_1 v1; + var_type_2 v2; + + v1 = class_a(); + verify(v1, spec<class_a>(), "[V] class_a(5511)"); + + verify(v2, spec<std::string>(), "[V] "); + + v2 = "abcde"; + verify(v2, spec<std::string>(), "[V] abcde"); + + v2 = v1; + verify(v2, spec<class_a>(), "[V] class_a(5511)"); + + v2 = 5; + v1 = v2; + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/test5.cpp b/src/boost/libs/variant/test/test5.cpp new file mode 100644 index 00000000..5de06c8c --- /dev/null +++ b/src/boost/libs/variant/test/test5.cpp @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test5.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include "jobs.h" + +#include <assert.h> +#include <iostream> +#include <string> +#include <vector> + + +void run() +{ + using std::string; + using boost::variant; + using boost::apply_visitor; + + typedef variant<int, float, unsigned short, unsigned char> t_var1; + typedef variant<int, t_var1, unsigned short, unsigned char> t_var2; + typedef variant<string, int, t_var2> t_var3; + + t_var1 v1; + t_var2 v2; + t_var2 v2_second; + t_var3 v3; + + const char c0 = 'x'; + v1 = c0; + + //v2 and v3 are holding (aka: containing) a variant + v2 = v1; + v3 = v2; + + verify(v1, spec<int>()); + verify(v2, spec<t_var1>()); + verify(v3, spec<t_var2>()); + + + // + // assignment from const char (Converted to int) + // + v2 = c0; + v3 = c0; + + verify(v2, spec<int>()); + verify(v3, spec<int>()); + + + BOOST_TEST(apply_visitor(sum_int(), v2) == c0); + BOOST_TEST(apply_visitor(sum_int(), v3) == c0); + + sum_int adder; + apply_visitor(adder, v2); + apply_visitor(adder, v3); + + BOOST_TEST(adder.result() == 2*c0); + + // + // A variant holding a variant + // + typedef variant<unsigned char, float> t_var4; + typedef variant<string, t_var4> t_var5; + + t_var4 v4; + t_var5 v5; + + v5 = 22.5f; + verify(v5, spec<t_var4>(), "[V] [V] 22.5"); +} + + + +int main() +{ + run(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test6.cpp b/src/boost/libs/variant/test/test6.cpp new file mode 100644 index 00000000..6a0c75d6 --- /dev/null +++ b/src/boost/libs/variant/test/test6.cpp @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test6.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include <iostream> + +#include "jobs.h" + + +//Just Another Class +struct jac +{ + jac() { } + jac(int ) { } + jac(const char* ) { } +}; + +std::ostream& operator<<(std::ostream& out, const jac& ) +{ + out << "jac "; + return out; +} + + +void run() +{ + using boost::variant; + + variant<jac, int, double*, const double*> v1; + variant<int, char, double*, const double*, char*> v2; + + v1 = v2; + + verify(v1, spec<int>()); + verify(v2, spec<int>()); + + verify_not(v1, spec<jac>()); + verify_not(v1, spec<double*>()); + verify_not(v1, spec<const double*>()); + + verify_not(v2, spec<char>()); + verify_not(v2, spec<double*>()); + verify_not(v2, spec<const double*>()); + verify_not(v2, spec<char*>()); + + + variant<jac, const double*> v3; + variant<int, unsigned char, double*> v4; + + v3 = v4; + verify(v3, spec<jac>()); + verify(v4, spec<int>()); + verify_not(v4, spec<unsigned char>()); +} + + + +int main() +{ + run(); + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test7.cpp b/src/boost/libs/variant/test/test7.cpp new file mode 100644 index 00000000..1acec31e --- /dev/null +++ b/src/boost/libs/variant/test/test7.cpp @@ -0,0 +1,255 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test7.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" + +#ifdef BOOST_MSVC +#pragma warning(disable:4244) // conversion from 'const int' to 'const short' +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include "jobs.h" + +#include <iostream> +#include <algorithm> +#include <string> +#include <map> + +#include "boost/detail/workaround.hpp" +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +# include "boost/mpl/bool.hpp" +# include "boost/type_traits/is_same.hpp" +#endif + + +using namespace boost; +using namespace std; + + +struct jas +{ + jas(int n = 364); + jas(const jas& other); + + ~jas(); + jas& operator=(const jas& other); + + void swap(jas& other); + + int n_; + + int sn_; + static int s_inst_id_; +}; + +struct Tracker +{ + typedef map<const jas*,int> table_type; + typedef table_type::iterator iterator_type; + + static table_type s_this_to_sn_; + + static void insert(const jas& j) + { + s_this_to_sn_[&j] = j.sn_; + cout << "jas( " << j.sn_ << ") Registered" << endl; + } + + static void remove(const jas& j) + { + iterator_type iter = s_this_to_sn_.find(&j); + BOOST_TEST(iter != s_this_to_sn_.end()); + BOOST_TEST( ((*iter).second) == j.sn_); + + int sn = (*iter).second; + if(sn != j.sn_) + { + cout << "Mismatch: this = " << (*iter).first << ", sn_ = " << sn + << ", other: this = " << &j << ", j.sn_ = " << j.sn_ << endl; + } + + BOOST_TEST(sn == j.sn_); + + + + + + s_this_to_sn_.erase(&j); + cout << "jas( " << j.sn_ << ") Removed" << endl; + } + + static void check() + { + BOOST_TEST(s_this_to_sn_.empty()); + } +}; + +Tracker::table_type Tracker::s_this_to_sn_; + + + +jas::jas(int n) : n_(n) +{ + sn_ = s_inst_id_; + s_inst_id_ += 1; + + Tracker::insert(*this); +} + +jas::jas(const jas& other) : n_(other.n_) +{ + sn_ = s_inst_id_; + s_inst_id_ += 1; + + Tracker::insert(*this); +} + +jas::~jas() +{ + Tracker::remove(*this); +} + +jas& jas::operator=(const jas& other) +{ + jas temp(other); + swap(temp); + + return *this; +} + +void jas::swap(jas& other) +{ + Tracker::remove(*this); + Tracker::remove(other); + + std::swap(n_, other.n_); + std::swap(sn_, other.sn_); + + Tracker::insert(*this); + Tracker::insert(other); +} + +int jas::s_inst_id_ = 0; + + +bool operator==(const jas& a, const jas& b) +{ + return a.n_ == b.n_; +} + +ostream& operator<<(ostream& out, const jas& a) +{ + cout << "jas::n_ = " << a.n_; + return out; +} + + +template<typename ValueType> +struct compare_helper : boost::static_visitor<bool> +{ + compare_helper(ValueType& expected) : expected_(expected) { } + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + + bool operator()(const ValueType& value) + { + return value == expected_; + } + + template <typename T> + bool operator()(const T& ) + { + return false; + } + +#else // MSVC6 + +private: + + bool compare_impl(const ValueType& value, boost::mpl::true_) + { + return value == expected_; + } + + template <typename T> + bool compare_impl(const T&, boost::mpl::false_) + { + return false; + } + +public: + + template <typename T> + bool operator()(const T& value) + { + typedef typename boost::is_same<T, ValueType>::type + T_is_ValueType; + + return compare_impl(value, T_is_ValueType()); + } + +#endif // MSVC6 workaround + + ValueType& expected_; + +private: + compare_helper& operator=(const compare_helper&); + +}; + +template<typename VariantType, typename ExpectedType> +void var_compare(const VariantType& v, ExpectedType expected) +{ + compare_helper<ExpectedType> ch(expected); + + bool checks = boost::apply_visitor(ch, v); + BOOST_TEST(checks); +} + + +void run() +{ + boost::variant<string, short> v0; + + var_compare(v0, string("")); + + v0 = 8; + var_compare(v0, static_cast<short>(8)); + + v0 = "penny lane"; + var_compare(v0, string("penny lane")); + + boost::variant<jas, string, int> v1, v2 = jas(195); + var_compare(v1, jas(364)); + + v1 = jas(500); + v1.swap(v2); + + var_compare(v1, jas(195)); + var_compare(v2, jas(500)); + + + boost::variant<string, int> v3; + var_compare(v3, string("")); +} + + +int main() +{ + run(); + Tracker::check(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test8.cpp b/src/boost/libs/variant/test/test8.cpp new file mode 100644 index 00000000..94ef65ab --- /dev/null +++ b/src/boost/libs/variant/test/test8.cpp @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test8.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include <iostream> +#include <vector> +#include <string> + +using namespace boost; + +typedef variant<float, std::string, int, std::vector<std::string> > t_var1; + +struct int_sum : static_visitor<> +{ + int_sum() : result_(0) { } + + void operator()(int t) + { + result_ += t; + } + + result_type operator()(float ) { } + result_type operator()(const std::string& ) { } + result_type operator()(const std::vector<std::string>& ) { } + + int result_; +}; + +template <typename T, typename Variant> +T& check_pass(Variant& v, T value) +{ + BOOST_TEST(get<T>(&v)); + + try + { + T& r = get<T>(v); + BOOST_TEST(r == value); + return r; + } + catch(boost::bad_get&) + { + throw; // must never reach + } +} + +template <typename T, typename Variant> +void check_fail(Variant& v) +{ + BOOST_TEST(!relaxed_get<T>(&v)); + + try + { + T& r = relaxed_get<T>(v); + (void)r; // suppress warning about r not being used + BOOST_TEST(false && relaxed_get<T>(&v)); // should never reach + } + catch(const boost::bad_get& e) + { + BOOST_TEST(!!e.what()); // make sure that what() is const qualified and returnes something + } +} + +int main() +{ + int_sum acc; + t_var1 v1 = 800; + + // check get on non-const variant + { + int& r1 = check_pass<int>(v1, 800); + const int& cr1 = check_pass<const int>(v1, 800); + + check_fail<float>(v1); + check_fail<const float>(v1); + check_fail<short>(v1); + check_fail<const short>(v1); + + apply_visitor(acc, v1); + BOOST_TEST(acc.result_ == 800); + + r1 = 920; // NOTE: modifies content of v1 + apply_visitor(acc, v1); + BOOST_TEST(cr1 == 920); + BOOST_TEST(acc.result_ == 800 + 920); + } + + // check const correctness: + { + const t_var1& c = v1; + + check_pass<const int>(c, 920); + + //check_fail<int>(c); + check_fail<const float>(c); + //check_fail<float>(c); + check_fail<const short>(c); + //check_fail<short>(c); + } + + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/test9.cpp b/src/boost/libs/variant/test/test9.cpp new file mode 100644 index 00000000..465089cd --- /dev/null +++ b/src/boost/libs/variant/test/test9.cpp @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/test9.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2016-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// Test from https://github.com/boostorg/variant/pull/21 + +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/mpl.hpp> +#include <boost/variant/variant.hpp> + +int main() { + boost::make_variant_over<boost::fusion::vector<int, char> >::type t; + (void)t; +} diff --git a/src/boost/libs/variant/test/variant_comparison_test.cpp b/src/boost/libs/variant/test/variant_comparison_test.cpp new file mode 100644 index 00000000..a918a675 --- /dev/null +++ b/src/boost/libs/variant/test/variant_comparison_test.cpp @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_comparison_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 Eric Friedman, Itay Maman +// Copyright (c) 2014-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/variant/variant.hpp" +#include "boost/core/lightweight_test.hpp" + +#include <iostream> +#include <sstream> +#include <string> + +#include <algorithm> +#include <vector> + +#include "boost/detail/workaround.hpp" +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) +# pragma warn -lvc // temporary used for parameter warning +#endif + +template <typename T> +void assert_equality_comparable( + const T& x, const T& y, const T& z + ) +{ + // identity check + BOOST_TEST( !(&x == &y) || (x == y) ); + BOOST_TEST( !(&x == &z) || (x == z) ); + BOOST_TEST( !(&y == &z) || (y == z) ); + BOOST_TEST( !(&x == &y) || !(x != y) ); + BOOST_TEST( !(&x == &z) || !(x != z) ); + BOOST_TEST( !(&y == &z) || !(y != z) ); + + // reflexivity check + BOOST_TEST( (x == x) ); + BOOST_TEST( (y == y) ); + BOOST_TEST( (z == z) ); + + // symmetry check + BOOST_TEST( !(x == y) || (y == x) ); + BOOST_TEST( !(y == x) || (x == y) ); + BOOST_TEST( (x != y) || (y == x) ); + BOOST_TEST( (y != x) || (x == y) ); + + BOOST_TEST( !(x == z) || (z == x) ); + BOOST_TEST( !(z == x) || (x == z) ); + BOOST_TEST( (x != z) || (z == x) ); + BOOST_TEST( (z != x) || (x == z) ); + + BOOST_TEST( !(y == z) || (z == y) ); + BOOST_TEST( !(z == y) || (y == z) ); + BOOST_TEST( (y != z) || (z == y) ); + BOOST_TEST( (z != y) || (y == z) ); + + // transitivity check + BOOST_TEST( !(x == y && y == z) || (x == z) ); + BOOST_TEST( !(x == z && z == y) || (x == y) ); + BOOST_TEST( !(y == z && z == x) || (y == x) ); +} + +template <typename T> +void assert_less_than_comparable( + const T& x, const T& y, const T& z + ) +{ + // irreflexivity check + BOOST_TEST( !(x < x) ); + BOOST_TEST( !(y < y) ); + BOOST_TEST( !(z < z) ); + BOOST_TEST( !(x > x) ); + BOOST_TEST( !(y > y) ); + BOOST_TEST( !(z > z) ); + + BOOST_TEST( (x <= x) ); + BOOST_TEST( (y <= y) ); + BOOST_TEST( (z <= z) ); + BOOST_TEST( (x >= x) ); + BOOST_TEST( (y >= y) ); + BOOST_TEST( (z >= z) ); + + // transitivity check + BOOST_TEST( (x < y) ); + BOOST_TEST( (y < z) ); + BOOST_TEST( (x < z) ); + + BOOST_TEST( (x <= y) ); + BOOST_TEST( (y <= z) ); + BOOST_TEST( (x <= z) ); + + BOOST_TEST( (z > y) ); + BOOST_TEST( (y > x) ); + BOOST_TEST( (z > x) ); + + BOOST_TEST( (z >= y) ); + BOOST_TEST( (y >= x) ); + BOOST_TEST( (z >= x) ); + + // antisymmetry check + BOOST_TEST( !(y < x) ); + BOOST_TEST( !(z < y) ); + BOOST_TEST( !(z < x) ); +} + +template <typename It> +std::string print_range(It first, It last) +{ + std::ostringstream result; + + while (first != last) + { + result << *first << ' '; + ++first; + } + + return result.str(); +} + +int main() +{ + typedef boost::variant<int, std::string> var_t; + + var_t var1(3); + var_t var2(5); + var_t var3("goodbye"); + var_t var4("hello"); + + assert_equality_comparable(var1, var1, var1); + assert_equality_comparable(var_t(var1), var_t(var1), var_t(var1)); + assert_equality_comparable(var1, var2, var3); + + assert_less_than_comparable(var1, var2, var3); + assert_less_than_comparable(var2, var3, var4); + + std::vector<var_t> vec; + vec.push_back( var3 ); + vec.push_back( var2 ); + vec.push_back( var4 ); + vec.push_back( var1 ); + std::sort(vec.begin(), vec.end()); + + std::string sort_result( print_range(vec.begin(), vec.end()) ); + BOOST_TEST( sort_result == "3 5 goodbye hello " ); + + // https://svn.boost.org/trac/boost/ticket/11751 + int a = 0, b = 0; + + boost::variant< int& > v (a), u (b); + BOOST_TEST(v == u); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_get_test.cpp b/src/boost/libs/variant/test/variant_get_test.cpp new file mode 100644 index 00000000..8fe09c1d --- /dev/null +++ b/src/boost/libs/variant/test/variant_get_test.cpp @@ -0,0 +1,417 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_get_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2014-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef _MSC_VER +#pragma warning(disable: 4127) // conditional expression is constant +#pragma warning(disable: 4181) // qualifier applied to reference type; ignored +#endif + +#include "boost/variant/get.hpp" +#include "boost/variant/variant.hpp" +#include "boost/variant/polymorphic_get.hpp" +#include "boost/variant/recursive_wrapper.hpp" +#include "boost/core/lightweight_test.hpp" + +struct base { + int trash; + + base() : trash(123) {} + base(const base& b) : trash(b.trash) { int i = 100; (void)i; } + const base& operator=(const base& b) { + trash = b.trash; + int i = 100; (void)i; + + return *this; + } + + virtual ~base(){} +}; + +struct derived1 : base{}; +struct derived2 : base{}; + +struct vbase { short trash; virtual ~vbase(){} virtual int foo() const { return 0; } }; +struct vderived1 : virtual vbase{ virtual int foo() const { return 1; } }; +struct vderived2 : virtual vbase{ virtual int foo() const { return 3; } }; +struct vderived3 : vderived1, vderived2 { virtual int foo() const { return 3; } }; + +typedef boost::variant<int, base, derived1, derived2, std::string> var_t; +typedef boost::variant<int, derived1, derived2, std::string> var_t_shortened; +typedef boost::variant<base, derived1, derived2> var_t_no_fallback; +typedef boost::variant<int&, base&, derived1&, derived2&, std::string&> var_ref_t; +typedef boost::variant<const int&, const base&, const derived1&, const derived2&, const std::string&> var_cref_t; + +struct recursive_structure; +typedef boost::variant< + int, base, derived1, derived2, std::string, boost::recursive_wrapper<recursive_structure> +> var_req_t; +struct recursive_structure { var_req_t var; }; + +template <class TypeInVariant, class V, class TestType> +inline void check_polymorphic_get_on_types_impl_single_type(V* v) +{ + typedef typename boost::add_reference<TestType>::type ref_test_t; + typedef typename boost::add_reference<const TestType>::type cref_test_t; + const bool exact_same = !!boost::is_same<TypeInVariant, TestType>::value; + const bool ref_same = !!boost::is_same<TypeInVariant, ref_test_t>::value; + + if (exact_same || ref_same) { + BOOST_TEST(boost::polymorphic_get<TestType>(v)); + BOOST_TEST(boost::polymorphic_get<const TestType>(v)); + BOOST_TEST(boost::polymorphic_strict_get<TestType>(v)); + BOOST_TEST(boost::polymorphic_strict_get<const TestType>(v)); + BOOST_TEST(boost::polymorphic_relaxed_get<TestType>(v)); + BOOST_TEST(boost::polymorphic_relaxed_get<const TestType>(v)); + + BOOST_TEST(boost::polymorphic_get<cref_test_t>(v)); + BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v)); + BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v)); + + if (ref_same) { + BOOST_TEST(boost::polymorphic_get<ref_test_t>(v)); + BOOST_TEST(boost::polymorphic_get<cref_test_t>(v)); + BOOST_TEST(boost::polymorphic_strict_get<ref_test_t>(v)); + BOOST_TEST(boost::polymorphic_strict_get<cref_test_t>(v)); + BOOST_TEST(boost::polymorphic_relaxed_get<ref_test_t>(v)); + BOOST_TEST(boost::polymorphic_relaxed_get<cref_test_t>(v)); + } + } else { + BOOST_TEST(!boost::polymorphic_get<TestType>(v)); + BOOST_TEST(!boost::polymorphic_get<const TestType>(v)); + BOOST_TEST(!boost::polymorphic_strict_get<TestType>(v)); + BOOST_TEST(!boost::polymorphic_strict_get<const TestType>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<TestType>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<const TestType>(v)); + } +} + +template <class T, class V, class TestType> +inline void check_get_on_types_impl_single_type(V* v) +{ + typedef typename boost::add_reference<TestType>::type ref_test_t; + typedef typename boost::add_reference<const TestType>::type cref_test_t; + const bool exact_same = !!boost::is_same<T, TestType>::value; + const bool ref_same = !!boost::is_same<T, ref_test_t>::value; + + if (exact_same || ref_same) { + BOOST_TEST(boost::get<TestType>(v)); + BOOST_TEST(boost::get<const TestType>(v)); + BOOST_TEST(boost::strict_get<TestType>(v)); + BOOST_TEST(boost::strict_get<const TestType>(v)); + BOOST_TEST(boost::relaxed_get<TestType>(v)); + BOOST_TEST(boost::relaxed_get<const TestType>(v)); + + BOOST_TEST(boost::get<cref_test_t>(v)); + BOOST_TEST(boost::strict_get<cref_test_t>(v)); + BOOST_TEST(boost::relaxed_get<cref_test_t>(v)); + + if (ref_same) { + BOOST_TEST(boost::get<ref_test_t>(v)); + BOOST_TEST(boost::get<cref_test_t>(v)); + BOOST_TEST(boost::strict_get<ref_test_t>(v)); + BOOST_TEST(boost::strict_get<cref_test_t>(v)); + BOOST_TEST(boost::relaxed_get<ref_test_t>(v)); + BOOST_TEST(boost::relaxed_get<cref_test_t>(v)); + } + } else { + BOOST_TEST(!boost::get<TestType>(v)); + BOOST_TEST(!boost::get<const TestType>(v)); + BOOST_TEST(!boost::strict_get<TestType>(v)); + BOOST_TEST(!boost::strict_get<const TestType>(v)); + BOOST_TEST(!boost::relaxed_get<TestType>(v)); + BOOST_TEST(!boost::relaxed_get<const TestType>(v)); + } +} + +template <class T, class V> +inline void check_get_on_types_impl(V* v) +{ + check_get_on_types_impl_single_type<T, V, int>(v); + check_polymorphic_get_on_types_impl_single_type<T, V, int>(v); + + check_get_on_types_impl_single_type<T, V, base>(v); + + check_get_on_types_impl_single_type<T, V, derived1>(v); + check_polymorphic_get_on_types_impl_single_type<T, V, derived1>(v); + + check_get_on_types_impl_single_type<T, V, derived2>(v); + check_polymorphic_get_on_types_impl_single_type<T, V, derived2>(v); + + check_get_on_types_impl_single_type<T, V, std::string>(v); + check_polymorphic_get_on_types_impl_single_type<T, V, std::string>(v); + + // Never exist in here + BOOST_TEST(!boost::relaxed_get<short>(v)); + BOOST_TEST(!boost::relaxed_get<const short>(v)); + BOOST_TEST(!boost::relaxed_get<char>(v)); + BOOST_TEST(!boost::relaxed_get<char*>(v)); + BOOST_TEST(!boost::relaxed_get<bool>(v)); + BOOST_TEST(!boost::relaxed_get<const bool>(v)); + + BOOST_TEST(!boost::polymorphic_relaxed_get<short>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<const short>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<char>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<char*>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<bool>(v)); + BOOST_TEST(!boost::polymorphic_relaxed_get<const bool>(v)); + + boost::get<T>(*v); // Must compile + boost::get<const T>(*v); // Must compile + boost::strict_get<T>(*v); // Must compile + boost::strict_get<const T>(*v); // Must compile + + bool is_ref = boost::is_lvalue_reference<T>::value; + (void)is_ref; + if (!is_ref) { + boost::polymorphic_get<T>(*v); // Must compile + boost::polymorphic_get<const T>(*v); // Must compile + boost::polymorphic_strict_get<T>(*v); // Must compile + boost::polymorphic_strict_get<const T>(*v); // Must compile + } +} + +template <class T, class V> +inline void check_get_on_types(V* v) +{ + check_get_on_types_impl<T, V>(v); + check_get_on_types_impl<T, const V>(v); +} + +inline void get_test() +{ + var_t v; + check_get_on_types<int>(&v); + + var_t(base()).swap(v); + check_get_on_types<base>(&v); + + var_t(derived1()).swap(v); + check_get_on_types<derived1>(&v); + + var_t(derived2()).swap(v); + check_get_on_types<derived2>(&v); + + var_t(std::string("Hello")).swap(v); + check_get_on_types<std::string>(&v); + + var_t_shortened vs = derived2(); + check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs); + check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs); + // Checking that Base is really determinated + check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs); + check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs); + + vs = derived1(); + check_polymorphic_get_on_types_impl_single_type<derived2, var_t_shortened, int>(&vs); + check_polymorphic_get_on_types_impl_single_type<derived2, const var_t_shortened, int>(&vs); + // Checking that Base is really determinated + check_polymorphic_get_on_types_impl_single_type<base, var_t_shortened, base>(&vs); + check_polymorphic_get_on_types_impl_single_type<base, const var_t_shortened, base>(&vs); +} + +inline void get_test_no_fallback() +{ + var_t_no_fallback v; + var_t_no_fallback(base()).swap(v); + check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v); + check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v); + check_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v); + check_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v); + + var_t_no_fallback(derived1()).swap(v); + check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v); + check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v); + check_get_on_types_impl_single_type<derived1, var_t_no_fallback, derived1>(&v); + check_get_on_types_impl_single_type<derived1, const var_t_no_fallback, derived1>(&v); + + var_t_no_fallback(derived2()).swap(v); + check_polymorphic_get_on_types_impl_single_type<base, var_t_no_fallback, base>(&v); + check_polymorphic_get_on_types_impl_single_type<base, const var_t_no_fallback, base>(&v); + check_get_on_types_impl_single_type<derived2, var_t_no_fallback, derived2>(&v); + check_get_on_types_impl_single_type<derived2, const var_t_no_fallback, derived2>(&v); +} + +inline void get_ref_test() +{ + int i = 0; + var_ref_t v(i); + check_get_on_types<int>(&v); + check_get_on_types<int&>(&v); + + base b; + var_ref_t v1(b); + check_get_on_types<base>(&v1); + check_get_on_types<base&>(&v1); + + derived1 d1; + var_ref_t v2(d1); + check_get_on_types<derived1>(&v2); + check_get_on_types<derived1&>(&v2); + + derived2 d2; + var_ref_t v3(d2); + check_get_on_types<derived2>(&v3); + check_get_on_types<derived2&>(&v3); + + std::string s("Hello"); + var_ref_t v4(s); + check_get_on_types<std::string>(&v4); + check_get_on_types<std::string&>(&v4); +} + + +inline void get_cref_test() +{ + int i = 0; + var_cref_t v(i); + BOOST_TEST(boost::get<const int>(&v)); + BOOST_TEST(boost::get<const int&>(&v)); + BOOST_TEST(!boost::get<const base>(&v)); + + base b; + var_cref_t v1(b); + BOOST_TEST(boost::get<const base>(&v1)); + BOOST_TEST(!boost::get<const derived1>(&v1)); + BOOST_TEST(!boost::get<const int>(&v1)); + + std::string s("Hello"); + const var_cref_t v4 = s; + BOOST_TEST(boost::get<const std::string>(&v4)); + BOOST_TEST(!boost::get<const int>(&v4)); +} + +inline void get_recursive_test() +{ + var_req_t v; + check_get_on_types<int>(&v); + + var_req_t(base()).swap(v); + check_get_on_types<base>(&v); + + var_req_t(derived1()).swap(v); + check_get_on_types<derived1>(&v); + + var_req_t(derived2()).swap(v); + check_get_on_types<derived2>(&v); + + var_req_t(std::string("Hello")).swap(v); + check_get_on_types<std::string>(&v); + + recursive_structure s = { v }; // copying "v" + v = s; + check_get_on_types<recursive_structure>(&v); +} + +template <class T> +inline void check_that_does_not_exist_impl() +{ + using namespace boost::detail::variant; + + BOOST_TEST((holds_element<T, const int>::value)); + BOOST_TEST((!holds_element<T, short>::value)); + BOOST_TEST((!holds_element<T, short>::value)); + BOOST_TEST((!holds_element<T, const short>::value)); + BOOST_TEST((!holds_element<T, char*>::value)); + BOOST_TEST((!holds_element<T, const char*>::value)); + BOOST_TEST((!holds_element<T, char[5]>::value)); + BOOST_TEST((!holds_element<T, const char[5]>::value)); + BOOST_TEST((!holds_element<T, bool>::value)); + BOOST_TEST((!holds_element<T, const bool>::value)); + + BOOST_TEST((!holds_element<T, boost::recursive_wrapper<int> >::value)); + BOOST_TEST((!holds_element<T, boost::recursive_wrapper<short> >::value)); + BOOST_TEST((!holds_element<T, boost::detail::reference_content<short> >::value)); + + + BOOST_TEST((holds_element_polymorphic<T, const int>::value)); + BOOST_TEST((!holds_element_polymorphic<T, short>::value)); + BOOST_TEST((!holds_element_polymorphic<T, short>::value)); + BOOST_TEST((!holds_element_polymorphic<T, const short>::value)); + BOOST_TEST((!holds_element_polymorphic<T, char*>::value)); + BOOST_TEST((!holds_element_polymorphic<T, const char*>::value)); + BOOST_TEST((!holds_element_polymorphic<T, char[5]>::value)); + BOOST_TEST((!holds_element_polymorphic<T, const char[5]>::value)); + BOOST_TEST((!holds_element_polymorphic<T, bool>::value)); + BOOST_TEST((!holds_element_polymorphic<T, const bool>::value)); + + BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<int> >::value)); + BOOST_TEST((!holds_element_polymorphic<T, boost::recursive_wrapper<short> >::value)); + BOOST_TEST((!holds_element_polymorphic<T, boost::detail::reference_content<short> >::value)); +} + +inline void check_that_does_not_exist() +{ + using namespace boost::detail::variant; + + BOOST_TEST((holds_element<var_t, int>::value)); + BOOST_TEST((holds_element<var_ref_t, int>::value)); + BOOST_TEST((!holds_element<var_cref_t, int>::value)); + + check_that_does_not_exist_impl<var_t>(); + check_that_does_not_exist_impl<var_ref_t>(); + check_that_does_not_exist_impl<var_cref_t>(); + check_that_does_not_exist_impl<var_req_t>(); +} + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +class MoveonlyType { +public: + MoveonlyType() {} + ~MoveonlyType() {} + + MoveonlyType(MoveonlyType&&) {} + void operator=(MoveonlyType&&) {} + +private: + MoveonlyType(const MoveonlyType&); + void operator=(const MoveonlyType&); +}; + +const boost::variant<int, std::string> foo1() { return ""; } +boost::variant<int, std::string> foo2() { return ""; } + +inline void get_rvref_test() +{ + boost::get<std::string>(foo1()); + boost::get<std::string>(foo2()); + + boost::variant<MoveonlyType, int> v; + + v = MoveonlyType(); + boost::get<MoveonlyType>(boost::move(v)); + + v = 3; + + v = MoveonlyType(); + boost::get<MoveonlyType>(v); + + boost::relaxed_get<MoveonlyType&>(boost::variant<MoveonlyType, int>()); + + v = MoveonlyType(); + MoveonlyType moved_from_variant(boost::get<MoveonlyType>(boost::move(v))); +} +#endif // BOOST_NO_CXX11_RVALUE_REFERENCES + +int main() +{ + get_test(); + get_test_no_fallback(); + get_ref_test(); + get_cref_test(); + get_recursive_test(); + check_that_does_not_exist(); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + get_rvref_test(); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_multivisit_test.cpp b/src/boost/libs/variant/test/variant_multivisit_test.cpp new file mode 100644 index 00000000..a614dd33 --- /dev/null +++ b/src/boost/libs/variant/test/variant_multivisit_test.cpp @@ -0,0 +1,159 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_multivisit_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2013-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/config.hpp" +#include "boost/noncopyable.hpp" +#define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 5 +#include "boost/variant/multivisitors.hpp" +#include "boost/variant.hpp" + +#include "boost/core/lightweight_test.hpp" + +struct my_noncopyable : boost::noncopyable { + my_noncopyable(){} + ~my_noncopyable(){} +}; + +typedef boost::variant<my_noncopyable, int> variant_noncopy_t; + + +typedef boost::variant<char, unsigned char, signed char, unsigned short, int, unsigned int> variant6_t; + +struct test_visitor: boost::static_visitor<> { + // operators that shall not be called + template <class T1, class T2, class T3> + void operator()(T1&, T2&, T3&) const + { + BOOST_TEST(false); + } + + template <class T1, class T2, class T3, class T4> + void operator()(T1&, T2&, T3&, T4&) const + { + BOOST_TEST(false); + } + + template <class T1, class T2, class T3, class T4, class T5> + void operator()(T1&, T2&, T3&, T4&, T5&) const + { + BOOST_TEST(false); + } + + // operators that are OK to call + void operator()(char v0, unsigned char v1, signed char v2) const + { + BOOST_TEST(v0 == 0); + BOOST_TEST(v1 == 1); + BOOST_TEST(v2 == 2); + } + + void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3) const + { + BOOST_TEST(v0 == 0); + BOOST_TEST(v1 == 1); + BOOST_TEST(v2 == 2); + BOOST_TEST(v3 == 3); + } + + void operator()(char v0, unsigned char v1, signed char v2, unsigned short v3, int v4) const + { + BOOST_TEST(v0 == 0); + BOOST_TEST(v1 == 1); + BOOST_TEST(v2 == 2); + BOOST_TEST(v3 == 3); + BOOST_TEST(v4 == 4); + } + + + // Noncopyables + void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&) const { + BOOST_TEST(true); + } + void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const { + BOOST_TEST(true); + } + void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const { + BOOST_TEST(true); + } + void operator()(my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&, my_noncopyable&) const { + BOOST_TEST(true); + } +}; + +typedef boost::variant<int, double, bool> bool_like_t; +typedef boost::variant<int, double> arithmetics_t; + +struct if_visitor: public boost::static_visitor<arithmetics_t> { + template <class T0, class T1, class T2> + arithmetics_t operator()(T0 b, T1 v1, T2 v2) const { + if (!!b) { + return v1; + } else { + return v2; + } + } +}; + + +int main() +{ + test_visitor v; + + variant6_t v_array6[6]; + v_array6[0] = char(0); + v_array6[1] = static_cast<unsigned char>(1); + v_array6[2] = static_cast<signed char>(2); + v_array6[3] = static_cast<unsigned short>(3); + v_array6[4] = static_cast<int>(4); + v_array6[5] = static_cast<unsigned int>(5); + + boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2]); + boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2]); + +// Following test also pass, but requires many Gigabytes of RAM for compilation and compile for about 15 minutes +//#define BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME +#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME + boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3]); + boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3]); + + boost::apply_visitor(v, v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]); + boost::apply_visitor(test_visitor(), v_array6[0], v_array6[1], v_array6[2], v_array6[3], v_array6[4]); +#endif + + bool_like_t v0(1), v1(true), v2(1.0); + + BOOST_TEST( + boost::apply_visitor(if_visitor(), v0, v1, v2) + == + arithmetics_t(true) + ); + +#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) + if_visitor if_vis; + BOOST_TEST( + boost::apply_visitor(if_vis)(v0, v1, v2) + == + arithmetics_t(true) + ); +#endif + + + variant_noncopy_t vnonc[6]; + boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2]); + boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3]); + +#ifdef BOOST_VARIANT_MULTIVISITORS_TEST_VERY_EXTREME + boost::apply_visitor(v, vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4]); + boost::apply_visitor(test_visitor(), vnonc[0], vnonc[1], vnonc[2], vnonc[3], vnonc[4], vnonc[5]); +#endif + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_nonempty_check.cpp b/src/boost/libs/variant/test/variant_nonempty_check.cpp new file mode 100644 index 00000000..d6150e69 --- /dev/null +++ b/src/boost/libs/variant/test/variant_nonempty_check.cpp @@ -0,0 +1,474 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_nonempty_check.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2014-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// In this file we are making tests to ensure that variant guarantees nonemptiness. +// +// For that purpose we create a `throwing_class`, that throws exception at a specified +// assignment attempt. If exception was thrown during move/assignemnt operation we make sure +// that data in variant is same as before move/assignemnt operation or that a fallback type is +// stored in variant. +// +// Different nonthrowing_class'es are used to tests different variant internal policies: +// with/without fallback type + throw/nothrow copyable + throw/nothrow movable + + +#include "boost/variant/variant.hpp" +#include "boost/variant/get.hpp" +#include "boost/core/lightweight_test.hpp" +#include <stdexcept> + +struct exception_on_assignment : std::exception {}; +struct exception_on_move_assignment : exception_on_assignment {}; + +void prevent_compiler_noexcept_detection() { + char* p = new char; + *p = '\0'; + delete p; +} + + +struct throwing_class { + int trash; + enum helper_enum { + do_not_throw = 780, + throw_after_5, + throw_after_4, + throw_after_3, + throw_after_2, + throw_after_1 + }; + + bool is_throw() { + if (trash < do_not_throw) { + return true; + } + + if (trash > do_not_throw && trash <= throw_after_1) { + ++ trash; + return false; + } + + return trash != do_not_throw; + } + + throwing_class(int value = 123) BOOST_NOEXCEPT_IF(false) : trash(value) { + prevent_compiler_noexcept_detection(); + } + + throwing_class(const throwing_class& b) BOOST_NOEXCEPT_IF(false) : trash(b.trash) { + if (is_throw()) { + throw exception_on_assignment(); + } + } + + const throwing_class& operator=(const throwing_class& b) BOOST_NOEXCEPT_IF(false) { + trash = b.trash; + if (is_throw()) { + throw exception_on_assignment(); + } + + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + throwing_class(throwing_class&& b) BOOST_NOEXCEPT_IF(false) : trash(b.trash) { + if (is_throw()) { + throw exception_on_move_assignment(); + } + } + + const throwing_class& operator=(throwing_class&& b) BOOST_NOEXCEPT_IF(false) { + trash = b.trash; + if (is_throw()) { + throw exception_on_move_assignment(); + } + + return *this; + } +#endif + + virtual ~throwing_class() {} +}; + +struct nonthrowing_class { + int trash; + + nonthrowing_class() BOOST_NOEXCEPT_IF(false) : trash(123) { + prevent_compiler_noexcept_detection(); + } + + nonthrowing_class(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + } + + const nonthrowing_class& operator=(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nonthrowing_class(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + } + + const nonthrowing_class& operator=(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + return *this; + } +#endif +}; + +struct nonthrowing_class2 { + int trash; + + nonthrowing_class2() BOOST_NOEXCEPT_IF(false) : trash(123) { + prevent_compiler_noexcept_detection(); + } +}; + +struct nonthrowing_class3 { + int trash; + + nonthrowing_class3() BOOST_NOEXCEPT_IF(true) : trash(123) {} + + nonthrowing_class3(const nonthrowing_class3&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + } + + const nonthrowing_class3& operator=(const nonthrowing_class3&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nonthrowing_class3(nonthrowing_class3&&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + } + + const nonthrowing_class3& operator=(nonthrowing_class3&&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + return *this; + } +#endif +}; + +struct nonthrowing_class4 { + int trash; + + nonthrowing_class4() BOOST_NOEXCEPT_IF(false) : trash(123) { + prevent_compiler_noexcept_detection(); + } + + nonthrowing_class4(const nonthrowing_class4&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + } + + const nonthrowing_class4& operator=(const nonthrowing_class4&) BOOST_NOEXCEPT_IF(false) { + prevent_compiler_noexcept_detection(); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + nonthrowing_class4(nonthrowing_class4&&) BOOST_NOEXCEPT_IF(true) { + } + + const nonthrowing_class4& operator=(nonthrowing_class4&&) BOOST_NOEXCEPT_IF(true) { + return *this; + } +#endif +}; + + +// Tests ///////////////////////////////////////////////////////////////////////////////////// + + +template <class Nonthrowing> +inline void check_1_impl(int helper) +{ + boost::variant<throwing_class, Nonthrowing> v; + try { + v = throwing_class(helper); + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<throwing_class>(&v)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<throwing_class>(&v)); + } + + try { + throwing_class tc(helper); + v = tc; + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<throwing_class>(&v)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<throwing_class>(&v)); + } +} + +inline void check_1(int helper = 1) +{ + check_1_impl<nonthrowing_class>(helper); + check_1_impl<nonthrowing_class2>(helper); + check_1_impl<nonthrowing_class3>(helper); + check_1_impl<nonthrowing_class4>(helper); + check_1_impl<boost::blank>(helper); +} + +template <class Nonthrowing> +inline void check_2_impl(int helper) +{ + boost::variant<Nonthrowing, throwing_class> v; + try { + v = throwing_class(helper); + BOOST_TEST(v.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v)); + } + + try { + throwing_class cl(helper); + v = cl; + BOOST_TEST(v.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v)); + } +} + +inline void check_2(int helper = 1) +{ + check_2_impl<nonthrowing_class>(helper); + check_2_impl<nonthrowing_class2>(helper); + check_2_impl<nonthrowing_class3>(helper); + check_2_impl<nonthrowing_class4>(helper); + check_2_impl<boost::blank>(helper); +} + +template <class Nonthrowing> +inline void check_3_impl(int helper) +{ + boost::variant<Nonthrowing, throwing_class> v1, v2; + + swap(v1, v2); + try { + v1 = throwing_class(helper); + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v1.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v1)); + } + + + try { + v2 = throwing_class(helper); + BOOST_TEST(v2.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v2)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v2.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v2)); + } + + + if (!v1.which() && !v2.which()) { + swap(v1, v2); // Make sure that two backup holders swap well + BOOST_TEST(!v1.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v1)); + BOOST_TEST(!v2.which()); + BOOST_TEST(boost::get<Nonthrowing>(&v2)); + + v1 = v2; + } +} + +inline void check_3(int helper = 1) +{ + check_3_impl<nonthrowing_class>(helper); + check_3_impl<nonthrowing_class2>(helper); + check_3_impl<nonthrowing_class3>(helper); + check_3_impl<nonthrowing_class4>(helper); + check_3_impl<boost::blank>(helper); +} + +inline void check_4(int helper = 1) +{ + // This one has a fallback + boost::variant<int, throwing_class> v1, v2; + + swap(v1, v2); + try { + v1 = throwing_class(helper); + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v1.which()); + BOOST_TEST(boost::get<int>(&v1)); + } + + + try { + v2 = throwing_class(helper); + BOOST_TEST(v2.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v2)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(!v2.which()); + BOOST_TEST(boost::get<int>(&v2)); + } + + if (!v1.which() && !v2.which()) { + swap(v1, v2); + BOOST_TEST(!v1.which()); + BOOST_TEST(boost::get<int>(&v1)); + BOOST_TEST(!v2.which()); + BOOST_TEST(boost::get<int>(&v2)); + + v1 = v2; + } +} + +template <class Nonthrowing> +inline void check_5_impl(int helper) +{ + boost::variant<Nonthrowing, throwing_class> v1, v2; + throwing_class throw_not_now; + throw_not_now.trash = throwing_class::do_not_throw; + v1 = throw_not_now; + v2 = throw_not_now; + + boost::get<throwing_class>(v1).trash = 1; + boost::get<throwing_class>(v2).trash = 1; + + try { + v1 = throwing_class(helper); + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } + + boost::get<throwing_class>(v1).trash = throwing_class::do_not_throw; + boost::get<throwing_class>(v2).trash = throwing_class::do_not_throw; + v1 = Nonthrowing(); + v2 = Nonthrowing(); + try { + v1 = throwing_class(helper); + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v1.which() == 0); + BOOST_TEST(boost::get<Nonthrowing>(&v1)); + } + + int v1_type = v1.which(); + int v2_type = v2.which(); + try { + swap(v1, v2); // Make sure that backup holders swap well + BOOST_TEST(v1.which() == v2_type); + BOOST_TEST(v2.which() == v1_type); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v1.which() == v1_type); + BOOST_TEST(v2.which() == v2_type); + } +} + + +inline void check_5(int helper = 1) +{ + check_5_impl<nonthrowing_class>(helper); + check_5_impl<nonthrowing_class2>(helper); + check_5_impl<nonthrowing_class3>(helper); + check_5_impl<nonthrowing_class4>(helper); + check_5_impl<boost::blank>(helper); +} + +template <class Nonthrowing> +inline void check_6_impl(int helper) +{ + boost::variant<Nonthrowing, throwing_class> v1, v2; + throwing_class throw_not_now; + throw_not_now.trash = throwing_class::do_not_throw; + v1 = throw_not_now; + v2 = throw_not_now; + + v1 = throw_not_now; + v2 = throw_not_now; + swap(v1, v2); + boost::get<throwing_class>(v1).trash = 1; + boost::get<throwing_class>(v2).trash = 1; + + v1 = throwing_class(throw_not_now); + v2 = v1; + + v1 = Nonthrowing(); + try { + throwing_class tc; + tc.trash = helper; + v1 = tc; + BOOST_TEST(v1.which() == 1); + BOOST_TEST(boost::get<throwing_class>(&v1)); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v1.which() == 0); + } + + v2 = Nonthrowing(); + try { + v2 = 2; + BOOST_TEST(false); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v2.which() == 0); + } + + // Probably the most significant test: + // unsuccessful swap must preserve old values of variant + v1 = throw_not_now; + boost::get<throwing_class>(v1).trash = helper; + try { + swap(v1, v2); + } catch (const exception_on_assignment& /*e*/) { + BOOST_TEST(v1.which() == 1); + BOOST_TEST(v2.which() == 0); + BOOST_TEST(boost::get<throwing_class>(v1).trash == helper); + } +} + + +inline void check_6(int helper = 1) +{ + check_6_impl<nonthrowing_class>(helper); + check_6_impl<nonthrowing_class2>(helper); + check_6_impl<nonthrowing_class3>(helper); + check_6_impl<nonthrowing_class4>(helper); + check_6_impl<boost::blank>(helper); +} + +int main() +{ + // throwing_class::throw_after_1 + 1 => throw on first assignment/construction + // throwing_class::throw_after_1 => throw on second assignment/construction + // throwing_class::throw_after_2 => throw on third assignment/construction + // ... + for (int i = throwing_class::throw_after_1 + 1; i != throwing_class::do_not_throw; --i) { + check_1(i); + check_2(i); + check_3(i); + check_4(i); + check_5(i); + check_6(i); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_over_joint_view_test.cpp b/src/boost/libs/variant/test/variant_over_joint_view_test.cpp new file mode 100644 index 00000000..c57302cb --- /dev/null +++ b/src/boost/libs/variant/test/variant_over_joint_view_test.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2017 +// Mikhail Maximov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// The test is base on https://svn.boost.org/trac/boost/ticket/8554 +// variant was not able to extract types from mpl::joint_view + +#include <string> + +#include "boost/config.hpp" +#include "boost/core/lightweight_test.hpp" + +#include "boost/variant.hpp" +#include "boost/mpl/joint_view.hpp" +#include "boost/mpl/insert_range.hpp" +#include "boost/mpl/set.hpp" + +template<class T, class Variant> +void check_exception_on_get(Variant& v) { + try { + boost::get<T>(v); + BOOST_ERROR("Expected exception boost::bad_get, but got nothing."); + } catch (boost::bad_get&) { //okay it is expected behaviour + } catch (...) { BOOST_ERROR("Expected exception boost::bad_get, but got something else."); } +} + +void test_joint_view() { + typedef boost::variant<int> v1; + typedef boost::variant<std::string> v2; + typedef boost::make_variant_over<boost::mpl::joint_view<v1::types, v2::types>::type>::type v3; + + v1 a = 1; + v2 b = "2"; + v3 c = a; + BOOST_TEST(boost::get<int>(c) == 1); + BOOST_TEST(c.which() == 0); + v3 d = b; + BOOST_TEST(boost::get<std::string>(d) == "2"); + BOOST_TEST(d.which() == 1); + check_exception_on_get<std::string>(c); + check_exception_on_get<int>(d); +} + +void test_set() { + typedef boost::mpl::set2< std::string, int > types; + typedef boost::make_variant_over< types >::type v; + + v a = 1; + BOOST_TEST(boost::get<int>(a) == 1); + check_exception_on_get<std::string>(a); + a = "2"; + BOOST_TEST(boost::get<std::string>(a) == "2"); + check_exception_on_get<int>(a); +} + +int main() +{ + test_joint_view(); + test_set(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_polymorphic_get_test.cpp b/src/boost/libs/variant/test/variant_polymorphic_get_test.cpp new file mode 100644 index 00000000..e1afce6a --- /dev/null +++ b/src/boost/libs/variant/test/variant_polymorphic_get_test.cpp @@ -0,0 +1,81 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_plymorphic_get_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 Eric Friedman +// Copyright (c) 2013-2019 Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/variant/variant.hpp" +#include "boost/variant/apply_visitor.hpp" +#include "boost/variant/static_visitor.hpp" +#include "boost/variant/polymorphic_get.hpp" +#include "boost/core/lightweight_test.hpp" + +struct base {int trash;}; +struct derived1 : base{}; +struct derived2 : base{}; + +struct vbase { short trash; virtual ~vbase(){} virtual int foo() const { return 0; } }; +struct vderived1 : virtual vbase{ virtual int foo() const { return 1; } }; +struct vderived2 : virtual vbase{ virtual int foo() const { return 3; } }; +struct vderived3 : vderived1, vderived2 { virtual int foo() const { return 3; } }; + +template <class T, class Variant> +inline void check_throws(Variant& v) { + try { + boost::polymorphic_get<T>(v); + BOOST_TEST(false); + } catch (const boost::bad_polymorphic_get& e) { + BOOST_TEST(!!e.what()); + BOOST_TEST(std::string(e.what()) != boost::bad_get().what()); + } +} + +int main() +{ + typedef boost::variant<int, base, derived1, derived2> var_t; + + var_t var1; + BOOST_TEST(!boost::polymorphic_get<base>(&var1)); + check_throws<base>(var1); + BOOST_TEST(!boost::polymorphic_get<const base>(&var1)); + check_throws<base, const var_t>(var1); + + var1 = derived1(); + BOOST_TEST(boost::polymorphic_get<base>(&var1)); + BOOST_TEST(boost::polymorphic_get<const base>(&var1)); + + derived2 d; + d.trash = 777; + var_t var2 = d; + BOOST_TEST(boost::polymorphic_get<base>(var2).trash == 777); + BOOST_TEST(boost::polymorphic_get<const base>(var2).trash == 777); + + var2 = 777; + BOOST_TEST(!boost::polymorphic_get<base>(&var2)); + check_throws<base>(var2); + BOOST_TEST(!boost::polymorphic_get<const base>(&var2)); + check_throws<base, const var_t>(var2); + BOOST_TEST(boost::polymorphic_get<int>(var2) == 777); + BOOST_TEST(boost::polymorphic_get<const int>(var2) == 777); + + typedef boost::variant<int, vbase, vderived1, vderived2, vderived3> vvar_t; + + vvar_t v = vderived3(); + boost::polymorphic_get<vderived3>(v).trash = 777; + const vvar_t& cv = v; + BOOST_TEST(boost::polymorphic_get<vbase>(cv).trash == 777); + BOOST_TEST(boost::polymorphic_get<const vbase>(cv).trash == 777); + + BOOST_TEST(boost::polymorphic_get<vbase>(cv).foo() == 3); + BOOST_TEST(boost::polymorphic_get<vbase>(v).foo() == 3); + BOOST_TEST(boost::polymorphic_get<const vbase>(cv).foo() == 3); + BOOST_TEST(boost::polymorphic_get<const vbase>(v).foo() == 3); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_reference_test.cpp b/src/boost/libs/variant/test/variant_reference_test.cpp new file mode 100644 index 00000000..3f7f5812 --- /dev/null +++ b/src/boost/libs/variant/test/variant_reference_test.cpp @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_reference_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/variant.hpp" +#include "boost/core/lightweight_test.hpp" + +#include "boost/mpl/bool.hpp" +#include "boost/type_traits/add_reference.hpp" +#include "boost/type_traits/is_pointer.hpp" + +///// +// support types and functions + +struct base_t { }; +struct derived_t : base_t { }; + +template <typename Base, typename Derived> +bool check_base_derived(Base* b, Derived* d, long) +{ + return b == d; +} + +template <typename Base, typename Derived> +bool check_base_derived(Base& b, Derived& d, int) +{ + return &b == &d; +} + +template <typename T> + typename boost::add_reference<T>::type +wknd_get(boost::variant<T&>& var, long) +{ + return boost::get<T>(var); +} + +template <typename T> + typename boost::add_reference<T>::type +wknd_get(boost::variant<T>& var, int) +{ + return boost::get<T>(var); +} + +///// +// test functions + +template <typename T> +void test_reference_content(T& t, const T& value1, const T& value2) +{ + BOOST_TEST( !(value1 == value2) ); + + ///// + + boost::variant< T& > var(t); + BOOST_TEST(( boost::get<T>(&var) == &t )); + + t = value1; + BOOST_TEST(( boost::get<T>(var) == value1 )); + + ///// + + boost::variant< T > var2(var); + BOOST_TEST(( boost::get<T>(var2) == value1 )); + + t = value2; + BOOST_TEST(( boost::get<T>(var2) == value1 )); +} + +template <typename Base, typename Derived> +void base_derived_test(Derived d) +{ + Base b(d); + BOOST_TEST((check_base_derived( + b + , d + , 1L + ))); + + boost::variant<Base> base_var(d); + BOOST_TEST((check_base_derived( + wknd_get(base_var, 1L) + , d + , 1L + ))); + + boost::variant<Derived> derived_var(d); + boost::variant<Base> base_from_derived_var(derived_var); + BOOST_TEST((check_base_derived( + wknd_get(base_from_derived_var, 1L) + , wknd_get(derived_var, 1L) + , 1L + ))); +} + +int main() +{ + int i = 0; + test_reference_content(i, 1, 2); + + ///// + + derived_t d; + base_derived_test< int&,int >(i); + base_derived_test< base_t*,derived_t* >(&d); + base_derived_test< base_t&,derived_t& >(d); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_rvalue_get_with_ampersand_test.cpp b/src/boost/libs/variant/test/variant_rvalue_get_with_ampersand_test.cpp new file mode 100644 index 00000000..674412c8 --- /dev/null +++ b/src/boost/libs/variant/test/variant_rvalue_get_with_ampersand_test.cpp @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_get_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2017-2017 Albert Sverdlov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/variant/get.hpp" +#include "boost/variant/variant.hpp" +#include "boost/core/lightweight_test.hpp" + +#include <boost/move/move.hpp> +#include <boost/static_assert.hpp> + +#include <string> + +#define UNUSED(v) (void)(v) + +inline void run() +{ +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef boost::variant<int, std::string> var_t; + + std::string s = "abacaba"; + var_t v = s; + + // must spit an error at compile-time because of 'std::string&' + std::string new_s = boost::strict_get<std::string&>(boost::move(v)); + UNUSED(new_s); +#else + BOOST_STATIC_ASSERT_MSG(false, "Dummy compile-time error to pass the test on C++03"); +#endif +} + +int main() +{ + run(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant/test/variant_swap_test.cpp b/src/boost/libs/variant/test/variant_swap_test.cpp new file mode 100644 index 00000000..08e8e507 --- /dev/null +++ b/src/boost/libs/variant/test/variant_swap_test.cpp @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_swap_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2009 ArtVPS Ltd. +// Copyright (c) 2013-2019 Antony Polukhin. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/core/lightweight_test.hpp" +#include "boost/variant.hpp" + +#include <vector> +#include <algorithm> + +void run1() +{ + using boost::variant; + typedef variant< int, std::vector<int>* > t_var; + + std::vector<int> vec; + t_var v0(23), v1(&vec); + + BOOST_TEST(v0.which() == 0); + BOOST_TEST(v1.which() == 1); + + swap(v0, v1); + + BOOST_TEST(v0.which() == 1); + BOOST_TEST(v1.which() == 0); +} + +void run2() +{ + using boost::variant; + using std::swap; + typedef variant< std::vector<int>, std::vector<double> > t_var; + + std::vector<int> vec1; + std::vector<double> vec2; + t_var v0(vec1), v1(vec2); + + BOOST_TEST(v0.which() == 0); + BOOST_TEST(v1.which() == 1); + + swap(v0, v1); + + BOOST_TEST(v0.which() == 1); + BOOST_TEST(v1.which() == 0); + + v0.swap(v1); + + BOOST_TEST(v0.which() == 0); + BOOST_TEST(v1.which() == 1); +} + +void run3() +{ + using boost::variant; + using std::swap; + typedef variant< int, double > t_var; + + t_var v0(1), v1(2.0); + + BOOST_TEST(v0.which() == 0); + BOOST_TEST(v1.which() == 1); + + swap(v0, v1); + + BOOST_TEST(v0.which() == 1); + BOOST_TEST(v1.which() == 0); + + v0.swap(v1); + + BOOST_TEST(v0.which() == 0); + BOOST_TEST(v1.which() == 1); +} + +int main() +{ + run1(); + run2(); + run3(); + + return boost::report_errors(); +} + diff --git a/src/boost/libs/variant/test/variant_visit_internal_linkage.cpp b/src/boost/libs/variant/test/variant_visit_internal_linkage.cpp new file mode 100644 index 00000000..81afb8e5 --- /dev/null +++ b/src/boost/libs/variant/test/variant_visit_internal_linkage.cpp @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_visit_internal_linkage.cpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2018 Louis Dionne, Antony Polukhin +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This test checks that we can visit a variant containing a type that has +// internal linkage (anonymous namespace). + +#include "boost/variant/variant.hpp" + +#ifdef BOOST_NO_CXX14_DECLTYPE_AUTO + +void run() {} + +#else + +namespace { + struct Foo { }; + + struct Visitor { + void operator()(Foo const&) const { } + }; +} + +void run() { + boost::variant<Foo> v = Foo(); + boost::apply_visitor(Visitor(), v); +} + +#endif + +int main() { + run(); +} + diff --git a/src/boost/libs/variant/test/variant_visit_test.cpp b/src/boost/libs/variant/test/variant_visit_test.cpp new file mode 100644 index 00000000..3a8dd1b9 --- /dev/null +++ b/src/boost/libs/variant/test/variant_visit_test.cpp @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/variant_visit_test.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "boost/variant/variant.hpp" +#include "boost/variant/apply_visitor.hpp" +#include "boost/variant/static_visitor.hpp" +#include "boost/core/lightweight_test.hpp" + +#include "boost/mpl/bool.hpp" +#include "boost/mpl/and.hpp" +#include "boost/type_traits/is_same.hpp" + +struct udt1 +{ +}; + +struct udt2 +{ +}; + +template <typename T> +class unary_check_content_type + : public boost::static_visitor<bool> +{ +public: + + // not recommended design, but simplifies workarounds: + + template <typename U> + bool operator()(U&) const + { + return ::boost::is_same<T,U>::value; + } + +}; + +template <typename T1, typename T2> +class binary_check_content_type + : public boost::static_visitor<bool> +{ +public: + + // not recommended design, but simplifies workarounds: + + template <typename U1, typename U2> + bool operator()(U1&, U2&) const + { + return ::boost::mpl::and_< + boost::is_same<T1,U1> + , boost::is_same<T2,U2> + >::value; + } + +}; + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS // BOOST_NO_CXX11_RVALUE_REFERENCES is not enough for disabling buggy GCCs < 4.8 +struct rvalue_ref_visitor +{ + typedef int result_type; + int operator()(udt1&&) const { return 0; } + int operator()(udt2&&) const { return 1; } +}; +#endif +#ifdef BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE +struct rvalue_ref_decltype_visitor +{ + int operator()(udt1&&) const { return 0; } + int operator()(udt2&&) const { return 1; } +}; +#endif + +template <typename Checker, typename Variant> +inline void unary_test(Variant& var, Checker* = 0) +{ + Checker checker; + const Checker& const_checker = checker; + + // standard tests + + BOOST_TEST( boost::apply_visitor(checker, var) ); + BOOST_TEST( boost::apply_visitor(const_checker, var) ); + BOOST_TEST( boost::apply_visitor(Checker(), var) ); + + // delayed tests + + BOOST_TEST( boost::apply_visitor(checker)(var) ); + BOOST_TEST( boost::apply_visitor(const_checker)(var) ); +} + +template <typename Checker, typename Variant1, typename Variant2> +inline void binary_test(Variant1& var1, Variant2& var2, Checker* = 0) +{ + Checker checker; + const Checker& const_checker = checker; + + // standard tests + + BOOST_TEST( boost::apply_visitor(checker, var1, var2) ); + BOOST_TEST( boost::apply_visitor(const_checker, var1, var2) ); + BOOST_TEST( boost::apply_visitor(Checker(), var1, var2) ); + + // delayed tests + + BOOST_TEST( boost::apply_visitor(checker)(var1, var2) ); + BOOST_TEST( boost::apply_visitor(const_checker)(var1, var2) ); +} + +int main() +{ + typedef boost::variant<udt1,udt2> var_t; + udt1 u1; + var_t var1(u1); + udt2 u2; + var_t var2(u2); + + const var_t& cvar1 = var1; + const var_t& cvar2 = var2; + + // + // unary tests + // + + typedef unary_check_content_type<udt1> check1_t; + typedef unary_check_content_type<const udt1> check1_const_t; + typedef unary_check_content_type<udt2> check2_t; + typedef unary_check_content_type<const udt2> check2_const_t; + + unary_test< check1_t >(var1); + unary_test< check1_const_t >(cvar1); + + unary_test< check2_t >(var2); + unary_test< check2_const_t >(cvar2); + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS // BOOST_NO_CXX11_RVALUE_REFERENCES is not enough for disabling buggy GCCs < 4.8 + BOOST_TEST_EQ( (boost::apply_visitor( + rvalue_ref_visitor(), + boost::variant<udt1, udt2>(udt2()))), 1 ); +#endif +#ifdef BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE + BOOST_TEST_EQ( (boost::apply_visitor( + rvalue_ref_decltype_visitor(), + boost::variant<udt1, udt2>(udt2()))), 1 ); +#endif + + // + // binary tests + // + + typedef binary_check_content_type<udt1,udt2> check12_t; + typedef binary_check_content_type<const udt1, const udt2> check12_const_t; + typedef binary_check_content_type<udt2,udt1> check21_t; + typedef binary_check_content_type<const udt2, const udt1> check21_const_t; + + binary_test< check12_t >(var1,var2); + binary_test< check12_const_t >(cvar1,cvar2); + + binary_test< check21_t >(var2,var1); + binary_test< check21_const_t >(cvar2,cvar1); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/CMakeLists.txt b/src/boost/libs/variant2/CMakeLists.txt new file mode 100644 index 00000000..88ed21d9 --- /dev/null +++ b/src/boost/libs/variant2/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# http://www.boost.org/LICENSE_1_0.txt + +# Partial (add_subdirectory only) and experimental CMake support +# Subject to change; please do not rely on the contents of this file yet + +cmake_minimum_required(VERSION 3.5) + +project(BoostVariant2 LANGUAGES CXX) + +add_library(boost_variant2 INTERFACE) +add_library(Boost::variant2 ALIAS boost_variant2) + +target_include_directories(boost_variant2 INTERFACE include) + +target_link_libraries(boost_variant2 + INTERFACE + Boost::config + Boost::mp11 +) diff --git a/src/boost/libs/variant2/README.md b/src/boost/libs/variant2/README.md new file mode 100644 index 00000000..83a32fe2 --- /dev/null +++ b/src/boost/libs/variant2/README.md @@ -0,0 +1,21 @@ +# variant2 + +This repository contains a never-valueless, strong guarantee, C++11/14/17 +implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant). +See [the documentation](https://www.boost.org/libs/variant2) +for more information. + +The code requires [Boost.Mp11](https://github.com/boostorg/mp11) and +Boost.Config. + +The library is part of Boost, starting from release 1.71, but the header +`variant.hpp` will also work [standalone](https://godbolt.org/z/nVUNKX). + +Supported compilers: + +* g++ 4.8 or later with `-std=c++11` or above +* clang++ 3.5 or later with `-std=c++11` or above +* Visual Studio 2015, 2017, 2019 + +Tested on [Travis](https://travis-ci.org/boostorg/variant2/) and +[Appveyor](https://ci.appveyor.com/project/pdimov/variant2-fkab9). diff --git a/src/boost/libs/variant2/benchmark/benchmark1.cpp b/src/boost/libs/variant2/benchmark/benchmark1.cpp new file mode 100644 index 00000000..703f8911 --- /dev/null +++ b/src/boost/libs/variant2/benchmark/benchmark1.cpp @@ -0,0 +1,168 @@ +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(ONLY_V2) +# define NO_BV +# define NO_SV +#endif + +#if defined(ONLY_BV) +# define NO_V2 +# define NO_SV +#endif + +#if defined(ONLY_SV) +# define NO_V2 +# define NO_BV +#endif + +#if !defined(NO_V2) +#include <boost/variant2/variant.hpp> +#endif + +#if !defined(NO_BV) +#include <boost/variant.hpp> +#endif + +#if !defined(NO_SV) +#include <variant> +#endif + +#include <type_traits> +#include <chrono> +#include <iostream> +#include <iomanip> +#include <vector> +#include <map> +#include <string> +#include <stdexcept> + +template<class T> struct is_numeric: std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value> +{ +}; + +template<class T, class U> struct have_addition: std::integral_constant<bool, is_numeric<T>::value && is_numeric<U>::value> +{ +}; + +template<class T, class U, class E = std::enable_if_t<have_addition<T, U>::value>> auto add( T const& t, U const& u ) +{ + return t + u; +} + +template<class T, class U, class E = std::enable_if_t<!have_addition<T, U>::value>> double add( T const& /*t*/, U const& /*u*/ ) +{ + throw std::logic_error( "Invalid addition" ); +} + +inline double to_double( double const& v ) +{ + return v; +} + +#if !defined(NO_V2) + +template<class... T> boost::variant2::variant<T...> operator+( boost::variant2::variant<T...> const& v1, boost::variant2::variant<T...> const& v2 ) +{ + return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant<T...> { return add( x1, x2 ); }, v1, v2 ); +} + +template<class... T> double to_double( boost::variant2::variant<T...> const& v ) +{ + return boost::variant2::get<double>( v ); +} + +#endif + +#if !defined(NO_BV) + +template<class... T> boost::variant<T...> operator+( boost::variant<T...> const& v1, boost::variant<T...> const& v2 ) +{ + return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant<T...> { return add( x1, x2 ); }, v1, v2 ); +} + +template<class... T> double to_double( boost::variant<T...> const& v ) +{ + return boost::get<double>( v ); +} + +#endif + +#if !defined(NO_SV) + +template<class... T> std::variant<T...> operator+( std::variant<T...> const& v1, std::variant<T...> const& v2 ) +{ + return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant<T...> { return add( x1, x2 ); }, v1, v2 ); +} + +template<class... T> double to_double( std::variant<T...> const& v ) +{ + return std::get<double>( v ); +} + +#endif + +template<class V> void test_( long long N ) +{ + std::vector<V> w; + // lack of reserve is deliberate + + auto tp1 = std::chrono::high_resolution_clock::now(); + + for( long long i = 0; i < N; ++i ) + { + V v; + + if( i % 7 == 0 ) + { + v = i / 7; + } + else + { + v = i / 7.0; + } + + w.push_back( v ); + } + + V s = 0.0; + + for( long long i = 0; i < N; ++i ) + { + s = s + w[ i ]; + } + + auto tp2 = std::chrono::high_resolution_clock::now(); + + std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n"; +} + +template<class... T> void test( long long N ) +{ + std::cout << "N=" << N << ":\n"; + + std::cout << " double: "; test_<double>( N ); +#if !defined(NO_V2) + std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N ); +#endif +#if !defined(NO_BV) + std::cout << "boost::variant: "; test_<boost::variant<T...>>( N ); +#endif +#if !defined(NO_SV) + std::cout << " std::variant: "; test_<std::variant<T...>>( N ); +#endif + + std::cout << '\n'; +} + +int main() +{ + long long const N = 100'000'000LL; + + test<long long, double>( N ); + test<std::nullptr_t, long long, double, std::string, std::vector<std::string>, std::map<std::string, std::string>>( N ); +} diff --git a/src/boost/libs/variant2/benchmark/benchmark1.md b/src/boost/libs/variant2/benchmark/benchmark1.md new file mode 100644 index 00000000..aa3bb933 --- /dev/null +++ b/src/boost/libs/variant2/benchmark/benchmark1.md @@ -0,0 +1,267 @@ +# benchmark1.cpp results + +## VS 2017 15.9.7 64 bit (cl.exe 19.16, /EHsc /std:c++17) + +### /Od + +#### Compile time + +``` + variant2 (-DONLY_V2): 1837 ms +boost::variant (-DONLY_BV): 2627 ms + std::variant (-DONLY_SV): 1425 ms +``` + +#### Run time + +``` +N=100000000: + double: 9041 ms; S=7.14286e+14 + variant2: 48367 ms; S=7.14286e+14 +boost::variant: 102776 ms; S=7.14286e+14 + std::variant: 40590 ms; S=7.14286e+14 + +N=100000000: + double: 9029 ms; S=7.14286e+14 + variant2: 92962 ms; S=7.14286e+14 +boost::variant: 110441 ms; S=7.14286e+14 + std::variant: 92974 ms; S=7.14286e+14 +``` + +### /O2 /DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 2571 ms +boost::variant (-DONLY_BV): 3335 ms + std::variant (-DONLY_SV): 1903 ms +``` + +#### Run time + +``` +N=100000000: + double: 1949 ms; S=7.14286e+14 + variant2: 4176 ms; S=7.14286e+14 +boost::variant: 11312 ms; S=7.14286e+14 + std::variant: 4617 ms; S=7.14286e+14 + +N=100000000: + double: 1949 ms; S=7.14286e+14 + variant2: 11807 ms; S=7.14286e+14 +boost::variant: 15632 ms; S=7.14286e+14 + std::variant: 10725 ms; S=7.14286e+14 +``` + +## g++ 7.4.0 -std=c++17 (Cygwin 64 bit) + +### -O0 + +#### Compile time + +``` + variant2 (-DONLY_V2): 2734 ms +boost::variant (-DONLY_BV): 4308 ms + std::variant (-DONLY_SV): 2298 ms +``` + +#### Run time + +``` +N=100000000: + double: 3620 ms; S=7.14286e+14 + variant2: 29214 ms; S=7.14286e+14 +boost::variant: 88492 ms; S=7.14286e+14 + std::variant: 39510 ms; S=7.14286e+14 + +N=100000000: + double: 3642 ms; S=7.14286e+14 + variant2: 75822 ms; S=7.14286e+14 +boost::variant: 96680 ms; S=7.14286e+14 + std::variant: 66411 ms; S=7.14286e+14 +``` + +### -O1 + +#### Compile time + +``` + variant2 (-DONLY_V2): 2103 ms +boost::variant (-DONLY_BV): 3398 ms + std::variant (-DONLY_SV): 1841 ms +``` + +#### Run time + +``` +N=100000000: + double: 1576 ms; S=7.14286e+14 + variant2: 3424 ms; S=7.14286e+14 +boost::variant: 4356 ms; S=7.14286e+14 + std::variant: 3764 ms; S=7.14286e+14 + +N=100000000: + double: 1582 ms; S=7.14286e+14 + variant2: 9062 ms; S=7.14286e+14 +boost::variant: 9603 ms; S=7.14286e+14 + std::variant: 8825 ms; S=7.14286e+14 +``` + +### -O2 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 2276 ms +boost::variant (-DONLY_BV): 3647 ms + std::variant (-DONLY_SV): 2111 ms +``` + +#### Run time + +``` +N=100000000: + double: 1643 ms; S=7.14286e+14 + variant2: 3070 ms; S=7.14286e+14 +boost::variant: 3385 ms; S=7.14286e+14 + std::variant: 3880 ms; S=7.14286e+14 + +N=100000000: + double: 1622 ms; S=7.14286e+14 + variant2: 8101 ms; S=7.14286e+14 +boost::variant: 8611 ms; S=7.14286e+14 + std::variant: 8694 ms; S=7.14286e+14 +``` + +### -O3 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 2390 ms +boost::variant (-DONLY_BV): 3768 ms + std::variant (-DONLY_SV): 2094 ms +``` + +#### Run time + +``` +N=100000000: + double: 1611 ms; S=7.14286e+14 + variant2: 2975 ms; S=7.14286e+14 +boost::variant: 3232 ms; S=7.14286e+14 + std::variant: 3726 ms; S=7.14286e+14 + +N=100000000: + double: 1603 ms; S=7.14286e+14 + variant2: 8157 ms; S=7.14286e+14 +boost::variant: 8419 ms; S=7.14286e+14 + std::variant: 8659 ms; S=7.14286e+14 +``` + +## clang++ 5.0.1 -std=c++17 -stdlib=libc++ (Cygwin 64 bit) + +### -O0 + +#### Compile time + +``` + variant2 (-DONLY_V2): 2190 ms +boost::variant (-DONLY_BV): 3537 ms + std::variant (-DONLY_SV): 2151 ms +``` + +#### Run time + +``` +N=100000000: + double: 6063 ms; S=7.14286e+14 + variant2: 23616 ms; S=7.14286e+14 +boost::variant: 92730 ms; S=7.14286e+14 + std::variant: 23160 ms; S=7.14286e+14 + +N=100000000: + double: 6054 ms; S=7.14286e+14 + variant2: 52738 ms; S=7.14286e+14 +boost::variant: 96896 ms; S=7.14286e+14 + std::variant: 72595 ms; S=7.14286e+14 +``` + +### -O1 + +#### Compile time + +``` + variant2 (-DONLY_V2): 2722 ms +boost::variant (-DONLY_BV): 4337 ms + std::variant (-DONLY_SV): 2697 ms +``` + +#### Run time + +``` +N=100000000: + double: 2171 ms; S=7.14286e+14 + variant2: 9280 ms; S=7.14286e+14 +boost::variant: 51478 ms; S=7.14286e+14 + std::variant: 5642 ms; S=7.14286e+14 + +N=100000000: + double: 2171 ms; S=7.14286e+14 + variant2: 22166 ms; S=7.14286e+14 +boost::variant: 54084 ms; S=7.14286e+14 + std::variant: 14330 ms; S=7.14286e+14 +``` + +### -O2 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 2499 ms +boost::variant (-DONLY_BV): 3826 ms + std::variant (-DONLY_SV): 2645 ms +``` + +#### Run time + +``` +N=100000000: + double: 1604 ms; S=7.14286e+14 + variant2: 2726 ms; S=7.14286e+14 +boost::variant: 6662 ms; S=7.14286e+14 + std::variant: 3869 ms; S=7.14286e+14 + +N=100000000: + double: 1598 ms; S=7.14286e+14 + variant2: 8136 ms; S=7.14286e+14 +boost::variant: 9236 ms; S=7.14286e+14 + std::variant: 6279 ms; S=7.14286e+14 +``` + +### -O3 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 2509 ms +boost::variant (-DONLY_BV): 3845 ms + std::variant (-DONLY_SV): 2638 ms +``` + +#### Run time + +``` +N=100000000: + double: 1592 ms; S=7.14286e+14 + variant2: 2697 ms; S=7.14286e+14 +boost::variant: 6648 ms; S=7.14286e+14 + std::variant: 3826 ms; S=7.14286e+14 + +N=100000000: + double: 1614 ms; S=7.14286e+14 + variant2: 8035 ms; S=7.14286e+14 +boost::variant: 9221 ms; S=7.14286e+14 + std::variant: 6319 ms; S=7.14286e+14 +``` diff --git a/src/boost/libs/variant2/benchmark/benchmark2.cpp b/src/boost/libs/variant2/benchmark/benchmark2.cpp new file mode 100644 index 00000000..bea5f3a9 --- /dev/null +++ b/src/boost/libs/variant2/benchmark/benchmark2.cpp @@ -0,0 +1,149 @@ +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(ONLY_V2) +# define NO_BV +# define NO_SV +#endif + +#if defined(ONLY_BV) +# define NO_V2 +# define NO_SV +#endif + +#if defined(ONLY_SV) +# define NO_V2 +# define NO_BV +#endif + +#if !defined(NO_V2) +#include <boost/variant2/variant.hpp> +#endif + +#if !defined(NO_BV) +#include <boost/variant.hpp> +#endif + +#if !defined(NO_SV) +#include <variant> +#endif + +#include <type_traits> +#include <chrono> +#include <iostream> +#include <iomanip> +#include <vector> + +struct prefix +{ + int v_; +}; + +struct X1: prefix {}; +struct X2: prefix {}; +struct X3: prefix {}; +struct X4: prefix {}; +struct X5: prefix {}; +struct X6: prefix {}; +struct X7: prefix {}; +struct X8: prefix {}; +struct X9: prefix {}; +struct X10: prefix {}; +struct X11: prefix {}; +struct X12: prefix {}; + +inline int get_value( prefix const& v ) +{ + return v.v_; +} + +#if !defined(NO_V2) + +template<class... T> int get_value( boost::variant2::variant<T...> const& v ) +{ + return visit( []( prefix const& x ) { return x.v_; }, v ); +} + +#endif + +#if !defined(NO_BV) + +template<class... T> int get_value( boost::variant<T...> const& v ) +{ + return boost::apply_visitor( []( prefix const& x ) { return x.v_; }, v ); +} + +#endif + +#if !defined(NO_SV) + +template<class... T> int get_value( std::variant<T...> const& v ) +{ + return visit( []( prefix const& x ) { return x.v_; }, v ); +} + +#endif + +template<class V> void test_( int N ) +{ + std::vector<V> w; + // lack of reserve is deliberate + + auto tp1 = std::chrono::high_resolution_clock::now(); + + for( int i = 0; i < N / 12; ++i ) + { + w.push_back( X1{ i } ); + w.push_back( X2{ i } ); + w.push_back( X3{ i } ); + w.push_back( X4{ i } ); + w.push_back( X5{ i } ); + w.push_back( X6{ i } ); + w.push_back( X7{ i } ); + w.push_back( X8{ i } ); + w.push_back( X9{ i } ); + w.push_back( X10{ i } ); + w.push_back( X11{ i } ); + w.push_back( X12{ i } ); + } + + unsigned long long s = 0; + + for( std::size_t i = 0, n = w.size(); i < n; ++i ) + { + s = s + get_value( w[ i ] ); + } + + auto tp2 = std::chrono::high_resolution_clock::now(); + + std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << s << "\n"; +} + +template<class... T> void test( int N ) +{ + std::cout << "N=" << N << ":\n"; + + std::cout << " prefix: "; test_<prefix>( N ); +#if !defined(NO_V2) + std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N ); +#endif +#if !defined(NO_BV) + std::cout << "boost::variant: "; test_<boost::variant<T...>>( N ); +#endif +#if !defined(NO_SV) + std::cout << " std::variant: "; test_<std::variant<T...>>( N ); +#endif + + std::cout << '\n'; +} + +int main() +{ + int const N = 100'000'000; + + test<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12>( N ); +} diff --git a/src/boost/libs/variant2/benchmark/benchmark2.md b/src/boost/libs/variant2/benchmark/benchmark2.md new file mode 100644 index 00000000..9aad6488 --- /dev/null +++ b/src/boost/libs/variant2/benchmark/benchmark2.md @@ -0,0 +1,207 @@ +# benchmark2.cpp results + +## VS 2017 15.9.7 64 bit (cl.exe 19.16, /EHsc /std:c++17) + +### /Od + +#### Compile time + +``` + variant2 (-DONLY_V2): 1403 ms +boost::variant (-DONLY_BV): 2972 ms + std::variant (-DONLY_SV): 1057 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 7016 ms; S=416666583333336 + variant2: 24723 ms; S=416666583333336 +boost::variant: 60438 ms; S=416666583333336 + std::variant: 20707 ms; S=416666583333336 +``` + +### /O2 /DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 1778 ms +boost::variant (-DONLY_BV): 3252 ms + std::variant (-DONLY_SV): 1372 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 803 ms; S=416666583333336 + variant2: 2124 ms; S=416666583333336 +boost::variant: 6191 ms; S=416666583333336 + std::variant: 2193 ms; S=416666583333336 +``` + +## g++ 7.4.0 -std=c++17 (Cygwin 64 bit) + +### -O0 + +#### Compile time + +``` + variant2 (-DONLY_V2): 1739 ms +boost::variant (-DONLY_BV): 3113 ms + std::variant (-DONLY_SV): 1719 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 5163 ms; S=416666583333336 + variant2: 20628 ms; S=416666583333336 +boost::variant: 43308 ms; S=416666583333336 + std::variant: 42375 ms; S=416666583333336 +``` + +### -O1 + +#### Compile time + +``` + variant2 (-DONLY_V2): 1484 ms +boost::variant (-DONLY_BV): 2947 ms + std::variant (-DONLY_SV): 1448 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 781 ms; S=416666583333336 + variant2: 1992 ms; S=416666583333336 +boost::variant: 2249 ms; S=416666583333336 + std::variant: 4843 ms; S=416666583333336 +``` + +### -O2 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 1547 ms +boost::variant (-DONLY_BV): 2999 ms + std::variant (-DONLY_SV): 1528 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 793 ms; S=416666583333336 + variant2: 1686 ms; S=416666583333336 +boost::variant: 1833 ms; S=416666583333336 + std::variant: 4340 ms; S=416666583333336 +``` + +### -O3 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 1595 ms +boost::variant (-DONLY_BV): 3084 ms + std::variant (-DONLY_SV): 1620 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 853 ms; S=416666583333336 + variant2: 1681 ms; S=416666583333336 +boost::variant: 1773 ms; S=416666583333336 + std::variant: 3989 ms; S=416666583333336 +``` + +## clang++ 5.0.1 -std=c++17 -stdlib=libc++ (Cygwin 64 bit) + +### -O0 + +#### Compile time + +``` + variant2 (-DONLY_V2): 1578 ms +boost::variant (-DONLY_BV): 2623 ms + std::variant (-DONLY_SV): 1508 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 4447 ms; S=416666583333336 + variant2: 16016 ms; S=416666583333336 +boost::variant: 42365 ms; S=416666583333336 + std::variant: 17817 ms; S=416666583333336 +``` + +### -O1 + +#### Compile time + +``` + variant2 (-DONLY_V2): 1841 ms +boost::variant (-DONLY_BV): 2919 ms + std::variant (-DONLY_SV): 1776 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 1390 ms; S=416666583333336 + variant2: 5397 ms; S=416666583333336 +boost::variant: 23234 ms; S=416666583333336 + std::variant: 2807 ms; S=416666583333336 +``` + +### -O2 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 1766 ms +boost::variant (-DONLY_BV): 2817 ms + std::variant (-DONLY_SV): 1718 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 604 ms; S=416666583333336 + variant2: 1625 ms; S=416666583333336 +boost::variant: 2735 ms; S=416666583333336 + std::variant: 2664 ms; S=416666583333336 +``` + +### -O3 -DNDEBUG + +#### Compile time + +``` + variant2 (-DONLY_V2): 1720 ms +boost::variant (-DONLY_BV): 2806 ms + std::variant (-DONLY_SV): 1737 ms +``` + +#### Run time + +``` +N=100000000: + prefix: 603 ms; S=416666583333336 + variant2: 1608 ms; S=416666583333336 +boost::variant: 2696 ms; S=416666583333336 + std::variant: 2668 ms; S=416666583333336 +``` diff --git a/src/boost/libs/variant2/index.html b/src/boost/libs/variant2/index.html new file mode 100644 index 00000000..ce8b2263 --- /dev/null +++ b/src/boost/libs/variant2/index.html @@ -0,0 +1,15 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=doc/html/variant2.html"> +</head> +<body> +Automatic redirection failed, please go to +<a href="doc/html/variant2.html">doc/html/variant2.html</a>. +</body> +</html> +<!-- + Copyright Beman Dawes, 2001 + Distributed under the Boost Software License, Version 1.0. + See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt +--> diff --git a/src/boost/libs/variant2/meta/libraries.json b/src/boost/libs/variant2/meta/libraries.json new file mode 100644 index 00000000..7d9337ec --- /dev/null +++ b/src/boost/libs/variant2/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "variant2", + "name": "Variant2", + "authors": [ + "Peter Dimov" + ], + "maintainers": [ + "Peter Dimov <pdimov -at- pdimov.com>" + ], + "description": "A never-valueless, strong guarantee implementation of std::variant.", + "category": [ + "Containers", "Data" + ] +} diff --git a/src/boost/libs/variant2/test/Jamfile b/src/boost/libs/variant2/test/Jamfile new file mode 100644 index 00000000..1093712d --- /dev/null +++ b/src/boost/libs/variant2/test/Jamfile @@ -0,0 +1,105 @@ +# Boost.Variant2 Library Test Jamfile +# +# Copyright 2015-2019 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt + +import testing ; +import ../../config/checks/config : requires ; + +project + : default-build + + <warnings>all + + : requirements + + [ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_constexpr ] + + <toolset>msvc:<warnings-as-errors>on + <toolset>gcc:<warnings-as-errors>on + <toolset>clang:<warnings-as-errors>on + ; + +run variant_size.cpp ; +run variant_alternative.cpp ; + +run variant_holds_alternative.cpp ; +compile variant_holds_alternative_cx.cpp ; + +run variant_get_by_index.cpp ; +compile variant_get_by_index_cx.cpp ; + +run variant_get_by_type.cpp ; +compile variant_get_by_type_cx.cpp ; + +run variant_default_construct.cpp ; +compile variant_default_construct_cx.cpp ; + +run variant_copy_construct.cpp ; +compile variant_copy_construct_cx.cpp : <toolset>msvc-14.0:<build>no ; + +run variant_move_construct.cpp ; +compile variant_move_construct_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_value_construct.cpp ; +compile variant_value_construct_cx.cpp ; + +run variant_in_place_index_construct.cpp ; +compile variant_in_place_index_construct_cx.cpp ; + +run variant_in_place_type_construct.cpp ; +compile variant_in_place_type_construct_cx.cpp ; + +run variant_copy_assign.cpp ; +compile variant_copy_assign_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_move_assign.cpp ; +compile variant_move_assign_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_value_assign.cpp ; +compile variant_value_assign_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_emplace_index.cpp ; +compile variant_emplace_index_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_emplace_type.cpp ; +compile variant_emplace_type_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_swap.cpp ; + +run variant_eq_ne.cpp ; +compile variant_eq_ne_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_lt_gt.cpp ; +compile variant_lt_gt_cx.cpp : [ requires cxx14_constexpr ] ; + +run variant_destroy.cpp ; +run variant_visit.cpp ; + +run variant_convert_construct.cpp ; +run variant_subset.cpp ; +run variant_valueless.cpp ; + +run variant_copy_construct_throw.cpp ; +run variant_move_construct_throw.cpp ; +run variant_convert_construct_throw.cpp ; + +run variant_copy_assign_throw.cpp ; +run variant_move_assign_throw.cpp ; + +local NX = + <exception-handling>off + <toolset>msvc:<cxxflags>/wd4530 + <toolset>msvc:<cxxflags>/wd4577 + ; + +run variant_get_by_index.cpp throw_exception.cpp : : : $(NX) : variant_get_by_index_nx ; +compile variant_get_by_index_cx.cpp : $(NX) : variant_get_by_index_cx_nx ; + +run variant_get_by_type.cpp throw_exception.cpp : : : $(NX) : variant_get_by_type_nx ; +compile variant_get_by_type_cx.cpp : $(NX) : variant_get_by_type_cx_nx ; + +run variant_subset.cpp throw_exception.cpp : : : $(NX) : variant_subset_nx ; diff --git a/src/boost/libs/variant2/test/cmake_subdir_test/CMakeLists.txt b/src/boost/libs/variant2/test/cmake_subdir_test/CMakeLists.txt new file mode 100644 index 00000000..90fd0144 --- /dev/null +++ b/src/boost/libs/variant2/test/cmake_subdir_test/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright 2018, 2019 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5) + +project(cmake_subdir_test LANGUAGES CXX) + +add_subdirectory(../.. boostorg/variant2) +add_subdirectory(../../../config boostorg/config) +add_subdirectory(../../../mp11 boostorg/mp11) + +add_executable(quick quick.cpp) +target_link_libraries(quick Boost::variant2) + +enable_testing() +add_test(quick quick) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>) diff --git a/src/boost/libs/variant2/test/cmake_subdir_test/quick.cpp b/src/boost/libs/variant2/test/cmake_subdir_test/quick.cpp new file mode 100644 index 00000000..789d0e70 --- /dev/null +++ b/src/boost/libs/variant2/test/cmake_subdir_test/quick.cpp @@ -0,0 +1,15 @@ + +// Copyright 2019 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +int main() +{ + variant<float, int> v( 2 ); + return get<1>( v ) == 2? 0: 1; +} diff --git a/src/boost/libs/variant2/test/throw_exception.cpp b/src/boost/libs/variant2/test/throw_exception.cpp new file mode 100644 index 00000000..9eaccc11 --- /dev/null +++ b/src/boost/libs/variant2/test/throw_exception.cpp @@ -0,0 +1,20 @@ + +// Copyright 2019 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/config.hpp> +#include <exception> +#include <cstdio> + +namespace boost +{ + +void throw_exception( std::exception const & e ) +{ + std::fprintf( stderr, "Exception: %s\n", e.what() ); + std::terminate(); +} + +} // namespace boost diff --git a/src/boost/libs/variant2/test/variant_alternative.cpp b/src/boost/libs/variant2/test/variant_alternative.cpp new file mode 100644 index 00000000..600c26c9 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_alternative.cpp @@ -0,0 +1,154 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/mp11.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <cstddef> + +using namespace boost::variant2; +using namespace boost::mp11; + +template<class I, class T> using var_alt_t = variant_alternative_t<I::value, T>; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void>>, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void> const>, void const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void> volatile>, void volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void> const volatile>, void const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char>&>, char&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char> const&>, char const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char>&&>, char&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char> const&&>, char const&&>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int>>, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> const>, void const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> volatile>, void volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> const volatile>, void const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int>&>, char&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int> const&>, char const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int>&&>, char&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int> const&&>, char const&&>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>>, int>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const>, int const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> volatile>, int volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const volatile>, int const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>&>, int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const&>, int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>&&>, int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const&&>, int const&&>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float>>, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> const>, void const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> volatile>, void volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> const volatile>, void const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float>&>, char&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float> const&>, char const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float>&&>, char&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float> const&&>, char const&&>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>>, int>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const>, int const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> volatile>, int volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const volatile>, int const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>&>, int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const&>, int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>&&>, int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const&&>, int const&&>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>>, float>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const>, float const>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> volatile>, float volatile>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const volatile>, float const volatile>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>&>, float&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const&>, float const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>&&>, float&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const&&>, float const&&>)); + + variant_alternative<0, void>(); + variant_alternative<0, void const>(); + variant_alternative<0, void volatile>(); + variant_alternative<0, void const volatile>(); + + variant_alternative<0, int&>(); + variant_alternative<0, int const&>(); + variant_alternative<0, int&&>(); + variant_alternative<0, int const&&>(); + + variant_alternative<0, variant<>>(); + variant_alternative<0, variant<> const>(); + variant_alternative<0, variant<> volatile>(); + variant_alternative<0, variant<> const volatile>(); + + variant_alternative<0, variant<>&>(); + variant_alternative<0, variant<> const&>(); + variant_alternative<0, variant<>&&>(); + variant_alternative<0, variant<> const&&>(); + + variant_alternative<1, variant<int>>(); + variant_alternative<1, variant<int> const>(); + variant_alternative<1, variant<int> volatile>(); + variant_alternative<1, variant<int> const volatile>(); + + variant_alternative<1, variant<int>&>(); + variant_alternative<1, variant<int> const&>(); + variant_alternative<1, variant<int>&&>(); + variant_alternative<1, variant<int> const&&>(); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void const>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void volatile>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void const volatile>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int const&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int&&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int const&&>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> volatile>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const volatile>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>&&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const&&>)); + + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> volatile>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const volatile>)); + + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>&&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const&&>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> volatile>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const volatile>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>&&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const&&>)); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_convert_construct.cpp b/src/boost/libs/variant2/test/variant_convert_construct.cpp new file mode 100644 index 00000000..dbf61d90 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_convert_construct.cpp @@ -0,0 +1,175 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +int main() +{ + { + variant<int> v( 1 ); + + variant<int, float> v2( v ); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v ), get<int>( v2 ) ); + + variant<int, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + } + + { + variant<int> const v( 1 ); + + variant<int, float> v2( v ); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v ), get<int>( v2 ) ); + + variant<int, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + } + + { + variant<int const> v( 1 ); + + variant<int const, float> v2( v ); + + BOOST_TEST( holds_alternative<int const>( v2 ) ); + BOOST_TEST_EQ( get<int const>( v ), get<int const>( v2 ) ); + + variant<int const, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<int const>( v3 ) ); + BOOST_TEST_EQ( get<int const>( v2 ), get<int const>( v3 ) ); + } + + { + variant<int const> const v( 1 ); + + variant<int const, float> v2( v ); + + BOOST_TEST( holds_alternative<int const>( v2 ) ); + BOOST_TEST_EQ( get<int const>( v ), get<int const>( v2 ) ); + + variant<int const, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<int const>( v3 ) ); + BOOST_TEST_EQ( get<int const>( v2 ), get<int const>( v3 ) ); + } + + { + variant<float> v( 3.14f ); + + variant<int, float> v2( v ); + + BOOST_TEST( holds_alternative<float>( v2 ) ); + BOOST_TEST_EQ( get<float>( v ), get<float>( v2 ) ); + + variant<int, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<float>( v3 ) ); + BOOST_TEST_EQ( get<float>( v2 ), get<float>( v3 ) ); + } + + { + variant<float> v( 3.15f ); + + variant<int, int, float> v2( v ); + + BOOST_TEST( holds_alternative<float>( v2 ) ); + BOOST_TEST_EQ( get<float>( v ), get<float>( v2 ) ); + + variant<int, int, float> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<float>( v3 ) ); + BOOST_TEST_EQ( get<float>( v2 ), get<float>( v3 ) ); + } + + { + variant<float, std::string> v( "s1" ); + + variant<int, int, float, std::string> v2( v ); + + BOOST_TEST( holds_alternative<std::string>( v2 ) ); + BOOST_TEST_EQ( get<std::string>( v ), get<std::string>( v2 ) ); + + variant<int, int, float, std::string> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<std::string>( v3 ) ); + BOOST_TEST_EQ( get<std::string>( v2 ), get<std::string>( v3 ) ); + } + + { + variant<X1, X2> v{ X1{1} }; + + variant<int, int, float, float, X1, X2> v2( v ); + + BOOST_TEST( holds_alternative<X1>( v2 ) ); + BOOST_TEST_EQ( get<X1>( v ).v, get<X1>( v2 ).v ); + + variant<int, int, float, float, X1, X2> v3( std::move(v) ); + + BOOST_TEST( holds_alternative<X1>( v3 ) ); + BOOST_TEST_EQ( get<X1>( v2 ).v, get<X1>( v3 ).v ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_convert_construct_throw.cpp b/src/boost/libs/variant2/test/variant_convert_construct_throw.cpp new file mode 100644 index 00000000..bb53d7ce --- /dev/null +++ b/src/boost/libs/variant2/test/variant_convert_construct_throw.cpp @@ -0,0 +1,95 @@ + +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <stdexcept> + +using namespace boost::variant2; + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + X( X const& ) + { + throw std::runtime_error( "X(X const&)" ); + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +void test_copy() +{ + X::instances = 0; + + { + variant<X> v1; + + BOOST_TEST_EQ( X::instances, 1 ); + + try + { + variant<X, int, float> v2( v1 ); + BOOST_TEST_EQ( X::instances, 2 ); + } + catch( std::exception const& ) + { + } + + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); +} + +void test_move() +{ + X::instances = 0; + + { + variant<X> v1; + + BOOST_TEST_EQ( X::instances, 1 ); + + try + { + variant<X, int, float> v2( std::move( v1 ) ); + BOOST_TEST_EQ( X::instances, 2 ); + } + catch( std::exception const& ) + { + } + + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); +} + +int main() +{ + test_copy(); + test_move(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_copy_assign.cpp b/src/boost/libs/variant2/test/variant_copy_assign.cpp new file mode 100644 index 00000000..c8ed44f7 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_assign.cpp @@ -0,0 +1,194 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +struct Y +{ + Y& operator=( Y const& ) = delete; +}; + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int> v2( 1 ); + + v = v2; + BOOST_TEST_EQ( get<0>(v), 1 ); + + variant<int> const v3( 2 ); + + v = v3; + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int, float> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, float> v2( 1 ); + + v = v2; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + variant<int, float> v3( 3.14f ); + + v = v3; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + variant<int, float> const v4( 3.15f ); + + v = v4; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.15f ); + } + + { + variant<int, int, float, std::string> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, int, float, std::string> v2( in_place_index_t<1>{}, 1 ); + + v = v2; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 1 ); + + variant<int, int, float, std::string> v3( 3.14f ); + + v = v3; + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + variant<int, int, float, std::string> const v4( 3.15f ); + + v = v4; + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.15f ); + + variant<int, int, float, std::string> v5( "s1" ); + + v = v5; + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + variant<int, int, float, std::string> const v6( "s2" ); + + v = v6; + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + } + + { + variant<X1, X2> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + variant<X1, X2> v2( X1{1} ); + + v = v2; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + variant<X1, X2> v3( in_place_index_t<1>{}, 2 ); + + v = v3; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + variant<X1, X2> const v4( in_place_index_t<1>{}, 3 ); + + v = v4; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 3 ); + + variant<X1, X2> const v5( in_place_index_t<0>{}, 4 ); + + v = v5; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + } + + { + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable<variant<int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable<variant<int, int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable<variant<int, float>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_assignable<variant<int, int, float, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<X1, int>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<X1, int, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<int, X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<int, int, X1>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_assignable<variant<X1, X2, int, int>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_copy_assignable<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_copy_assignable<variant<int const>>)); + BOOST_TEST_TRAIT_FALSE((std::is_copy_assignable<variant<int, float, Y>>)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_copy_assign_cx.cpp b/src/boost/libs/variant2/test/variant_copy_assign_cx.cpp new file mode 100644 index 00000000..8be25794 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_assign_cx.cpp @@ -0,0 +1,116 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class V, class T, class A> constexpr T test( A const& a ) +{ + V v; + + v = a; + + return get<T>(v); +} + +int main() +{ + { + constexpr variant<int> v( 1 ); + constexpr auto w = test<variant<int>, int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<X> v( 1 ); + constexpr auto w = test<variant<X>, X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant<Y> v( 1 ); + constexpr auto w = test<variant<Y>, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr variant<int, float> v( 1 ); + constexpr auto w = test<variant<int, float>, int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, float> v( 3.0f ); + constexpr auto w = test<variant<int, float>, float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant<int, int, float> v( 3.0f ); + constexpr auto w = test<variant<int, int, float>, float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant<E, E, X> v( 1 ); + constexpr auto w = test<variant<E, E, X>, X>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, int, float, float, X> v( X(1) ); + constexpr auto w = test<variant<int, int, float, float, X>, X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant<E, E, Y> v( 1 ); + constexpr auto w = test<variant<E, E, Y>, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, int, float, float, Y> v( Y(1) ); + constexpr auto w = test<variant<int, int, float, float, Y>, Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_copy_assign_throw.cpp b/src/boost/libs/variant2/test/variant_copy_assign_throw.cpp new file mode 100644 index 00000000..a13dccbe --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_assign_throw.cpp @@ -0,0 +1,55 @@ + +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <stdexcept> + +using namespace boost::variant2; + +struct Y1 +{ + Y1() noexcept {} // =default fails on msvc-14.0 + + Y1(Y1 const&) + { + throw std::runtime_error( "Y1(Y1 const&)" ); + } + + Y1& operator=(Y1 const&) = default; +}; + +struct Y2 +{ + Y2() noexcept {} + + Y2(Y2 const&) + { + throw std::runtime_error( "Y2(Y2 const&)" ); + } + + Y2& operator=(Y2 const&) = default; +}; + +void test() +{ + variant<Y1, Y2> v1( in_place_type_t<Y1>{} ); + variant<Y1, Y2> v2( in_place_type_t<Y2>{} ); + + BOOST_TEST_THROWS( v1 = v2, std::runtime_error ) +} + +int main() +{ + test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_copy_construct.cpp b/src/boost/libs/variant2/test/variant_copy_construct.cpp new file mode 100644 index 00000000..63b88a7e --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_construct.cpp @@ -0,0 +1,145 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + X1() {} + X1(X1 const&) {} + X1(X1&&) {} +}; + +inline bool operator==( X1, X1 ) { return true; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); + +struct X2 +{ + X2() {} + X2(X2 const&) {} + X2(X2&&) {} +}; + +inline bool operator==( X2, X2 ) { return true; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); + +struct Y +{ + Y( Y const& ) = delete; +}; + +template<class V> static void test( V const & v ) +{ + V v2( v ); + + BOOST_TEST_EQ( v.index(), v2.index() ); + BOOST_TEST( v == v2 ); +} + +int main() +{ + test( variant<int>() ); + test( variant<int>(1) ); + + test( variant<int const>() ); + test( variant<int const>(1) ); + + test( variant<int, float>() ); + test( variant<int, float>(1) ); + test( variant<int, float>(3.14f) ); + + test( variant<int const, float const>() ); + test( variant<int const, float const>(1) ); + test( variant<int const, float const>(3.14f) ); + + test( variant<std::string>() ); + test( variant<std::string>("test") ); + + test( variant<std::string const>() ); + test( variant<std::string const>("test") ); + + test( variant<int, float, std::string>() ); + test( variant<int, float, std::string>(1) ); + test( variant<int, float, std::string>(3.14f) ); + test( variant<int, float, std::string>("test") ); + + test( variant<int, int>() ); + + test( variant<int, int, float>() ); + test( variant<int, int, float>(3.14f) ); + + test( variant<int, int, float, float>() ); + + test( variant<int, int, float, float, std::string>("test") ); + + test( variant<std::string, std::string, float>() ); + + test( variant<X1 const>() ); + + test( variant<X1, X2>() ); + test( variant<X1, X2, int>() ); + test( variant<X1, X2, X2>() ); + test( variant<X1, X1, X2, X2>() ); + + { + variant<X1, X2> v; + v.emplace<X2>(); + + test( v ); + } + + { + variant<X1, X1, X2> v; + v.emplace<X2>(); + + test( v ); + } + + { + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int const>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, float>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int, int, float, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, int>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, int, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<int, X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<int, int, X1>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible<variant<X1, X2, int, int>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible<variant<X1, X2>>)); + +#if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + + BOOST_TEST_TRAIT_FALSE((std::is_copy_constructible<variant<int, float, Y>>)); + +#endif + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_copy_construct_cx.cpp b/src/boost/libs/variant2/test/variant_copy_construct_cx.cpp new file mode 100644 index 00000000..cd3a7c2b --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_construct_cx.cpp @@ -0,0 +1,112 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class T, class V> constexpr T test( V const v ) +{ + return get<T>( v ); +} + +int main() +{ + { + constexpr variant<int> v( 1 ); + constexpr auto w = test<int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<X> v( 1 ); + constexpr auto w = test<X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant<Y> v( 1 ); + constexpr auto w = test<Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr variant<int, float> v( 1 ); + constexpr auto w = test<int>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, float> v( 3.0f ); + constexpr auto w = test<float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant<int, int, float> v( 3.0f ); + constexpr auto w = test<float>( v ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr variant<E, E, X> v( 1 ); + constexpr auto w = test<X>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, int, float, float, X> v( X(1) ); + constexpr auto w = test<X>( v ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr variant<E, E, Y> v( 1 ); + constexpr auto w = test<Y>( v ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr variant<int, int, float, float, Y> v( Y(1) ); + constexpr auto w = test<Y>( v ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_copy_construct_throw.cpp b/src/boost/libs/variant2/test/variant_copy_construct_throw.cpp new file mode 100644 index 00000000..81b44d9f --- /dev/null +++ b/src/boost/libs/variant2/test/variant_copy_construct_throw.cpp @@ -0,0 +1,69 @@ + +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <stdexcept> + +using namespace boost::variant2; + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + X( X const& ) + { + throw std::runtime_error( "X(X const&)" ); + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +void test() +{ + X::instances = 0; + + { + variant<X> v1; + + BOOST_TEST_EQ( X::instances, 1 ); + + try + { + variant<X> v2( v1 ); + BOOST_TEST_EQ( X::instances, 2 ); + } + catch( std::exception const& ) + { + } + + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); +} + +int main() +{ + test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_default_construct.cpp b/src/boost/libs/variant2/test/variant_default_construct.cpp new file mode 100644 index 00000000..894934cb --- /dev/null +++ b/src/boost/libs/variant2/test/variant_default_construct.cpp @@ -0,0 +1,103 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ + X(); +}; + +struct Y +{ + Y() = delete; +}; + +int main() +{ + { + variant<int> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int const> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, float, std::string> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, int, std::string> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<std::string> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), std::string() ); + } + + { + variant<std::string const> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), std::string() ); + } + + { + variant<std::string, int, float> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), std::string() ); + } + + { + variant<std::string, std::string, float> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), std::string() ); + } + + { + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int const>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int, X>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int, float, X>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int, int, X>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_default_constructible<variant<int, X, X>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible<variant<X>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible<variant<X, int>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_default_constructible<variant<X, int, float>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_default_constructible<variant<int, Y>>)); + BOOST_TEST_TRAIT_FALSE((std::is_default_constructible<variant<Y, int>>)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_default_construct_cx.cpp b/src/boost/libs/variant2/test/variant_default_construct_cx.cpp new file mode 100644 index 00000000..d3325c6b --- /dev/null +++ b/src/boost/libs/variant2/test/variant_default_construct_cx.cpp @@ -0,0 +1,51 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v; + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<int const> v; + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<int, float> v; + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<int, int, float> v; + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<int, float, float> v; + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } +} diff --git a/src/boost/libs/variant2/test/variant_destroy.cpp b/src/boost/libs/variant2/test/variant_destroy.cpp new file mode 100644 index 00000000..392a2d7d --- /dev/null +++ b/src/boost/libs/variant2/test/variant_destroy.cpp @@ -0,0 +1,205 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X1 +{ + static int instances; + + int v; + + X1(): v(0) { ++instances; } + explicit X1(int v): v(v) { ++instances; } + X1(X1 const& r): v(r.v) { ++instances; } + X1(X1&& r): v(r.v) { ++instances; } + + ~X1() noexcept { --instances; } + + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +int X1::instances = 0; + +struct X2 +{ + static int instances; + + int v; + + X2(): v(0) { ++instances; } + explicit X2(int v): v(v) { ++instances; } + X2(X2 const& r): v(r.v) { ++instances; } + X2(X2&& r): v(r.v) { ++instances; } + + ~X2() noexcept { --instances; } + + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +int X2::instances = 0; + +struct Y1 +{ + static int instances; + + int v; + + Y1() noexcept: v(0) { ++instances; } + explicit Y1(int v) noexcept: v(v) { ++instances; } + Y1(Y1 const& r) noexcept: v(r.v) { ++instances; } + Y1(Y1&& r) noexcept: v(r.v) { ++instances; } + + ~Y1() noexcept { --instances; } + + Y1& operator=( Y1 const& r ) noexcept { v = r.v; return *this; } + Y1& operator=( Y1&& r ) noexcept { v = r.v; return *this; } +}; + +int Y1::instances = 0; + +struct Y2 +{ + static int instances; + + int v; + + Y2() noexcept: v(0) { ++instances; } + explicit Y2(int v) noexcept: v(v) { ++instances; } + Y2(Y2 const& r) noexcept: v(r.v) { ++instances; } + Y2(Y2&& r) noexcept: v(r.v) { ++instances; } + + ~Y2() noexcept { --instances; } + + Y2& operator=( Y2 const& r ) noexcept { v = r.v; return *this; } + Y2& operator=( Y2&& r ) noexcept { v = r.v; return *this; } +}; + +int Y2::instances = 0; + +int main() +{ + BOOST_TEST_EQ( Y1::instances, 0 ); + + { + variant<Y1> v; + BOOST_TEST_EQ( Y1::instances, 1 ); + + { + variant<Y1> v2; + BOOST_TEST_EQ( Y1::instances, 2 ); + + v = v2; + BOOST_TEST_EQ( Y1::instances, 2 ); + } + + BOOST_TEST_EQ( Y1::instances, 1 ); + + v = Y1{1}; + BOOST_TEST_EQ( Y1::instances, 1 ); + } + + BOOST_TEST_EQ( Y1::instances, 0 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + { + variant<Y1, Y2> v; + + BOOST_TEST_EQ( Y1::instances, 1 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + { + variant<Y1, Y2> v2; + BOOST_TEST_EQ( Y1::instances, 2 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + v = v2; + BOOST_TEST_EQ( Y1::instances, 2 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + v2 = Y2{1}; + BOOST_TEST_EQ( Y1::instances, 1 ); + BOOST_TEST_EQ( Y2::instances, 1 ); + + v = v2; + BOOST_TEST_EQ( Y1::instances, 0 ); + BOOST_TEST_EQ( Y2::instances, 2 ); + } + + BOOST_TEST_EQ( Y1::instances, 0 ); + BOOST_TEST_EQ( Y2::instances, 1 ); + + v.emplace<0>(); + + BOOST_TEST_EQ( Y1::instances, 1 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + v.emplace<Y2>(); + + BOOST_TEST_EQ( Y1::instances, 0 ); + BOOST_TEST_EQ( Y2::instances, 1 ); + } + + BOOST_TEST_EQ( Y1::instances, 0 ); + BOOST_TEST_EQ( Y2::instances, 0 ); + + BOOST_TEST_EQ( X1::instances, 0 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + { + variant<X1, X2> v; + + BOOST_TEST_EQ( X1::instances, 1 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + { + variant<X1, X2> v2; + BOOST_TEST_EQ( X1::instances, 2 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + v = v2; + BOOST_TEST_EQ( X1::instances, 2 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + v2 = X2{1}; + BOOST_TEST_EQ( X1::instances, 1 ); + BOOST_TEST_EQ( X2::instances, 1 ); + + v = v2; + BOOST_TEST_EQ( X1::instances, 0 ); + BOOST_TEST_EQ( X2::instances, 2 ); + } + + BOOST_TEST_EQ( X1::instances, 0 ); + BOOST_TEST_EQ( X2::instances, 1 ); + + v.emplace<0>(); + + BOOST_TEST_EQ( X1::instances, 1 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + v.emplace<X2>(); + + BOOST_TEST_EQ( X1::instances, 0 ); + BOOST_TEST_EQ( X2::instances, 1 ); + } + + BOOST_TEST_EQ( X1::instances, 0 ); + BOOST_TEST_EQ( X2::instances, 0 ); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_emplace_index.cpp b/src/boost/libs/variant2/test/variant_emplace_index.cpp new file mode 100644 index 00000000..7fa30b7f --- /dev/null +++ b/src/boost/libs/variant2/test/variant_emplace_index.cpp @@ -0,0 +1,181 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<0>( 1 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v.emplace<0>(); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, float> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<0>( 1 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v.emplace<1>( 3.14f ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + v.emplace<1>(); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 0 ); + + v.emplace<0>(); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, int, float, std::string> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<0>( 1 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v.emplace<1>(); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 0 ); + + v.emplace<1>( 1 ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 1 ); + + v.emplace<2>( 3.14f ); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + v.emplace<2>(); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 0 ); + + v.emplace<3>( "s1" ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + v.emplace<3>( "s2" ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + + v.emplace<3>(); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string() ); + + v.emplace<3>( { 'a', 'b' } ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), (std::string{ 'a', 'b'}) ); + + v.emplace<3>( { 'c', 'd' }, std::allocator<char>() ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), (std::string{ 'c', 'd'}) ); + } + + { + variant<X1, X2> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + v.emplace<0>( 1 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + v.emplace<1>( 2 ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + v.emplace<0>(); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + v.emplace<0>( 4 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + + v.emplace<1>(); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 0 ); + + v.emplace<1>( 6 ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 6 ); + + v.emplace<0>( 3 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 3 ); + + v.emplace<0>( 4 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_emplace_index_cx.cpp b/src/boost/libs/variant2/test/variant_emplace_index_cx.cpp new file mode 100644 index 00000000..f66f99fc --- /dev/null +++ b/src/boost/libs/variant2/test/variant_emplace_index_cx.cpp @@ -0,0 +1,136 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr explicit X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr explicit Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class V, std::size_t I, class A> constexpr A test( A const& a ) +{ + V v; + + v.template emplace<I>( a ); + + return get<I>(v); +} + +int main() +{ + { + constexpr auto w = test<variant<int>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<X>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<Y>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test<variant<int, float>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, float>, 1>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 1>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 2>( 2.0f ); + STATIC_ASSERT( w == 2.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 3>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 4>( 4 ); + STATIC_ASSERT( w == 4 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X, X>, 5>( 5 ); + STATIC_ASSERT( w == 5 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 0>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 1>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 2>( 2.0f ); + STATIC_ASSERT( w == 2.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 3>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 4>( 4 ); + STATIC_ASSERT( w == 4 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y, Y>, 5>( 5 ); + STATIC_ASSERT( w == 5 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_emplace_type.cpp b/src/boost/libs/variant2/test/variant_emplace_type.cpp new file mode 100644 index 00000000..df8b364a --- /dev/null +++ b/src/boost/libs/variant2/test/variant_emplace_type.cpp @@ -0,0 +1,194 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +struct Y1 +{ +}; + +struct Y2 +{ + ~Y2() {} +}; + +struct Guard +{ + explicit Guard(int) {} + Guard(Guard&&) = delete; +}; + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<int>( 1 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v.emplace<int>(); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, float> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<int>( 1 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v.emplace<float>( 3.14f ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + v.emplace<float>(); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 0 ); + + v.emplace<int>(); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, int, float, std::string> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v.emplace<float>( 3.14f ); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + v.emplace<float>(); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 0 ); + + v.emplace<std::string>( "s1" ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + v.emplace<std::string>( "s2" ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + + v.emplace<std::string>(); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string() ); + + v.emplace<std::string>( { 'a', 'b' } ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), (std::string{ 'a', 'b' }) ); + + v.emplace<std::string>( { 'c', 'd' }, std::allocator<char>() ); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), (std::string{ 'c', 'd' }) ); + } + + { + variant<X1, X2> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + v.emplace<X1>( 1 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + v.emplace<X2>( 2 ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + v.emplace<X1>(); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + v.emplace<X1>( 4 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + + v.emplace<X2>(); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 0 ); + + v.emplace<X2>( 6 ); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 6 ); + + v.emplace<X1>( 3 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 3 ); + + v.emplace<X1>( 4 ); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + } + + { + variant<Y1, Guard> v; + v.emplace<Guard>( 1 ); + } + + { + variant<Y2, Guard> v; + v.emplace<Guard>( 1 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_emplace_type_cx.cpp b/src/boost/libs/variant2/test/variant_emplace_type_cx.cpp new file mode 100644 index 00000000..2449b12b --- /dev/null +++ b/src/boost/libs/variant2/test/variant_emplace_type_cx.cpp @@ -0,0 +1,91 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr explicit X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr explicit Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class V, class T, class A> constexpr A test( A const& a ) +{ + V v; + + v.template emplace<T>( a ); + + return get<T>(v); +} + +int main() +{ + { + constexpr auto w = test<variant<int>, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<X>, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<Y>, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test<variant<int, float>, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, float>, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float>, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X>, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<int, int, float, float, Y>, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_eq_ne.cpp b/src/boost/libs/variant2/test/variant_eq_ne.cpp new file mode 100644 index 00000000..b2fc19dc --- /dev/null +++ b/src/boost/libs/variant2/test/variant_eq_ne.cpp @@ -0,0 +1,92 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ +}; + +inline bool operator==( X const&, X const& ) { return false; } +inline bool operator!=( X const&, X const& ) { return false; } + +int main() +{ + { + variant<int> v1, v2, v3( 1 ), v4( 1 ); + + BOOST_TEST( v1 == v2 ); + BOOST_TEST_NOT( v1 != v2 ); + + BOOST_TEST( v1 != v3 ); + BOOST_TEST_NOT( v1 == v3 ); + + BOOST_TEST( v3 == v4 ); + BOOST_TEST_NOT( v3 != v4 ); + } + + { + variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); + + BOOST_TEST( v1 == v2 ); + BOOST_TEST_NOT( v1 != v2 ); + + BOOST_TEST( v1 != v3 ); + BOOST_TEST_NOT( v1 == v3 ); + + BOOST_TEST( v3 == v4 ); + BOOST_TEST_NOT( v3 != v4 ); + + BOOST_TEST( v1 != v5 ); + BOOST_TEST_NOT( v1 == v5 ); + + BOOST_TEST( v3 != v5 ); + BOOST_TEST_NOT( v3 == v5 ); + + BOOST_TEST( v5 == v6 ); + BOOST_TEST_NOT( v5 != v6 ); + } + + { + variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); + + BOOST_TEST( v1 == v2 ); + BOOST_TEST_NOT( v1 != v2 ); + + BOOST_TEST( v1 != v3 ); + BOOST_TEST_NOT( v1 == v3 ); + + BOOST_TEST( v3 == v4 ); + BOOST_TEST_NOT( v3 != v4 ); + + BOOST_TEST( v1 != v5 ); + BOOST_TEST_NOT( v1 == v5 ); + + BOOST_TEST( v3 != v5 ); + BOOST_TEST_NOT( v3 == v5 ); + + BOOST_TEST( v5 == v6 ); + BOOST_TEST_NOT( v5 != v6 ); + } + + { + variant<X> v1, v2; + + BOOST_TEST_NOT( v1 == v2 ); + BOOST_TEST_NOT( v1 != v2 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_eq_ne_cx.cpp b/src/boost/libs/variant2/test/variant_eq_ne_cx.cpp new file mode 100644 index 00000000..9ebb751c --- /dev/null +++ b/src/boost/libs/variant2/test/variant_eq_ne_cx.cpp @@ -0,0 +1,98 @@ + +// Copyright 2017, 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +using namespace boost::variant2; + +#if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) + +#include <boost/config/pragma_message.hpp> + +BOOST_PRAGMA_MESSAGE("Skipping constexpr op==, op!= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") + +int main() {} + +#else + +struct X +{ +}; + +inline constexpr bool operator==( X const&, X const& ) { return false; } +inline constexpr bool operator!=( X const&, X const& ) { return false; } + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v1, v2, v3( 1 ), v4( 1 ); + + STATIC_ASSERT( v1 == v2 ); + STATIC_ASSERT( !(v1 != v2) ); + + STATIC_ASSERT( v1 != v3 ); + STATIC_ASSERT( !(v1 == v3) ); + + STATIC_ASSERT( v3 == v4 ); + STATIC_ASSERT( !(v3 != v4) ); + } + + { + constexpr variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); + + STATIC_ASSERT( v1 == v2 ); + STATIC_ASSERT( !(v1 != v2) ); + + STATIC_ASSERT( v1 != v3 ); + STATIC_ASSERT( !(v1 == v3) ); + + STATIC_ASSERT( v3 == v4 ); + STATIC_ASSERT( !(v3 != v4) ); + + STATIC_ASSERT( v1 != v5 ); + STATIC_ASSERT( !(v1 == v5) ); + + STATIC_ASSERT( v3 != v5 ); + STATIC_ASSERT( !(v3 == v5) ); + + STATIC_ASSERT( v5 == v6 ); + STATIC_ASSERT( !(v5 != v6) ); + } + + { + constexpr variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); + + STATIC_ASSERT( v1 == v2 ); + STATIC_ASSERT( !(v1 != v2) ); + + STATIC_ASSERT( v1 != v3 ); + STATIC_ASSERT( !(v1 == v3) ); + + STATIC_ASSERT( v3 == v4 ); + STATIC_ASSERT( !(v3 != v4) ); + + STATIC_ASSERT( v1 != v5 ); + STATIC_ASSERT( !(v1 == v5) ); + + STATIC_ASSERT( v3 != v5 ); + STATIC_ASSERT( !(v3 == v5) ); + + STATIC_ASSERT( v5 == v6 ); + STATIC_ASSERT( !(v5 != v6) ); + } + + { + constexpr variant<X> v1, v2; + + STATIC_ASSERT( !(v1 == v2) ); + STATIC_ASSERT( !(v1 != v2) ); + } +} + +#endif diff --git a/src/boost/libs/variant2/test/variant_get_by_index.cpp b/src/boost/libs/variant2/test/variant_get_by_index.cpp new file mode 100644 index 00000000..2728196e --- /dev/null +++ b/src/boost/libs/variant2/test/variant_get_by_index.cpp @@ -0,0 +1,349 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +int main() +{ + { + variant<int> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int*>)); + } + + { + variant<int> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const*>)); + } + + { + variant<int const> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const*>)); + } + + { + variant<int volatile> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const volatile*>)); + } + + { + variant<int> v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int> const v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int> v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int> const v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int, float> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(v)), float&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(std::move(v))), float&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<1>(&v)), float*>)); + } + + { + variant<int, float> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(v)), float const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(std::move(v))), float const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<1>(&v)), float const*>)); + } + + { + variant<int const, float volatile> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(v)), float volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(std::move(v))), float volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<1>(&v)), float volatile*>)); + } + + { + variant<int const, float volatile> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<0>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<0>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(v)), float const volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<1>(std::move(v))), float const volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<1>(&v)), float const volatile*>)); + } + + { + variant<int, float> v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int, float> const v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int, float> v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int, float> const v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int, float> v( 3.14f ); + + BOOST_TEST_THROWS( get<0>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<0>(&v), nullptr ); + + BOOST_TEST_EQ( get<1>(v), 3.14f ); + BOOST_TEST_EQ( get_if<1>(&v), &get<1>(v) ); + + BOOST_TEST_EQ( get<1>(std::move(v)), 3.14f ); + } + + { + variant<int, float> const v( 3.14f ); + + BOOST_TEST_THROWS( get<0>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<0>(&v), nullptr ); + + BOOST_TEST_EQ( get<1>(v), 3.14f ); + BOOST_TEST_EQ( get_if<1>(&v), &get<1>(v) ); + + BOOST_TEST_EQ( get<1>(std::move(v)), 3.14f ); + } + + { + variant<int, float, float> v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_THROWS( get<2>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<2>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int, float, float> const v; + + BOOST_TEST_EQ( get<0>(v), 0 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_THROWS( get<2>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<2>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 0 ); + } + + { + variant<int, float, float> v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_THROWS( get<2>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<2>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int, float, float> const v( 1 ); + + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get_if<0>(&v), &get<0>(v) ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_THROWS( get<2>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<2>(&v), nullptr ); + + BOOST_TEST_EQ( get<0>(std::move(v)), 1 ); + } + + { + variant<int, int, float> v( 3.14f ); + + BOOST_TEST_THROWS( get<0>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<0>(&v), nullptr ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<2>(v), 3.14f ); + BOOST_TEST_EQ( get_if<2>(&v), &get<2>(v) ); + + BOOST_TEST_EQ( get<2>(std::move(v)), 3.14f ); + } + + { + variant<int, int, float> const v( 3.14f ); + + BOOST_TEST_THROWS( get<0>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<0>(&v), nullptr ); + + BOOST_TEST_THROWS( get<1>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<1>(&v), nullptr ); + + BOOST_TEST_EQ( get<2>(v), 3.14f ); + BOOST_TEST_EQ( get_if<2>(&v), &get<2>(v) ); + + BOOST_TEST_EQ( get<2>(std::move(v)), 3.14f ); + } + + { + variant<int> * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int const> * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int> const * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int const> const * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int, float> * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int, float> const * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int const, float volatile> * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int const, float volatile> const * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int, int, float, float> * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + { + variant<int, int, float, float> const * p = 0; + BOOST_TEST_EQ( get_if<0>(p), nullptr ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_get_by_index_cx.cpp b/src/boost/libs/variant2/test/variant_get_by_index_cx.cpp new file mode 100644 index 00000000..026b9d3c --- /dev/null +++ b/src/boost/libs/variant2/test/variant_get_by_index_cx.cpp @@ -0,0 +1,96 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/config.hpp> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#if BOOST_WORKAROUND(BOOST_GCC, < 50000) +# define STATIC_ASSERT_IF(...) +#else +# define STATIC_ASSERT_IF(...) static_assert(__VA_ARGS__, #__VA_ARGS__) +#endif + +int main() +{ + { + constexpr variant<int> v; + + STATIC_ASSERT( get<0>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + } + + { + constexpr variant<int> v( 1 ); + + STATIC_ASSERT( get<0>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + } + + { + constexpr variant<int, float> v; + + STATIC_ASSERT( get<0>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); + } + + { + constexpr variant<int, float> v( 1 ); + + STATIC_ASSERT( get<0>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); + } + + { + constexpr variant<int, float> v( 3.14f ); + + STATIC_ASSERT( get<1>(v) == 3.14f ); + + STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<1>(&v) == &get<1>(v) ); + } + + { + constexpr variant<int, float, float> v; + + STATIC_ASSERT( get<0>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<2>(&v) == nullptr ); + } + + { + constexpr variant<int, float, float> v( 1 ); + + STATIC_ASSERT( get<0>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<0>(&v) == &get<0>(v) ); + STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<2>(&v) == nullptr ); + } + + { + constexpr variant<int, int, float> v( 3.14f ); + + STATIC_ASSERT( get<2>(v) == 3.14f ); + + STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<2>(&v) == &get<2>(v) ); + } +} diff --git a/src/boost/libs/variant2/test/variant_get_by_type.cpp b/src/boost/libs/variant2/test/variant_get_by_type.cpp new file mode 100644 index 00000000..47daa94c --- /dev/null +++ b/src/boost/libs/variant2/test/variant_get_by_type.cpp @@ -0,0 +1,307 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +int main() +{ + { + variant<int> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(v)), int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(std::move(v))), int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int>(&v)), int*>)); + } + + { + variant<int> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int>(&v)), int const*>)); + } + + { + variant<int const> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int const>(&v)), int const*>)); + } + + { + variant<int volatile> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int volatile>(v)), int const volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int volatile>(std::move(v))), int const volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int volatile>(&v)), int const volatile*>)); + } + + { + variant<int> v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int> const v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int> v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int> const v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int, float> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(v)), int&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(std::move(v))), int&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int>(&v)), int*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float>(v)), float&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float>(std::move(v))), float&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<float>(&v)), float*>)); + } + + { + variant<int, float> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float>(v)), float const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float>(std::move(v))), float const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<float>(&v)), float const*>)); + } + + { + variant<int const, float volatile> v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int const>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float volatile>(v)), float volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float volatile>(std::move(v))), float volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<float volatile>(&v)), float volatile*>)); + } + + { + variant<int const, float volatile> const v; + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(v)), int const&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<int const>(std::move(v))), int const&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<int const>(&v)), int const*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float volatile>(v)), float const volatile&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get<float volatile>(std::move(v))), float const volatile&&>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<decltype(get_if<float volatile>(&v)), float const volatile*>)); + } + + { + variant<int, float> v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_THROWS( get<float>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<float>(&v), nullptr ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int, float> const v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_THROWS( get<float>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<float>(&v), nullptr ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int, float> v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_THROWS( get<float>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<float>(&v), nullptr ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int, float> const v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_THROWS( get<float>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<float>(&v), nullptr ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int, float> v( 3.14f ); + + BOOST_TEST_THROWS( get<int>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<int>(&v), nullptr ); + + BOOST_TEST_EQ( get<float>(v), 3.14f ); + BOOST_TEST_EQ( get_if<float>(&v), &get<float>(v) ); + + BOOST_TEST_EQ( get<float>(std::move(v)), 3.14f ); + } + + { + variant<int, float> const v( 3.14f ); + + BOOST_TEST_THROWS( get<int>(v), bad_variant_access ); + BOOST_TEST_EQ( get_if<int>(&v), nullptr ); + + BOOST_TEST_EQ( get<float>(v), 3.14f ); + BOOST_TEST_EQ( get_if<float>(&v), &get<float>(v) ); + + BOOST_TEST_EQ( get<float>(std::move(v)), 3.14f ); + } + + { + variant<int, float, float> v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int, float, float> const v; + + BOOST_TEST_EQ( get<int>(v), 0 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 0 ); + } + + { + variant<int, float, float> v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int, float, float> const v( 1 ); + + BOOST_TEST_EQ( get<int>(v), 1 ); + BOOST_TEST_EQ( get_if<int>(&v), &get<int>(v) ); + + BOOST_TEST_EQ( get<int>(std::move(v)), 1 ); + } + + { + variant<int, int, float> v( 3.14f ); + + BOOST_TEST_EQ( get<float>(v), 3.14f ); + BOOST_TEST_EQ( get_if<float>(&v), &get<float>(v) ); + + BOOST_TEST_EQ( get<float>(std::move(v)), 3.14f ); + } + + { + variant<int, int, float> const v( 3.14f ); + + BOOST_TEST_EQ( get<float>(v), 3.14f ); + BOOST_TEST_EQ( get_if<float>(&v), &get<float>(v) ); + + BOOST_TEST_EQ( get<float>(std::move(v)), 3.14f ); + } + + { + variant<int> * p = 0; + BOOST_TEST_EQ( get_if<int>(p), nullptr ); + } + + { + variant<int const> * p = 0; + BOOST_TEST_EQ( get_if<int const>(p), nullptr ); + } + + { + variant<int> const * p = 0; + BOOST_TEST_EQ( get_if<int>(p), nullptr ); + } + + { + variant<int const> const * p = 0; + BOOST_TEST_EQ( get_if<int const>(p), nullptr ); + } + + { + variant<int, float> * p = 0; + + BOOST_TEST_EQ( get_if<int>(p), nullptr ); + BOOST_TEST_EQ( get_if<float>(p), nullptr ); + } + + { + variant<int, float> const * p = 0; + + BOOST_TEST_EQ( get_if<int>(p), nullptr ); + BOOST_TEST_EQ( get_if<float>(p), nullptr ); + } + + { + variant<int, int, float> * p = 0; + BOOST_TEST_EQ( get_if<float>(p), nullptr ); + } + + { + variant<int, int, float> const * p = 0; + BOOST_TEST_EQ( get_if<float>(p), nullptr ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_get_by_type_cx.cpp b/src/boost/libs/variant2/test/variant_get_by_type_cx.cpp new file mode 100644 index 00000000..0f9a40c5 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_get_by_type_cx.cpp @@ -0,0 +1,90 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/config.hpp> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#if BOOST_WORKAROUND(BOOST_GCC, < 50000) +# define STATIC_ASSERT_IF(...) +#else +# define STATIC_ASSERT_IF(...) static_assert(__VA_ARGS__, #__VA_ARGS__) +#endif + +int main() +{ + { + constexpr variant<int> v; + + STATIC_ASSERT( get<int>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + } + + { + constexpr variant<int> v( 1 ); + + STATIC_ASSERT( get<int>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + } + + { + constexpr variant<int, float> v; + + STATIC_ASSERT( get<int>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + STATIC_ASSERT_IF( get_if<float>(&v) == nullptr ); + } + + { + constexpr variant<int, float> v( 1 ); + + STATIC_ASSERT( get<int>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + STATIC_ASSERT_IF( get_if<float>(&v) == nullptr ); + } + + { + constexpr variant<int, float> v( 3.14f ); + + STATIC_ASSERT( get<float>(v) == 3.14f ); + + STATIC_ASSERT_IF( get_if<int>(&v) == nullptr ); + STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) ); + } + + { + constexpr variant<int, float, float> v; + + STATIC_ASSERT( get<int>(v) == 0 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + } + + { + constexpr variant<int, float, float> v( 1 ); + + STATIC_ASSERT( get<int>(v) == 1 ); + + STATIC_ASSERT_IF( get_if<int>(&v) == &get<int>(v) ); + } + + { + constexpr variant<int, int, float> v( 3.14f ); + + STATIC_ASSERT( get<float>(v) == 3.14f ); + + STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) ); + } +} diff --git a/src/boost/libs/variant2/test/variant_holds_alternative.cpp b/src/boost/libs/variant2/test/variant_holds_alternative.cpp new file mode 100644 index 00000000..4931f40f --- /dev/null +++ b/src/boost/libs/variant2/test/variant_holds_alternative.cpp @@ -0,0 +1,78 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <string> + +using namespace boost::variant2; + +int main() +{ + { + variant<int> v; + BOOST_TEST( holds_alternative<int>( v ) ); + } + + { + variant<int, float> v; + BOOST_TEST( holds_alternative<int>( v ) ); + BOOST_TEST( !holds_alternative<float>( v ) ); + } + + { + variant<int, float> v( 3.14f ); + BOOST_TEST( !holds_alternative<int>( v ) ); + BOOST_TEST( holds_alternative<float>( v ) ); + } + + { + variant<int, float, float> v; + BOOST_TEST( holds_alternative<int>( v ) ); + } + + { + variant<int, int, float> v( 3.14f ); + BOOST_TEST( holds_alternative<float>( v ) ); + } + + { + variant<int, float, std::string> v; + BOOST_TEST( holds_alternative<int>( v ) ); + BOOST_TEST( !holds_alternative<float>( v ) ); + BOOST_TEST( !holds_alternative<std::string>( v ) ); + } + + { + variant<int, float, std::string> v( 3.14f ); + BOOST_TEST( !holds_alternative<int>( v ) ); + BOOST_TEST( holds_alternative<float>( v ) ); + BOOST_TEST( !holds_alternative<std::string>( v ) ); + } + + { + variant<int, float, std::string> v( "text" ); + BOOST_TEST( !holds_alternative<int>( v ) ); + BOOST_TEST( !holds_alternative<float>( v ) ); + BOOST_TEST( holds_alternative<std::string>( v ) ); + } + + { + variant<int, int, float, std::string> v( 3.14f ); + BOOST_TEST( holds_alternative<float>( v ) ); + BOOST_TEST( !holds_alternative<std::string>( v ) ); + } + + { + variant<int, int, float, std::string> v( "text" ); + BOOST_TEST( !holds_alternative<float>( v ) ); + BOOST_TEST( holds_alternative<std::string>( v ) ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_holds_alternative_cx.cpp b/src/boost/libs/variant2/test/variant_holds_alternative_cx.cpp new file mode 100644 index 00000000..c2bdc0a6 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_holds_alternative_cx.cpp @@ -0,0 +1,43 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v; + STATIC_ASSERT( holds_alternative<int>( v ) ); + } + + { + constexpr variant<int, float> v; + STATIC_ASSERT( holds_alternative<int>( v ) ); + STATIC_ASSERT( !holds_alternative<float>( v ) ); + } + + { + constexpr variant<int, float> v( 3.14f ); + STATIC_ASSERT( !holds_alternative<int>( v ) ); + STATIC_ASSERT( holds_alternative<float>( v ) ); + } + + { + constexpr variant<int, float, float> v; + STATIC_ASSERT( holds_alternative<int>( v ) ); + } + + { + constexpr variant<int, int, float> v( 3.14f ); + STATIC_ASSERT( holds_alternative<float>( v ) ); + } +} diff --git a/src/boost/libs/variant2/test/variant_in_place_index_construct.cpp b/src/boost/libs/variant2/test/variant_in_place_index_construct.cpp new file mode 100644 index 00000000..75821d32 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_in_place_index_construct.cpp @@ -0,0 +1,138 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ + X() = default; + X( in_place_index_t<0> ) = delete; +}; + +int main() +{ + { + variant<int> v( in_place_index_t<0>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<X> v( in_place_index_t<0>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + } + + { + variant<int> v( in_place_index_t<0>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int, float> v( in_place_index_t<0>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + } + + { + variant<int, float> v( in_place_index_t<0>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int, float> v( in_place_index_t<1>{} ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 0 ); + } + + { + variant<int, float> v( in_place_index_t<1>{}, 3.14f ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<0>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<1>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 1 ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<2>{}, 3.14f ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<3>{}, 3.14f ); + + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), 3.14f ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<4>{}, "text" ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), std::string("text") ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<5>{}, "text" ); + + BOOST_TEST_EQ( v.index(), 5 ); + BOOST_TEST_EQ( get<5>(v), std::string("text") ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<5>{}, 4, 'a' ); + + BOOST_TEST_EQ( v.index(), 5 ); + BOOST_TEST_EQ( get<5>(v), std::string( 4, 'a' ) ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<4>{}, { 'a', 'b', 'c' } ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); + } + + { + variant<int, int, float, float, std::string, std::string> v( in_place_index_t<5>{}, { 'a', 'b', 'c' }, std::allocator<char>() ); + + BOOST_TEST_EQ( v.index(), 5 ); + BOOST_TEST_EQ( get<5>(v), (std::string{ 'a', 'b', 'c' }) ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_in_place_index_construct_cx.cpp b/src/boost/libs/variant2/test/variant_in_place_index_construct_cx.cpp new file mode 100644 index 00000000..80a6934e --- /dev/null +++ b/src/boost/libs/variant2/test/variant_in_place_index_construct_cx.cpp @@ -0,0 +1,116 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ + constexpr X() = default; + constexpr explicit X(int, int) {} + X( in_place_index_t<0> ) = delete; +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v( in_place_index_t<0>{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<X> v( in_place_index_t<0>{} ); + + STATIC_ASSERT( v.index() == 0 ); + } + + { + constexpr variant<int> v( in_place_index_t<0>{}, 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int, float> v( in_place_index_t<0>{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + } + + { + constexpr variant<int, float> v( in_place_index_t<0>{}, 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int, float> v( in_place_index_t<1>{} ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( get<1>(v) == 0 ); + } + + { + constexpr variant<int, float> v( in_place_index_t<1>{}, 3.14f ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( get<1>(v) == 3.14f ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<0>{}, 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<1>{}, 1 ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( get<1>(v) == 1 ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<2>{}, 3.14f ); + + STATIC_ASSERT( v.index() == 2 ); + STATIC_ASSERT( get<2>(v) == 3.14f ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<3>{}, 3.14f ); + + STATIC_ASSERT( v.index() == 3 ); + STATIC_ASSERT( get<3>(v) == 3.14f ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<4>{} ); + + STATIC_ASSERT( v.index() == 4 ); + } + + { + constexpr variant<int, int, float, float, X, X> v( in_place_index_t<5>{}, 0, 0 ); + + STATIC_ASSERT( v.index() == 5 ); + } +} diff --git a/src/boost/libs/variant2/test/variant_in_place_type_construct.cpp b/src/boost/libs/variant2/test/variant_in_place_type_construct.cpp new file mode 100644 index 00000000..3c8265ac --- /dev/null +++ b/src/boost/libs/variant2/test/variant_in_place_type_construct.cpp @@ -0,0 +1,134 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ + X() = default; + template<class T> X( in_place_type_t<T> ) = delete; +}; + +int main() +{ + { + variant<int> v( in_place_type_t<int>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + BOOST_TEST( holds_alternative<int>(v) ); + } + + { + variant<X> v( in_place_type_t<X>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + + BOOST_TEST( holds_alternative<X>(v) ); + } + + { + variant<int> v( in_place_type_t<int>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + BOOST_TEST( holds_alternative<int>(v) ); + } + + { + variant<int, float> v( in_place_type_t<int>{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + BOOST_TEST( holds_alternative<int>(v) ); + } + + { + variant<int, float> v( in_place_type_t<int>{}, 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + BOOST_TEST( holds_alternative<int>(v) ); + } + + { + variant<int, float> v( in_place_type_t<float>{} ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 0 ); + + BOOST_TEST( holds_alternative<float>(v) ); + } + + { + variant<int, float> v( in_place_type_t<float>{}, 3.14f ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + BOOST_TEST( holds_alternative<float>(v) ); + } + + { + variant<int, int, float, std::string> v( in_place_type_t<float>{}, 3.14f ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + BOOST_TEST( holds_alternative<float>(v) ); + } + + { + variant<int, int, float, float, std::string> v( in_place_type_t<std::string>{}, "text" ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), std::string("text") ); + + BOOST_TEST( holds_alternative<std::string>(v) ); + } + + { + variant<int, int, float, float, std::string> v( in_place_type_t<std::string>{}, 4, 'a' ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), std::string( 4, 'a' ) ); + + BOOST_TEST( holds_alternative<std::string>(v) ); + } + + { + variant<int, int, float, float, std::string> v( in_place_type_t<std::string>{}, { 'a', 'b', 'c' } ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); + + BOOST_TEST( holds_alternative<std::string>(v) ); + } + + { + variant<int, int, float, float, std::string> v( in_place_type_t<std::string>{}, { 'a', 'b', 'c' }, std::allocator<char>() ); + + BOOST_TEST_EQ( v.index(), 4 ); + BOOST_TEST_EQ( get<4>(v), (std::string{ 'a', 'b', 'c' }) ); + + BOOST_TEST( holds_alternative<std::string>(v) ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_in_place_type_construct_cx.cpp b/src/boost/libs/variant2/test/variant_in_place_type_construct_cx.cpp new file mode 100644 index 00000000..a64c3470 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_in_place_type_construct_cx.cpp @@ -0,0 +1,110 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + constexpr X() = default; + constexpr explicit X(int, int) {} + template<class T> X( in_place_type_t<T> ) = delete; +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v( in_place_type_t<int>{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + + STATIC_ASSERT( holds_alternative<int>(v) ); + } + + { + constexpr variant<X> v( in_place_type_t<X>{} ); + + STATIC_ASSERT( v.index() == 0 ); + + STATIC_ASSERT( holds_alternative<X>(v) ); + } + + { + constexpr variant<int> v( in_place_type_t<int>{}, 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + + STATIC_ASSERT( holds_alternative<int>(v) ); + } + + { + constexpr variant<int, float> v( in_place_type_t<int>{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 0 ); + + STATIC_ASSERT( holds_alternative<int>(v) ); + } + + { + constexpr variant<int, float> v( in_place_type_t<int>{}, 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + + STATIC_ASSERT( holds_alternative<int>(v) ); + } + + { + constexpr variant<int, float> v( in_place_type_t<float>{} ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( get<1>(v) == 0 ); + + STATIC_ASSERT( holds_alternative<float>(v) ); + } + + { + constexpr variant<int, float> v( in_place_type_t<float>{}, 3.14f ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( get<1>(v) == 3.14f ); + + STATIC_ASSERT( holds_alternative<float>(v) ); + } + + { + constexpr variant<int, int, float, X> v( in_place_type_t<float>{}, 3.14f ); + + STATIC_ASSERT( v.index() == 2 ); + STATIC_ASSERT( get<2>(v) == 3.14f ); + + STATIC_ASSERT( holds_alternative<float>(v) ); + } + + { + constexpr variant<int, int, float, float, X> v( in_place_type_t<X>{} ); + + STATIC_ASSERT( v.index() == 4 ); + + STATIC_ASSERT( holds_alternative<X>(v) ); + } + + { + constexpr variant<int, int, float, float, X> v( in_place_type_t<X>{}, 0, 0 ); + + STATIC_ASSERT( v.index() == 4 ); + + STATIC_ASSERT( holds_alternative<X>(v) ); + } +} diff --git a/src/boost/libs/variant2/test/variant_lt_gt.cpp b/src/boost/libs/variant2/test/variant_lt_gt.cpp new file mode 100644 index 00000000..688209f8 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_lt_gt.cpp @@ -0,0 +1,85 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ +}; + +inline bool operator<( X const&, X const& ) { return false; } +inline bool operator>( X const&, X const& ) { return false; } +inline bool operator<=( X const&, X const& ) { return false; } +inline bool operator>=( X const&, X const& ) { return false; } + +#define TEST_EQ( v1, v2 ) \ + BOOST_TEST_NOT( v1 < v2 ); \ + BOOST_TEST_NOT( v1 > v2 ); \ + BOOST_TEST( v1 <= v2 ); \ + BOOST_TEST( v1 >= v2 ); + +#define TEST_LE( v1, v3 ) \ + BOOST_TEST( v1 < v3 ); \ + BOOST_TEST( v3 > v1 ); \ + BOOST_TEST_NOT( v1 > v3 ); \ + BOOST_TEST_NOT( v3 < v1 ); \ + BOOST_TEST( v1 <= v3 ); \ + BOOST_TEST( v3 >= v1 ); \ + BOOST_TEST_NOT( v1 >= v3 ); \ + BOOST_TEST_NOT( v3 <= v1 ); + +int main() +{ + { + variant<int> v1, v2, v3( 1 ), v4( 1 ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + } + + { + variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + TEST_LE( v1, v5 ) + TEST_LE( v3, v5 ) + TEST_EQ( v5, v6 ) + } + + { + variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + TEST_LE( v1, v5 ) + TEST_LE( v3, v5 ) + TEST_EQ( v5, v6 ) + } + + { + variant<X> v1, v2; + + BOOST_TEST_NOT( v1 < v2 ); + BOOST_TEST_NOT( v1 > v2 ); + BOOST_TEST_NOT( v1 <= v2 ); + BOOST_TEST_NOT( v1 >= v2 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_lt_gt_cx.cpp b/src/boost/libs/variant2/test/variant_lt_gt_cx.cpp new file mode 100644 index 00000000..b5708464 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_lt_gt_cx.cpp @@ -0,0 +1,91 @@ + +// Copyright 2017, 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +using namespace boost::variant2; + +#if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR) + +#include <boost/config/pragma_message.hpp> + +BOOST_PRAGMA_MESSAGE("Skipping constexpr op<, op<= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined") + +int main() {} + +#else + +struct X +{ +}; + +inline constexpr bool operator<( X const&, X const& ) { return false; } +inline constexpr bool operator>( X const&, X const& ) { return false; } +inline constexpr bool operator<=( X const&, X const& ) { return false; } +inline constexpr bool operator>=( X const&, X const& ) { return false; } + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#define TEST_EQ( v1, v2 ) \ + STATIC_ASSERT( !(v1 < v2) ); \ + STATIC_ASSERT( !(v1 > v2) ); \ + STATIC_ASSERT( v1 <= v2 ); \ + STATIC_ASSERT( v1 >= v2 ); + +#define TEST_LE( v1, v3 ) \ + STATIC_ASSERT( v1 < v3 ); \ + STATIC_ASSERT( v3 > v1 ); \ + STATIC_ASSERT( !(v1 > v3) ); \ + STATIC_ASSERT( !(v3 < v1) ); \ + STATIC_ASSERT( v1 <= v3 ); \ + STATIC_ASSERT( v3 >= v1 ); \ + STATIC_ASSERT( !(v1 >= v3) ); \ + STATIC_ASSERT( !(v3 <= v1) ); + +int main() +{ + { + constexpr variant<int> v1, v2, v3( 1 ), v4( 1 ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + } + + { + constexpr variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + TEST_LE( v1, v5 ) + TEST_LE( v3, v5 ) + TEST_EQ( v5, v6 ) + } + + { + constexpr variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f ); + + TEST_EQ( v1, v2 ) + TEST_LE( v1, v3 ) + TEST_EQ( v3, v4 ) + TEST_LE( v1, v5 ) + TEST_LE( v3, v5 ) + TEST_EQ( v5, v6 ) + } + + { + constexpr variant<X> v1, v2; + + STATIC_ASSERT( !(v1 < v2) ); + STATIC_ASSERT( !(v1 > v2) ); + STATIC_ASSERT( !(v1 <= v2) ); + STATIC_ASSERT( !(v1 >= v2) ); + } +} + +#endif diff --git a/src/boost/libs/variant2/test/variant_move_assign.cpp b/src/boost/libs/variant2/test/variant_move_assign.cpp new file mode 100644 index 00000000..632f0681 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_assign.cpp @@ -0,0 +1,194 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +struct Y +{ + Y& operator=( Y&& ) = delete; +}; + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int> v2( 1 ); + + v = std::move(v2); + BOOST_TEST_EQ( get<0>(v), 1 ); + + variant<int> v3( 2 ); + + v = std::move(v3); + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int, float> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, float> v2( 1 ); + + v = std::move(v2); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + variant<int, float> v3( 3.14f ); + + v = std::move(v3); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + variant<int, float> v4( 3.15f ); + + v = std::move(v4); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.15f ); + } + + { + variant<int, int, float, std::string> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, int, float, std::string> v2( in_place_index_t<1>{}, 1 ); + + v = std::move(v2); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 1 ); + + variant<int, int, float, std::string> v3( 3.14f ); + + v = std::move(v3); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + variant<int, int, float, std::string> v4( 3.15f ); + + v = std::move(v4); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.15f ); + + variant<int, int, float, std::string> v5( "s1" ); + + v = std::move(v5); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + variant<int, int, float, std::string> v6( "s2" ); + + v = std::move(v6); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + } + + { + variant<X1, X2> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + variant<X1, X2> v2( X1{1} ); + + v = std::move(v2); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + variant<X1, X2> v3( in_place_index_t<1>{}, 2 ); + + v = std::move(v3); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + variant<X1, X2> v4( in_place_index_t<1>{}, 3 ); + + v = std::move(v4); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 3 ); + + variant<X1, X2> v5( in_place_index_t<0>{}, 4 ); + + v = std::move(v5); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + } + + { + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable<variant<int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable<variant<int, int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable<variant<int, float>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_assignable<variant<int, int, float, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<X1, int>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<X1, int, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<int, X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<int, int, X1>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_assignable<variant<X1, X2, int, int>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_move_assignable<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_move_assignable<variant<int const>>)); + BOOST_TEST_TRAIT_FALSE((std::is_move_assignable<variant<int, float, Y>>)); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_move_assign_cx.cpp b/src/boost/libs/variant2/test/variant_move_assign_cx.cpp new file mode 100644 index 00000000..d7ab65fa --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_assign_cx.cpp @@ -0,0 +1,107 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <utility> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class V, class T, class A> constexpr T test( A&& a ) +{ + V v; + + v = std::forward<A>(a); + + return get<T>(v); +} + +int main() +{ + { + constexpr auto w = test<variant<int>, int>( variant<int>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<X>, X>( variant<X>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<Y>, Y>( variant<Y>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test<variant<int, float>, int>( variant<int, float>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, float>, float>( variant<int, float>( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float>, float>( variant<int, int, float>( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<E, E, X>, X>( variant<E, E, X>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X>, X>( variant<int, int, float, float, X>( X(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<E, E, Y>, Y>( variant<E, E, Y>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y>, Y>( variant<int, int, float, float, Y>( Y(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_move_assign_throw.cpp b/src/boost/libs/variant2/test/variant_move_assign_throw.cpp new file mode 100644 index 00000000..c1df5944 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_assign_throw.cpp @@ -0,0 +1,55 @@ + +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <stdexcept> + +using namespace boost::variant2; + +struct Y1 +{ + Y1() noexcept {} // =default fails on msvc-14.0 + + Y1(Y1&&) + { + throw std::runtime_error( "Y1(Y1&&)" ); + } + + Y1& operator=(Y1&&) = default; +}; + +struct Y2 +{ + Y2() noexcept {} + + Y2(Y2&&) + { + throw std::runtime_error( "Y2(Y2&&)" ); + } + + Y2& operator=(Y2&&) = default; +}; + +void test() +{ + variant<Y1, Y2> v1( in_place_type_t<Y1>{} ); + variant<Y1, Y2> v2( in_place_type_t<Y2>{} ); + + BOOST_TEST_THROWS( v1 = std::move( v2 ), std::runtime_error ) +} + +int main() +{ + test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_move_construct.cpp b/src/boost/libs/variant2/test/variant_move_construct.cpp new file mode 100644 index 00000000..dd83c8c1 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_construct.cpp @@ -0,0 +1,146 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + X1() {} + X1(X1 const&) {} + X1(X1&&) {} +}; + +inline bool operator==( X1, X1 ) { return true; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); + +struct X2 +{ + X2() {} + X2(X2 const&) {} + X2(X2&&) {} +}; + +inline bool operator==( X2, X2 ) { return true; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); + +struct Y +{ + Y( Y&& ) = delete; +}; + +template<class V> static void test( V&& v ) +{ + V v2( v ); + V v3( std::move(v) ); + + BOOST_TEST_EQ( v2.index(), v3.index() ); + BOOST_TEST( v2 == v3 ); +} + +int main() +{ + test( variant<int>() ); + test( variant<int>(1) ); + + test( variant<int const>() ); + test( variant<int const>(1) ); + + test( variant<int, float>() ); + test( variant<int, float>(1) ); + test( variant<int, float>(3.14f) ); + + test( variant<int const, float const>() ); + test( variant<int const, float const>(1) ); + test( variant<int const, float const>(3.14f) ); + + test( variant<std::string>() ); + test( variant<std::string>("test") ); + + test( variant<std::string const>() ); + test( variant<std::string const>("test") ); + + test( variant<int, float, std::string>() ); + test( variant<int, float, std::string>(1) ); + test( variant<int, float, std::string>(3.14f) ); + test( variant<int, float, std::string>("test") ); + + test( variant<int, int>() ); + + test( variant<int, int, float>() ); + test( variant<int, int, float>(3.14f) ); + + test( variant<int, int, float, float>() ); + + test( variant<int, int, float, float, std::string>("test") ); + + test( variant<std::string, std::string, float>() ); + + test( variant<X1 const>() ); + + test( variant<X1, X2>() ); + test( variant<X1, X2, int>() ); + test( variant<X1, X2, X2>() ); + test( variant<X1, X1, X2, X2>() ); + + { + variant<X1, X2> v; + v.emplace<X2>(); + + test( std::move(v) ); + } + + { + variant<X1, X1, X2> v; + v.emplace<X2>(); + + test( std::move(v) ); + } + + { + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int const>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, int>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, float>>)); + BOOST_TEST_TRAIT_TRUE((std::is_nothrow_move_constructible<variant<int, int, float, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, int>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, int, float>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<int, X1>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<int, int, X1>>)); + + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, X2>>)); + BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible<variant<X1, X2, int, int>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_move_constructible<variant<X1, X2>>)); + +#if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + + BOOST_TEST_TRAIT_FALSE((std::is_move_constructible<variant<int, float, Y>>)); + +#endif + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_move_construct_cx.cpp b/src/boost/libs/variant2/test/variant_move_construct_cx.cpp new file mode 100644 index 00000000..1e49b7f8 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_construct_cx.cpp @@ -0,0 +1,104 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <utility> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class T, class V> constexpr T test( V&& v ) +{ + V v2( std::forward<V>(v) ); + return get<T>( v2 ); +} + +int main() +{ + { + constexpr auto w = test<int>( variant<int>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<X>( variant<X>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<Y>( variant<Y>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test<int>( variant<int, float>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<float>( variant<int, float>( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<float>( variant<int, int, float>( 3.0f ) ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<X>( variant<E, E, X>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<X>( variant<int, int, float, float, X>( X(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<Y>( variant<E, E, Y>( 1 ) ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<Y>( variant<int, int, float, float, Y>( Y(1) ) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_move_construct_throw.cpp b/src/boost/libs/variant2/test/variant_move_construct_throw.cpp new file mode 100644 index 00000000..aabf7d26 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_move_construct_throw.cpp @@ -0,0 +1,69 @@ + +// Copyright 2019 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <stdexcept> + +using namespace boost::variant2; + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + X( X const& ) + { + throw std::runtime_error( "X(X const&)" ); + } + + ~X() + { + --instances; + } +}; + +int X::instances = 0; + +void test() +{ + X::instances = 0; + + { + variant<X> v1; + + BOOST_TEST_EQ( X::instances, 1 ); + + try + { + variant<X> v2( std::move( v1 ) ); + BOOST_TEST_EQ( X::instances, 2 ); + } + catch( std::exception const& ) + { + } + + BOOST_TEST_EQ( X::instances, 1 ); + } + + BOOST_TEST_EQ( X::instances, 0 ); +} + +int main() +{ + test(); + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_size.cpp b/src/boost/libs/variant2/test/variant_size.cpp new file mode 100644 index 00000000..81e63ac1 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_size.cpp @@ -0,0 +1,104 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/mp11.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <cstddef> + +using namespace boost::variant2; +using namespace boost::mp11; + +template<class T> using var_size_t = mp_size_t<variant_size<T>::value>; + +int main() +{ + BOOST_TEST_EQ( (variant_size<variant<>>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<> const>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<> volatile>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<> const volatile>::value), 0 ); + + BOOST_TEST_EQ( (variant_size<variant<>&>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<> const&>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<>&&>::value), 0 ); + BOOST_TEST_EQ( (variant_size<variant<> const&&>::value), 0 ); + + BOOST_TEST_EQ( (variant_size<variant<void>>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void> const>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void> volatile>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void> const volatile>::value), 1 ); + + BOOST_TEST_EQ( (variant_size<variant<void>&>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void> const&>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void>&&>::value), 1 ); + BOOST_TEST_EQ( (variant_size<variant<void> const&&>::value), 1 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void>>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void> const>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void> volatile>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void> const volatile>::value), 2 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void>&>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void> const&>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void>&&>::value), 2 ); + BOOST_TEST_EQ( (variant_size<variant<void, void> const&&>::value), 2 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void, void>>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void> const>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void> volatile>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void> const volatile>::value), 3 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void, void>&>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void> const&>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void>&&>::value), 3 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void> const&&>::value), 3 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> volatile>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const volatile>::value), 4 ); + + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>&>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const&>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>&&>::value), 4 ); + BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const&&>::value), 4 ); + + variant_size<void>(); + variant_size<void const>(); + variant_size<void volatile>(); + variant_size<void const volatile>(); + + variant_size<int&>(); + variant_size<int const&>(); + variant_size<int&&>(); + variant_size<int const&&>(); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void const>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void volatile>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void const volatile>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int const&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int&&>)); + BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int const&&>)); + + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> volatile>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const volatile>)); + + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>&&>)); + BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const&&>)); + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_subset.cpp b/src/boost/libs/variant2/test/variant_subset.cpp new file mode 100644 index 00000000..90c9bc21 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_subset.cpp @@ -0,0 +1,159 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +int main() +{ + { + variant<int, float> v1( 1 ); + + variant<int> v2 = v1.subset<int>(); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v1 ), get<int>( v2 ) ); + + BOOST_TEST_THROWS( v1.subset<float>(), bad_variant_access ); + + variant<int> v3 = std::move(v1).subset<int>(); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + + BOOST_TEST_THROWS( std::move(v1).subset<float>(), bad_variant_access ); + } + + { + variant<int, float> const v1( 1 ); + + variant<int> v2 = v1.subset<int>(); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v1 ), get<int>( v2 ) ); + + BOOST_TEST_THROWS( v1.subset<float>(), bad_variant_access ); + + variant<int> v3 = std::move(v1).subset<int>(); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + + BOOST_TEST_THROWS( std::move(v1).subset<float>(), bad_variant_access ); + } + + { + variant<int, float> v1( 1 ); + + variant<int, float> v2 = v1.subset<int, float>(); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v1 ), get<int>( v2 ) ); + + variant<int, float> v3 = std::move(v1).subset<int, float>(); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + } + + { + variant<int, float> v1( 1 ); + + variant<float, int> v2 = v1.subset<float, int>(); + + BOOST_TEST( holds_alternative<int>( v2 ) ); + BOOST_TEST_EQ( get<int>( v1 ), get<int>( v2 ) ); + + variant<float, int> v3 = std::move(v1).subset<float, int>(); + + BOOST_TEST( holds_alternative<int>( v3 ) ); + BOOST_TEST_EQ( get<int>( v2 ), get<int>( v3 ) ); + } + + { + variant<int, float, std::string> v1( "s1" ); + + variant<int, std::string> v2 = v1.subset<int, std::string>(); + + BOOST_TEST( holds_alternative<std::string>( v2 ) ); + BOOST_TEST_EQ( get<std::string>( v1 ), get<std::string>( v2 ) ); + + variant<float, std::string> v3 = std::move(v1).subset<float, std::string>(); + + BOOST_TEST( holds_alternative<std::string>( v3 ) ); + BOOST_TEST_EQ( get<std::string>( v2 ), get<std::string>( v3 ) ); + } + + { + variant<int, int, float, float, X1, X2> v1{ X1{1} }; + + variant<X1, X2> v2 = v1.subset<X1, X2>(); + + BOOST_TEST( holds_alternative<X1>( v2 ) ); + BOOST_TEST_EQ( get<X1>( v1 ).v, get<X1>( v2 ).v ); + + variant<X1, X2> v3 = std::move( v1 ).subset<X1, X2>(); + + BOOST_TEST( holds_alternative<X1>( v3 ) ); + BOOST_TEST_EQ( get<X1>( v2 ).v, get<X1>( v3 ).v ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_swap.cpp b/src/boost/libs/variant2/test/variant_swap.cpp new file mode 100644 index 00000000..3e80f0f2 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_swap.cpp @@ -0,0 +1,259 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int> v2( 1 ); + BOOST_TEST_EQ( get<0>(v2), 1 ); + + swap( v, v2 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + BOOST_TEST_EQ( get<0>(v2), 0 ); + + variant<int> v3( 2 ); + BOOST_TEST_EQ( get<0>(v3), 2 ); + + swap( v, v3 ); + BOOST_TEST_EQ( get<0>(v), 2 ); + BOOST_TEST_EQ( get<0>(v3), 1 ); + } + + { + variant<int, float> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, float> v2( 1 ); + + BOOST_TEST_EQ( v2.index(), 0 ); + BOOST_TEST_EQ( get<0>(v2), 1 ); + + swap( v, v2 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + BOOST_TEST_EQ( v2.index(), 0 ); + BOOST_TEST_EQ( get<0>(v2), 0 ); + + variant<int, float> v3( 3.14f ); + + BOOST_TEST_EQ( v3.index(), 1 ); + BOOST_TEST_EQ( get<1>(v3), 3.14f ); + + swap( v, v3 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + BOOST_TEST_EQ( v3.index(), 0 ); + BOOST_TEST_EQ( get<0>(v3), 1 ); + + variant<int, float> v4( 3.15f ); + + BOOST_TEST_EQ( v4.index(), 1 ); + BOOST_TEST_EQ( get<1>(v4), 3.15f ); + + swap( v, v4 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.15f ); + + BOOST_TEST_EQ( v4.index(), 1 ); + BOOST_TEST_EQ( get<1>(v4), 3.14f ); + } + + { + variant<int, int, float, std::string> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + variant<int, int, float, std::string> v2( in_place_index_t<1>{}, 1 ); + + BOOST_TEST_EQ( v2.index(), 1 ); + BOOST_TEST_EQ( get<1>(v2), 1 ); + + swap( v, v2 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 1 ); + + BOOST_TEST_EQ( v2.index(), 0 ); + BOOST_TEST_EQ( get<0>(v2), 0 ); + + variant<int, int, float, std::string> v3( 3.14f ); + + BOOST_TEST_EQ( v3.index(), 2 ); + BOOST_TEST_EQ( get<2>(v3), 3.14f ); + + swap( v, v3 ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + BOOST_TEST_EQ( v3.index(), 1 ); + BOOST_TEST_EQ( get<1>(v3), 1 ); + + variant<int, int, float, std::string> v4( 3.15f ); + + BOOST_TEST_EQ( v4.index(), 2 ); + BOOST_TEST_EQ( get<2>(v4), 3.15f ); + + swap( v, v4 ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.15f ); + + BOOST_TEST_EQ( v4.index(), 2 ); + BOOST_TEST_EQ( get<2>(v4), 3.14f ); + + variant<int, int, float, std::string> v5( "s1" ); + + BOOST_TEST_EQ( v5.index(), 3 ); + BOOST_TEST_EQ( get<3>(v5), std::string("s1") ); + + swap( v, v5 ); + + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + BOOST_TEST_EQ( v5.index(), 2 ); + BOOST_TEST_EQ( get<2>(v5), 3.15f ); + + variant<int, int, float, std::string> v6( "s2" ); + + BOOST_TEST_EQ( v6.index(), 3 ); + BOOST_TEST_EQ( get<3>(v6), std::string("s2") ); + + swap( v, v6 ); + + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + + BOOST_TEST_EQ( v6.index(), 3 ); + BOOST_TEST_EQ( get<3>(v6), std::string("s1") ); + } + + { + variant<X1, X2> v; + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + variant<X1, X2> v2( X1{1} ); + + BOOST_TEST_EQ( v2.index(), 0 ); + BOOST_TEST_EQ( get<0>(v2).v, 1 ); + + swap( v, v2 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + BOOST_TEST_EQ( v2.index(), 0 ); + BOOST_TEST_EQ( get<0>(v2).v, 0 ); + + variant<X1, X2> v3( in_place_index_t<1>{}, 2 ); + + BOOST_TEST_EQ( v3.index(), 1 ); + BOOST_TEST_EQ( get<1>(v3).v, 2 ); + + swap( v, v3 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + BOOST_TEST_EQ( v3.index(), 0 ); + BOOST_TEST_EQ( get<0>(v3).v, 1 ); + + variant<X1, X2> v4( in_place_index_t<1>{}, 3 ); + + BOOST_TEST_EQ( v4.index(), 1 ); + BOOST_TEST_EQ( get<1>(v4).v, 3 ); + + swap( v, v4 ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 3 ); + + BOOST_TEST_EQ( v4.index(), 1 ); + BOOST_TEST_EQ( get<1>(v4).v, 2 ); + + variant<X1, X2> v5( in_place_index_t<0>{}, 4 ); + + BOOST_TEST_EQ( v5.index(), 0 ); + BOOST_TEST_EQ( get<0>(v5).v, 4 ); + + swap( v, v5 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + + BOOST_TEST_EQ( v5.index(), 1 ); + BOOST_TEST_EQ( get<1>(v5).v, 3 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_value_assign.cpp b/src/boost/libs/variant2/test/variant_value_assign.cpp new file mode 100644 index 00000000..2519adc0 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_value_assign.cpp @@ -0,0 +1,206 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +struct X1 +{ + int v; + + X1(): v(0) {} + explicit X1(int v): v(v) {} + X1(X1 const& r): v(r.v) {} + X1(X1&& r): v(r.v) {} + X1& operator=( X1 const& r ) { v = r.v; return *this; } + X1& operator=( X1&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X1 const& a, X1 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X1>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X1>::value ); + +struct X2 +{ + int v; + + X2(): v(0) {} + explicit X2(int v): v(v) {} + X2(X2 const& r): v(r.v) {} + X2(X2&& r): v(r.v) {} + X2& operator=( X2 const& r ) { v = r.v; return *this; } + X2& operator=( X2&& r ) { v = r.v; return *this; } +}; + +inline bool operator==( X2 const& a, X2 const& b ) { return a.v == b.v; } + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value ); +STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value ); + +int main() +{ + { + variant<int> v; + BOOST_TEST_EQ( get<0>(v), 0 ); + + v = 1; + BOOST_TEST_EQ( get<0>(v), 1 ); + + v = 2; + BOOST_TEST_EQ( get<0>(v), 2 ); + + int w1 = 3; + + v = w1; + BOOST_TEST_EQ( get<0>(v), 3 ); + + int const w2 = 4; + + v = w2; + BOOST_TEST_EQ( get<0>(v), 4 ); + + v = std::move( w1 ); + BOOST_TEST_EQ( get<0>(v), 3 ); + + v = std::move( w2 ); + BOOST_TEST_EQ( get<0>(v), 4 ); + } + + { + variant<int, float> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v = 1; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + + v = 3.14f; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + + float w1 = 3.15f; + + v = w1; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.15f ); + + int const w2 = 2; + + v = w2; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 2 ); + + v = std::move(w1); + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v), 3.15f ); + + v = std::move(w2); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int, int, float, std::string> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 0 ); + + v = 3.14f; + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + + float const w1 = 3.15f; + + v = w1; + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.15f ); + + variant<int, int, float, std::string> v5( "s1" ); + + v = "s1"; + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s1") ); + + std::string w2( "s2" ); + + v = w2; + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + + v = std::move(w1); + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST_EQ( get<2>(v), 3.15f ); + + v = std::move(w2); + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST_EQ( get<3>(v), std::string("s2") ); + } + + { + variant<X1, X2> v; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 0 ); + + v = X1{1}; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 1 ); + + v = X2{2}; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 2 ); + + X1 w1{3}; + + v = w1; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 3 ); + + X1 const w2{4}; + + v = w2; + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + + X2 w3{5}; + + v = w3; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 5 ); + + X2 const w4{6}; + + v = w4; + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST_EQ( get<1>(v).v, 6 ); + + v = std::move(w1); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 3 ); + + v = std::move(w2); + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v).v, 4 ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_value_assign_cx.cpp b/src/boost/libs/variant2/test/variant_value_assign_cx.cpp new file mode 100644 index 00000000..0a29a0af --- /dev/null +++ b/src/boost/libs/variant2/test/variant_value_assign_cx.cpp @@ -0,0 +1,106 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + int v; + X() = default; + constexpr X( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +struct Y +{ + int v; + constexpr Y(): v() {} + constexpr Y( int v ): v( v ) {} + constexpr operator int() const { return v; } +}; + +enum E +{ + v +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template<class V, class T, class A> constexpr A test( A const& a ) +{ + V v; + + v = a; + + return get<T>(v); +} + +int main() +{ + { + constexpr auto w = test<variant<int>, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<X>, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<Y>, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + +#endif + + { + constexpr auto w = test<variant<int, float>, int>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, float>, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<int, int, float>, float>( 3.0f ); + STATIC_ASSERT( w == 3.0f ); + } + + { + constexpr auto w = test<variant<E, E, X>, X>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, X>, X>( X(1) ); + STATIC_ASSERT( w == 1 ); + } + +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 +#else + + { + constexpr auto w = test<variant<E, E, Y>, Y>( 1 ); + STATIC_ASSERT( w == 1 ); + } + + { + constexpr auto w = test<variant<int, int, float, float, Y>, Y>( Y(1) ); + STATIC_ASSERT( w == 1 ); + } + +#endif +} diff --git a/src/boost/libs/variant2/test/variant_value_construct.cpp b/src/boost/libs/variant2/test/variant_value_construct.cpp new file mode 100644 index 00000000..56df8967 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_value_construct.cpp @@ -0,0 +1,124 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <type_traits> +#include <utility> +#include <string> + +using namespace boost::variant2; + +struct X +{ + operator int() const { return 2; } +}; + +int main() +{ + { + variant<int> v( 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int> v( 'a' ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 'a' ); + } + + { + variant<int> v( X{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int const> v( 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int const> v( 'a' ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 'a' ); + } + + { + variant<int const> v( X{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int, float, std::string> v( 1 ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST( holds_alternative<int>(v) ); + BOOST_TEST_EQ( get<0>(v), 1 ); + } + + { + variant<int, float, std::string> v( 'a' ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST( holds_alternative<int>(v) ); + BOOST_TEST_EQ( get<0>(v), 'a' ); + } + + { + variant<int, float, std::string> v( X{} ); + + BOOST_TEST_EQ( v.index(), 0 ); + BOOST_TEST( holds_alternative<int>(v) ); + BOOST_TEST_EQ( get<0>(v), 2 ); + } + + { + variant<int, float, std::string> v( 3.14f ); + + BOOST_TEST_EQ( v.index(), 1 ); + BOOST_TEST( holds_alternative<float>(v) ); + BOOST_TEST_EQ( get<1>(v), 3.14f ); + } + + { + variant<int, float, std::string> v( "text" ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST( holds_alternative<std::string>(v) ); + BOOST_TEST_EQ( get<2>(v), std::string("text") ); + } + + { + variant<int, int, float, std::string> v( 3.14f ); + + BOOST_TEST_EQ( v.index(), 2 ); + BOOST_TEST( holds_alternative<float>(v) ); + BOOST_TEST_EQ( get<2>(v), 3.14f ); + } + + { + variant<int, int, float, std::string> v( "text" ); + + BOOST_TEST_EQ( v.index(), 3 ); + BOOST_TEST( holds_alternative<std::string>(v) ); + BOOST_TEST_EQ( get<3>(v), std::string("text") ); + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_value_construct_cx.cpp b/src/boost/libs/variant2/test/variant_value_construct_cx.cpp new file mode 100644 index 00000000..5ffad252 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_value_construct_cx.cpp @@ -0,0 +1,109 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include <boost/variant2/variant.hpp> + +using namespace boost::variant2; + +struct X +{ + constexpr operator int() const { return 2; } +}; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +int main() +{ + { + constexpr variant<int> v( 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int> v( 'a' ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 'a' ); + } + + { + constexpr variant<int> v( X{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 2 ); + } + + { + constexpr variant<int const> v( 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int const> v( 'a' ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 'a' ); + } + + { + constexpr variant<int const> v( X{} ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( get<0>(v) == 2 ); + } + + { + constexpr variant<int, float, X> v( 1 ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( holds_alternative<int>(v) ); + STATIC_ASSERT( get<0>(v) == 1 ); + } + + { + constexpr variant<int, float, X> v( 'a' ); + + STATIC_ASSERT( v.index() == 0 ); + STATIC_ASSERT( holds_alternative<int>(v) ); + STATIC_ASSERT( get<0>(v) == 'a' ); + } + + { + constexpr variant<int, float, X> v( 3.14f ); + + STATIC_ASSERT( v.index() == 1 ); + STATIC_ASSERT( holds_alternative<float>(v) ); + STATIC_ASSERT( get<1>(v) == 3.14f ); + } + + { + constexpr variant<int, float, X> v( X{} ); + + STATIC_ASSERT( v.index() == 2 ); + STATIC_ASSERT( holds_alternative<X>(v) ); + } + + { + constexpr variant<int, int, float, X> v( 3.14f ); + + STATIC_ASSERT( v.index() == 2 ); + STATIC_ASSERT( holds_alternative<float>(v) ); + STATIC_ASSERT( get<2>(v) == 3.14f ); + } + + { + constexpr variant<int, int, float, X> v( X{} ); + + STATIC_ASSERT( v.index() == 3 ); + STATIC_ASSERT( holds_alternative<X>(v) ); + } +} diff --git a/src/boost/libs/variant2/test/variant_valueless.cpp b/src/boost/libs/variant2/test/variant_valueless.cpp new file mode 100644 index 00000000..d5d18d77 --- /dev/null +++ b/src/boost/libs/variant2/test/variant_valueless.cpp @@ -0,0 +1,260 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4702 ) // unreachable code +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/core/lightweight_test.hpp> +#include <type_traits> +#include <utility> +#include <string> +#include <stdexcept> + +using namespace boost::variant2; +namespace v2d = boost::variant2::detail; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +// + +enum E1 { e1 }; +enum E1x { e1x }; + +struct X1 +{ + X1() = default; + + X1( E1 ) noexcept {} + X1( E1x ) { throw std::runtime_error( "X1(E1x)" ); } +}; + +STATIC_ASSERT( std::is_nothrow_default_constructible<X1>::value ); +STATIC_ASSERT( std::is_nothrow_copy_constructible<X1>::value ); +STATIC_ASSERT( std::is_nothrow_move_constructible<X1>::value ); +STATIC_ASSERT( std::is_trivially_destructible<X1>::value ); +STATIC_ASSERT( v2d::is_trivially_move_assignable<X1>::value ); +STATIC_ASSERT( std::is_nothrow_constructible<X1, E1>::value ); +STATIC_ASSERT( !std::is_nothrow_constructible<X1, E1x>::value ); + +enum E2 { e2 }; +enum E2x { e2x }; + +struct X2 +{ + X2(); + ~X2(); + + X2( E2 ) noexcept {} + X2( E2x ) { throw std::runtime_error( "X2(E2x)" ); } +}; + +X2::X2() {} +X2::~X2() {} + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X2>::value ); +STATIC_ASSERT( std::is_nothrow_copy_constructible<X2>::value ); +STATIC_ASSERT( std::is_nothrow_move_constructible<X2>::value ); +STATIC_ASSERT( !std::is_trivially_destructible<X2>::value ); +STATIC_ASSERT( std::is_nothrow_constructible<X2, E2>::value ); +STATIC_ASSERT( !std::is_nothrow_constructible<X2, E2x>::value ); + +enum E3 { e3 }; +enum E3x { e3x }; + +struct X3 +{ + X3(); + + X3( X3 const& ) {} + X3( X3&& ) {} + + X3( E3 ) noexcept {} + X3( E3x ) { throw std::runtime_error( "X3(E3x)" ); } + + X3& operator=( X3 const& ) = default; + X3& operator=( X3&& ) = default; +}; + +X3::X3() {} + +STATIC_ASSERT( !std::is_nothrow_default_constructible<X3>::value ); +STATIC_ASSERT( !std::is_nothrow_copy_constructible<X3>::value ); +STATIC_ASSERT( !std::is_nothrow_move_constructible<X3>::value ); +STATIC_ASSERT( std::is_trivially_destructible<X3>::value ); +//STATIC_ASSERT( v2d::is_trivially_move_assignable<X3>::value ); +STATIC_ASSERT( std::is_nothrow_constructible<X3, E3>::value ); +STATIC_ASSERT( !std::is_nothrow_constructible<X3, E3x>::value ); + +// + +STATIC_ASSERT( std::is_nothrow_default_constructible<monostate>::value ); +STATIC_ASSERT( std::is_nothrow_copy_constructible<monostate>::value ); +STATIC_ASSERT( std::is_nothrow_move_constructible<monostate>::value ); +STATIC_ASSERT( std::is_trivially_destructible<monostate>::value ); + +// + +int main() +{ + { + variant<X2, X1> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X1, X2> v( e2 ); + + BOOST_TEST_EQ( v.index(), 1 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 1 ); + } + } + + { + variant<X2, X1, monostate> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X1, X2, monostate> v( e2 ); + + BOOST_TEST_EQ( v.index(), 1 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 1 ); + } + } + + { + variant<X2, X3, X1> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e3x; + BOOST_ERROR( "`v = e3x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X2, X3, X1, monostate> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e3x; + BOOST_ERROR( "`v = e3x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X2, X3> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e3x; + BOOST_ERROR( "`v = e3x;` failed to throw" ); + } + catch( std::exception const& ) + { + // double buffered, no change + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X3, X1> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + { + variant<X3, X1, monostate> v; + + BOOST_TEST_EQ( v.index(), 0 ); + + try + { + v = e1x; + BOOST_ERROR( "`v = e1x;` failed to throw" ); + } + catch( std::exception const& ) + { + // strong guarantee + BOOST_TEST_EQ( v.index(), 0 ); + } + } + + return boost::report_errors(); +} diff --git a/src/boost/libs/variant2/test/variant_visit.cpp b/src/boost/libs/variant2/test/variant_visit.cpp new file mode 100644 index 00000000..ed7943ef --- /dev/null +++ b/src/boost/libs/variant2/test/variant_visit.cpp @@ -0,0 +1,126 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#if defined(_MSC_VER) +# pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data +#endif + +#include <boost/variant2/variant.hpp> +#include <boost/mp11.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/core/lightweight_test_trait.hpp> +#include <boost/config.hpp> +#include <type_traits> +#include <utility> +#include <string> +#include <cstdio> + +using namespace boost::variant2; +using boost::mp11::mp_size_t; + +struct X +{ +}; + +struct F +{ + mp_size_t<1> operator()( X& ) const; + mp_size_t<2> operator()( X const& ) const; + mp_size_t<3> operator()( X&& ) const; + mp_size_t<4> operator()( X const&& ) const; +}; + +int main() +{ + { + variant<int> v( 1 ); + + BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 1 ); + + visit( []( int x ){ BOOST_TEST_EQ( x, 1 ); }, v ); + visit( []( int x ){ BOOST_TEST_EQ( x, 1 ); }, std::move(v) ); + } + + { + variant<int> const v( 2 ); + + BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 2 ); + + visit( []( int x ){ BOOST_TEST_EQ( x, 2 ); }, v ); + visit( []( int x ){ BOOST_TEST_EQ( x, 2 ); }, std::move(v) ); + } + + { + variant<int const> v( 3 ); + + BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 3 ); + + visit( []( int x ){ BOOST_TEST_EQ( x, 3 ); }, v ); + visit( []( int x ){ BOOST_TEST_EQ( x, 3 ); }, std::move(v) ); + } + + { + variant<int const> const v( 4 ); + + BOOST_TEST_EQ( (visit( []( int x ){ return x; }, v )), 4 ); + + visit( []( int x ){ BOOST_TEST_EQ( x, 4 ); }, v ); + visit( []( int x ){ BOOST_TEST_EQ( x, 4 ); }, std::move(v) ); + } + + { + variant<int, float> v1( 1 ); + variant<int, float> const v2( 3.14f ); + + BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 ); + + visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 ); + visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) ); + } + + { + variant<int, float, double> v1( 1 ); + variant<int, float, double> const v2( 3.14f ); + variant<int, float, double> v3( 6.28 ); + + 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 ); + + 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 ); + 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) ); + } + + { + variant<int, float, double, char> v1( 1 ); + variant<int, float, double, char> const v2( 3.14f ); + variant<int, float, double, char> v3( 6.28 ); + variant<int, float, double, char> const v4( 'A' ); + + 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' ); + + 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 ); + 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) ); + } + + { + variant<X> v; + variant<X> const cv; + + BOOST_TEST_EQ( decltype(visit(F{}, v))::value, 1 ); + BOOST_TEST_EQ( decltype(visit(F{}, cv))::value, 2 ); + BOOST_TEST_EQ( decltype(visit(F{}, std::move(v)))::value, 3 ); + +#if !BOOST_WORKAROUND(BOOST_GCC, < 40900) + + // g++ 4.8 doesn't handle const&& particularly well + BOOST_TEST_EQ( decltype(visit(F{}, std::move(cv)))::value, 4 ); + +#endif + } + + return boost::report_errors(); +} |