diff options
Diffstat (limited to 'src/boost/libs/variant')
41 files changed, 5766 insertions, 0 deletions
diff --git a/src/boost/libs/variant/CMakeLists.txt b/src/boost/libs/variant/CMakeLists.txt new file mode 100644 index 000000000..1984c195d --- /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 000000000..f66db24a0 --- /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 000000000..17fc68c63 --- /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 000000000..e0b9a5981 --- /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 000000000..302f2ef25 --- /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 000000000..efdd31d00 --- /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 000000000..7ff043f8d --- /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-2020 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 000000000..bfe505b74 --- /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-2020 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 000000000..7cb1ff81c --- /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 000000000..097c2c402 --- /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 000000000..72afff9e2 --- /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 000000000..c6d5ef301 --- /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 000000000..87f1f694c --- /dev/null +++ b/src/boost/libs/variant/test/hash_variant_test.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2011-2020 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 000000000..3b47abb6e --- /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-2020 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 000000000..c106ceead --- /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-2020 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 000000000..9b965554a --- /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 000000000..77edbd550 --- /dev/null +++ b/src/boost/libs/variant/test/no_rvalue_to_nonconst_visitation.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2017-2020 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 000000000..e00487ca6 --- /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-2020 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 000000000..d327bfb4c --- /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-2020 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 000000000..7bb5b4cf0 --- /dev/null +++ b/src/boost/libs/variant/test/recursive_wrapper_move_test.cpp @@ -0,0 +1,77 @@ +// 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 <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 000000000..884435d34 --- /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-2020 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 000000000..b7b9494c4 --- /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 000000000..12e318360 --- /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 000000000..27f0f5892 --- /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 000000000..bef83b361 --- /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 000000000..5de06c8c4 --- /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 000000000..6a0c75d6b --- /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 000000000..1acec31e0 --- /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 000000000..94ef65ab5 --- /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 000000000..08f5267df --- /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-2020 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 000000000..156f3f56e --- /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-2020 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 000000000..e99f3ff99 --- /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-2020 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 000000000..069452398 --- /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-2020 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 000000000..49173c4e3 --- /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-2020 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 000000000..c57302cbe --- /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 000000000..25642b313 --- /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-2020 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 000000000..3f7f58125 --- /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 000000000..674412c8a --- /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 000000000..9aa971c0b --- /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-2020 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 000000000..81afb8e53 --- /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 000000000..c3d0ddc20 --- /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* = BOOST_VARIANT_NULL) +{ + 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* = BOOST_VARIANT_NULL) +{ + 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(); +} |