123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- //-----------------------------------------------------------------------------
- // boost-libs variant/test/auto_visitors.cpp source file
- // See http://www.boost.org for updates, documentation, and revision history.
- //-----------------------------------------------------------------------------
- //
- // Copyright (c) 2014-2019 Antony Polukhin
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include "boost/config.hpp"
- #include "boost/core/lightweight_test.hpp"
- #include "boost/variant.hpp"
- #include "boost/variant/multivisitors.hpp"
- #include "boost/lexical_cast.hpp"
- #include <boost/noncopyable.hpp>
- #include <boost/core/ignore_unused.hpp>
- namespace has_result_type_tests {
- template <class T>
- struct wrap {
- typedef T result_type;
- };
- struct s1 : wrap<int> {};
- struct s2 : wrap<int&> {};
- struct s3 : wrap<const int&> {};
- struct s4 {};
- struct s5 : wrap<int*> {};
- struct s6 : wrap<int**> {};
- struct s7 : wrap<const int*> {};
- struct s8 : wrap<boost::noncopyable> {};
- struct s9 : wrap<boost::noncopyable&> {};
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- struct s10 : wrap<boost::noncopyable&&> {};
- #endif
- struct s11 : wrap<const boost::noncopyable&> {};
- struct s12 : wrap<const boost::noncopyable*> {};
- struct s13 : wrap<boost::noncopyable*> {};
- struct s14 { typedef int result_type; };
- struct s15 { typedef int& result_type; };
- struct s16 { typedef const int& result_type; };
- }
- void test_has_result_type_triat() {
- using namespace has_result_type_tests;
- using boost::detail::variant::has_result_type;
- BOOST_TEST(has_result_type<s1>::value);
- BOOST_TEST(has_result_type<s2>::value);
- BOOST_TEST(has_result_type<s3>::value);
- BOOST_TEST(!has_result_type<s4>::value);
- BOOST_TEST(has_result_type<s5>::value);
- BOOST_TEST(has_result_type<s6>::value);
- BOOST_TEST(has_result_type<s7>::value);
- BOOST_TEST(has_result_type<s8>::value);
- BOOST_TEST(has_result_type<s9>::value);
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- BOOST_TEST(has_result_type<s10>::value);
- #endif
- BOOST_TEST(has_result_type<s11>::value);
- BOOST_TEST(has_result_type<s12>::value);
- BOOST_TEST(has_result_type<s13>::value);
- BOOST_TEST(has_result_type<s14>::value);
- BOOST_TEST(has_result_type<s15>::value);
- BOOST_TEST(has_result_type<s16>::value);
- }
- struct lex_streamer_explicit: boost::static_visitor<std::string> {
- template <class T>
- const char* operator()(const T& ) {
- return "10";
- }
- template <class T1, class T2>
- const char* operator()(const T1& , const T2& ) {
- return "100";
- }
- };
- void run_explicit()
- {
- typedef boost::variant<int, std::string, double> variant_type;
- variant_type v2("10"), v1("100");
- lex_streamer_explicit visitor_ref;
- // Must return instance of std::string
- BOOST_TEST(boost::apply_visitor(visitor_ref, v2).c_str() == std::string("10"));
- BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1).c_str() == std::string("100"));
- }
- // Most part of tests from this file require decltype(auto)
- #ifdef BOOST_NO_CXX14_DECLTYPE_AUTO
- void run()
- {
- BOOST_TEST(true);
- }
- void run2()
- {
- BOOST_TEST(true);
- }
- void run3()
- {
- BOOST_TEST(true);
- }
- #else
- #include <iostream>
- struct lex_streamer {
- template <class T>
- std::string operator()(const T& val) const {
- return boost::lexical_cast<std::string>(val);
- }
- };
- struct lex_streamer_void {
- template <class T>
- void operator()(const T& val) const {
- std::cout << val << std::endl;
- }
- template <class T1, class T2>
- void operator()(const T1& val, const T2& val2) const {
- std::cout << val << '+' << val2 << std::endl;
- }
- template <class T1, class T2, class T3>
- void operator()(const T1& val, const T2& val2, const T3& val3) const {
- std::cout << val << '+' << val2 << '+' << val3 << std::endl;
- }
- };
- struct lex_streamer2 {
- std::string res;
- template <class T>
- const char* operator()(const T& /*val*/) const {
- return "fail";
- }
- template <class T1, class T2>
- const char* operator()(const T1& /*v1*/, const T2& /*v2*/) const {
- return "fail2";
- }
- template <class T1, class T2, class T3>
- const char* operator()(const T1& /*v1*/, const T2& /*v2*/, const T3& /*v3*/) const {
- return "fail3";
- }
- template <class T>
- std::string& operator()(const T& val) {
- res = boost::lexical_cast<std::string>(val);
- return res;
- }
- template <class T1, class T2>
- std::string& operator()(const T1& v1, const T2& v2) {
- res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2);
- return res;
- }
- template <class T1, class T2, class T3>
- std::string& operator()(const T1& v1, const T2& v2, const T3& v3) {
- res = boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2)
- + "+" + boost::lexical_cast<std::string>(v3);
- return res;
- }
- };
- #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
- # define BOOST_TEST_IF_HAS_VARIADIC(x) BOOST_TEST(x)
- #else
- # define BOOST_TEST_IF_HAS_VARIADIC(x) /**/
- #endif
- void run()
- {
- typedef boost::variant<int, std::string, double> variant_type;
- variant_type v1(1), v2("10"), v3(100.0);
- lex_streamer lex_streamer_visitor;
- BOOST_TEST(boost::apply_visitor(lex_streamer(), v1) == "1");
- BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v1) == "1");
- BOOST_TEST(boost::apply_visitor(lex_streamer(), v2) == "10");
- BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_streamer_visitor)(v2) == "10");
- #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
- BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v1) == "1");
- BOOST_TEST(boost::apply_visitor([](auto v) { return boost::lexical_cast<std::string>(v); }, v2) == "10");
- // Retun type must be the same in all instances, so this code does not compile
- //boost::variant<int, short, unsigned> v_diff_types(1);
- //BOOST_TEST(boost::apply_visitor([](auto v) { return v; }, v_diff_types) == 1);
- boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v1);
- boost::apply_visitor([](auto v) { std::cout << v << std::endl; }, v2);
- #endif
- lex_streamer2 visitor_ref;
- BOOST_TEST(boost::apply_visitor(visitor_ref, v1) == "1");
- BOOST_TEST(boost::apply_visitor(visitor_ref, v2) == "10");
- #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
- std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1);
- BOOST_TEST(ref_to_string == "1");
- #endif
- lex_streamer_void lex_streamer_void_visitor;
- boost::apply_visitor(lex_streamer_void(), v1);
- boost::apply_visitor(lex_streamer_void(), v2);
- #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
- boost::apply_visitor(lex_streamer_void_visitor)(v2);
- #endif
- boost::ignore_unused(lex_streamer_visitor, visitor_ref, lex_streamer_void_visitor);
- }
- struct lex_combine {
- template <class T1, class T2>
- std::string operator()(const T1& v1, const T2& v2) const {
- return boost::lexical_cast<std::string>(v1) + "+" + boost::lexical_cast<std::string>(v2);
- }
- template <class T1, class T2, class T3>
- std::string operator()(const T1& v1, const T2& v2, const T3& v3) const {
- return boost::lexical_cast<std::string>(v1) + "+"
- + boost::lexical_cast<std::string>(v2) + '+'
- + boost::lexical_cast<std::string>(v3);
- }
- };
- void run2()
- {
- typedef boost::variant<int, std::string, double> variant_type;
- variant_type v1(1), v2("10"), v3(100.0);
- lex_combine lex_combine_visitor;
- BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2) == "1+10");
- BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1) == "10+1");
- BOOST_TEST_IF_HAS_VARIADIC(boost::apply_visitor(lex_combine_visitor)(v2, v1) == "10+1");
- #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
- BOOST_TEST(
- boost::apply_visitor(
- [](auto v1, auto v2) {
- return boost::lexical_cast<std::string>(v1) + "+"
- + boost::lexical_cast<std::string>(v2);
- }
- , v1
- , v2
- ) == "1+10"
- );
- BOOST_TEST(
- boost::apply_visitor(
- [](auto v1, auto v2) {
- return boost::lexical_cast<std::string>(v1) + "+"
- + boost::lexical_cast<std::string>(v2);
- }
- , v2
- , v1
- ) == "10+1"
- );
- boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v1, v2);
- boost::apply_visitor([](auto v1, auto v2) { std::cout << v1 << '+' << v2 << std::endl; }, v2, v1);
- #endif
- lex_streamer2 visitor_ref;
- BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10");
- BOOST_TEST(boost::apply_visitor(visitor_ref, v2, v1) == "10+1");
- #ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
- std::string& ref_to_string = boost::apply_visitor(visitor_ref)(v1, v2);
- BOOST_TEST(ref_to_string == "1+10");
- #endif
- boost::apply_visitor(lex_streamer_void(), v1, v2);
- boost::apply_visitor(lex_streamer_void(), v2, v1);
- boost::ignore_unused(lex_combine_visitor, visitor_ref);
- }
- #undef BOOST_TEST_IF_HAS_VARIADIC
- void run3()
- {
- #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
- typedef boost::variant<int, std::string, double> variant_type;
- variant_type v1(1), v2("10"), v3(100);
- lex_combine lex_combine_visitor;
- BOOST_TEST(boost::apply_visitor(lex_combine(), v1, v2, v3) == "1+10+100");
- BOOST_TEST(boost::apply_visitor(lex_combine(), v2, v1, v3) == "10+1+100");
- BOOST_TEST(boost::apply_visitor(lex_combine_visitor)(v2, v1, v3) == "10+1+100");
- #ifndef BOOST_NO_CXX14_GENERIC_LAMBDAS
- BOOST_TEST(
- boost::apply_visitor(
- [](auto v1, auto v2, auto v3) {
- return boost::lexical_cast<std::string>(v1) + "+"
- + boost::lexical_cast<std::string>(v2) + "+"
- + boost::lexical_cast<std::string>(v3);
- }
- , v1
- , v2
- , v3
- ) == "1+10+100"
- );
- BOOST_TEST(
- boost::apply_visitor(
- [](auto v1, auto v2, auto v3) {
- return boost::lexical_cast<std::string>(v1) + "+"
- + boost::lexical_cast<std::string>(v2) + "+"
- + boost::lexical_cast<std::string>(v3);
- }
- , v3
- , v1
- , v3
- ) == "100+1+100"
- );
- boost::apply_visitor(
- [](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; },
- v1, v2, v3
- );
- boost::apply_visitor(
- [](auto v1, auto v2, auto v3) { std::cout << v1 << '+' << v2 << '+' << v3 << std::endl; },
- v2, v1, v3
- );
- #endif
- lex_streamer2 visitor_ref;
- BOOST_TEST(boost::apply_visitor(visitor_ref, v1, v2) == "1+10");
- BOOST_TEST(boost::apply_visitor(visitor_ref)(v2, v1) == "10+1");
- std::string& ref_to_string = boost::apply_visitor(visitor_ref, v1, v2);
- BOOST_TEST(ref_to_string == "1+10");
- lex_streamer_void lex_streamer_void_visitor;
- boost::apply_visitor(lex_streamer_void(), v1, v2, v1);
- boost::apply_visitor(lex_streamer_void(), v2, v1, v1);
- boost::apply_visitor(lex_streamer_void_visitor)(v2, v1, v1);
- #endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
- }
- #endif
- int main()
- {
- run_explicit();
- run();
- run2();
- run3();
- test_has_result_type_triat();
- return boost::report_errors();
- }
|