This commit is contained in:
diplay
2017-10-09 17:47:27 +03:00
parent ea73f3fb81
commit 86142eccda
4 changed files with 256 additions and 4 deletions
@@ -30,6 +30,10 @@
# include <boost/variant/detail/has_result_type.hpp>
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# define USE_UNIVERSAL_REF
#endif
namespace boost {
//////////////////////////////////////////////////////////////////////////
@@ -144,7 +148,13 @@ inline
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
apply_visitor(
Visitor& visitor
, Visitable1& visitable1, Visitable2& visitable2
#ifdef USE_UNIVERSAL_REF
, Visitable1&& visitable1
, Visitable2&& visitable2
#else
, Visitable1& visitable1
, Visitable2& visitable2
#endif
)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
@@ -167,7 +177,13 @@ inline
)
apply_visitor(
const Visitor& visitor
, Visitable1& visitable1, Visitable2& visitable2
#ifdef USE_UNIVERSAL_REF
, Visitable1&& visitable1
, Visitable2&& visitable2
#else
, Visitable1& visitable1
, Visitable2& visitable2
#endif
)
{
::boost::detail::variant::apply_visitor_binary_unwrap<
@@ -273,8 +289,38 @@ inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1& visitabl
return boost::apply_visitor(unwrapper, visitable1);
}
//universal reference visitables
template <typename Visitor, typename Visitable1, typename Visitable2>
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
Visitor, Visitable2
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, visitable1);
}
template <typename Visitor, typename Visitable1, typename Visitable2>
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
const Visitor, Visitable2
> unwrapper(visitor, visitable2);
return boost::apply_visitor(unwrapper, visitable1);
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
} // namespace boost
#undef USE_UNIVERSAL_REF
#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
@@ -62,10 +62,20 @@ namespace boost {
#endif // EDG-based compilers workaround
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# define USE_UNIVERSAL_REF
#endif
template <typename Visitor, typename Visitable>
inline
BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
apply_visitor(Visitor& visitor, Visitable& visitable)
apply_visitor(Visitor& visitor,
#ifdef USE_UNIVERSAL_REF
Visitable&& visitable
#else
Visitable& visitable
#endif
)
{
return visitable.apply_visitor(visitor);
}
@@ -79,11 +89,19 @@ apply_visitor(Visitor& visitor, Visitable& visitable)
template <typename Visitor, typename Visitable>
inline
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
apply_visitor(const Visitor& visitor, Visitable& visitable)
apply_visitor(const Visitor& visitor,
#ifdef USE_UNIVERSAL_REF
Visitable&& visitable
#else
Visitable& visitable
#endif
)
{
return visitable.apply_visitor(visitor);
}
#undef USE_UNIVERSAL_REF
#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
@@ -166,6 +184,26 @@ inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable
return visitable.apply_visitor(cpp14_vis);
}
template <typename Visitor, typename Visitable>
inline decltype(auto) apply_visitor(Visitor& visitor, Visitable&& visitable,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(visitor);
return visitable.apply_visitor(cpp14_vis);
}
template <typename Visitor, typename Visitable>
inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable&& visitable,
typename boost::disable_if<
boost::detail::variant::has_result_type<Visitor>
>::type* = 0)
{
boost::detail::variant::result_wrapper1<const Visitor, Visitable> cpp14_vis(visitor);
return visitable.apply_visitor(cpp14_vis);
}
#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
} // namespace boost
+1
View File
@@ -53,6 +53,7 @@ test-suite variant
[ run overload_selection.cpp ]
[ run recursive_wrapper_move_test.cpp ]
[ run variant_over_joint_view_test.cpp ]
[ run const_ref_apply_visitor.cpp : : : <cxxflags>-std=c++14 ]
;
+167
View File
@@ -0,0 +1,167 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/auto_visitors.cpp source file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
#include "boost/config.hpp"
#include "boost/test/minimal.hpp"
#include "boost/variant.hpp"
#include "boost/variant/apply_visitor.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";
}
construction_logger(construction_logger&& cl) :
_val(cl._val)
{
std::cout << _val << " move constructed\n";
}
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);
}
};
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_CHECK(boost::apply_visitor(lex_streamer_explicit(), test_var) == lcs(test_var));
}
void test_const_ref_parameter2(const variant_type& test_var, const variant_type& test_var2)
{
std::cout << "Testing const lvalue reference visitable\n";
BOOST_CHECK(boost::apply_visitor(lex_streamer_explicit(), test_var, test_var2) == lcs(test_var) + '+' + lcs(test_var2));
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void test_rvalue_parameter(variant_type&& test_var)
{
std::cout << "Testing rvalue visitable\n";
const auto expected_val = lcs(test_var);
BOOST_CHECK(boost::apply_visitor(lex_streamer_explicit(), std::move(test_var)) == expected_val);
}
void test_rvalue_parameter2(variant_type&& test_var, variant_type&& test_var2)
{
std::cout << "Testing rvalue visitable\n";
const auto expected_val = lcs(test_var) + '+' + lcs(test_var2);
BOOST_CHECK(boost::apply_visitor(lex_streamer_explicit(), std::move(test_var), std::move(test_var2)) == expected_val);
}
#endif
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
void test_cpp14_visitor(const variant_type& test_var)
{
std::cout << "Testing const lvalue visitable for c++14\n";
BOOST_CHECK(boost::apply_visitor([](auto&& v) { return lcs(v); }, test_var) == lcs(test_var));
}
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_CHECK(boost::apply_visitor([](auto&& v, auto&& vv) { return lcs(v) + '+' + lcs(vv); }, test_var, test_var2) == lcs(test_var) + '+' + lcs(test_var2));
}
void test_cpp14_visitor(variant_type&& test_var)
{
std::cout << "Testing const rvalue visitable for c++14\n";
const auto expected_val = lcs(test_var);
BOOST_CHECK(boost::apply_visitor([](auto&& v) { return lcs(v); }, test_var) == expected_val);
}
void test_cpp14_visitor(variant_type&& test_var, variant_type&& test_var2)
{
std::cout << "Testing const rvalue visitable for c++14\n";
const auto expected_val = lcs(test_var) + '+' + lcs(test_var2);
BOOST_CHECK(boost::apply_visitor([](auto&& v, auto&& vv) { return lcs(v) + '+' + lcs(vv); }, std::move(test_var), std::move(test_var2)) == expected_val);
}
#endif
void run()
{
{
const variant_type v1(1), v2(2);
test_const_ref_parameter(v1);
test_const_ref_parameter2(v1, v2);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
{
variant_type v1(10), v2(20), v3(30);
test_rvalue_parameter(boost::move(v1));
test_rvalue_parameter2(boost::move(v2), boost::move(v3));
}
#endif
#ifndef BOOST_NO_CXX14_DECLTYPE_AUTO
{
variant_type v1(10), v2(20), v3(30);
test_cpp14_visitor(v1);
test_cpp14_visitor(v2, v3);
test_cpp14_visitor(boost::move(v1));
test_cpp14_visitor(boost::move(v2), boost::move(v3));
}
#endif
}
int test_main(int , char* [])
{
run();
return 0;
}