diff options
Diffstat (limited to 'libs/variant/test/auto_visitors.cpp')
-rw-r--r-- | libs/variant/test/auto_visitors.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/libs/variant/test/auto_visitors.cpp b/libs/variant/test/auto_visitors.cpp new file mode 100644 index 000000000..84c91c9d2 --- /dev/null +++ b/libs/variant/test/auto_visitors.cpp @@ -0,0 +1,321 @@ +//----------------------------------------------------------------------------- +// boost-libs variant/test/auto_visitors.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2014-2015 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/test/minimal.hpp" +#include "boost/variant.hpp" +#include "boost/variant/multivisitors.hpp" +#include "boost/lexical_cast.hpp" + +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_CHECK(boost::apply_visitor(visitor_ref, v2).c_str() == std::string("10")); + BOOST_CHECK(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_CHECK(true); +} + +void run2() +{ + BOOST_CHECK(true); +} + + +void run3() +{ + BOOST_CHECK(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_CHECK_IF_HAS_VARIADIC(x) BOOST_CHECK(x) +#else +# define BOOST_CHECK_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_CHECK(boost::apply_visitor(lex_streamer(), v1) == "1"); + BOOST_CHECK_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v1) == "1"); + BOOST_CHECK(boost::apply_visitor(lex_streamer(), v2) == "10"); + BOOST_CHECK_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v2) == "10"); + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_CHECK(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v1) == "1"); + BOOST_CHECK(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_CHECK(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_CHECK(boost::apply_visitor(visitor_ref, v1) == "1"); + BOOST_CHECK(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_CHECK(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 +} + + +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_CHECK(boost::apply_visitor(lex_combine(), v1, v2) == "1+10"); + BOOST_CHECK(boost::apply_visitor(lex_combine(), v2, v1) == "10+1"); + BOOST_CHECK_IF_HAS_VARIADIC(boost::apply_visitor(lex_combine_visitor)(v2, v1) == "10+1"); + + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_CHECK( + 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_CHECK( + 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_CHECK(boost::apply_visitor(visitor_ref, v1, v2) == "1+10"); + BOOST_CHECK(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_CHECK(ref_to_string == "1+10"); +#endif + + boost::apply_visitor(lex_streamer_void(), v1, v2); + boost::apply_visitor(lex_streamer_void(), v2, v1); +} + +#undef BOOST_CHECK_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_CHECK(boost::apply_visitor(lex_combine(), v1, v2, v3) == "1+10+100"); + BOOST_CHECK(boost::apply_visitor(lex_combine(), v2, v1, v3) == "10+1+100"); + BOOST_CHECK(boost::apply_visitor(lex_combine_visitor)(v2, v1, v3) == "10+1+100"); + + + #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS + BOOST_CHECK( + 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_CHECK( + 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_CHECK(boost::apply_visitor(visitor_ref, v1, v2) == "1+10"); + BOOST_CHECK(boost::apply_visitor(visitor_ref)(v2, v1) == "10+1"); + std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1, v2); + BOOST_CHECK(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 test_main(int , char* []) +{ + run_explicit(); + run(); + run2(); + run3(); + + return 0; +} |