Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <utility>
- #include <functional>
- #include <type_traits>
- #include <cstdlib>
- #include <cassert>
- namespace details
- {
- template< typename visitor >
- struct reference_wrapper
- {
- reference_wrapper(visitor && _visitor)
- : visitor_(std::forward< visitor >(_visitor))
- { ; }
- template< typename ...arguments >
- decltype(std::declval< visitor >()(std::declval< arguments >()...)) // sfinae
- operator () (arguments &&... _arguments) const
- {
- return std::forward< visitor >(visitor_)(std::forward< arguments >(_arguments)...);
- }
- template< typename ...arguments >
- decltype(std::declval< visitor >()(std::declval< arguments >()...)) // sfinae
- operator () (arguments &&... _arguments)
- {
- return std::forward< visitor >(visitor_)(std::forward< arguments >(_arguments)...);
- }
- private :
- visitor && visitor_;
- };
- template< typename type, typename visitor = std::decay_t< type > >
- using effective_type = std::conditional_t< std::is_constructible< visitor, type >{}, visitor, reference_wrapper< type > >;
- template< typename visitor, typename ...visitors >
- struct composite_visitor
- : effective_type< visitor >
- , composite_visitor< visitors... >
- {
- composite_visitor(visitor && _visitor, visitors &&... _visitors)
- : effective_type< visitor >(std::forward< visitor >(_visitor))
- , composite_visitor< visitors... >{std::forward< visitors >(_visitors)...}
- { ; }
- };
- template< typename visitor >
- struct composite_visitor< visitor >
- : effective_type< visitor >
- {
- composite_visitor(visitor && _visitor)
- : effective_type< visitor >(std::forward< visitor >(_visitor))
- { ; }
- };
- }
- template< typename visitor, typename ...visitors >
- details::composite_visitor< visitor, visitors... >
- compose_visitors(visitor && _visitor, visitors &&... _visitors)
- {
- return {std::forward< visitor >(_visitor), std::forward< visitors >(_visitors)...};
- }
- namespace details
- {
- template< typename R, typename visitor >
- struct add_result_type
- : effective_type< visitor >
- {
- using result_type = R;
- add_result_type(visitor && _visitor)
- : effective_type< visitor >(std::forward< visitor >(_visitor))
- { ; }
- };
- }
- template< typename result_type = void, typename visitor = void >
- details::add_result_type< result_type, visitor >
- add_result_type(visitor && _visitor) // for boost::apply_visitor support
- {
- return {std::forward< visitor >(_visitor)};
- }
- struct VV
- {
- template< typename type >
- auto
- operator () (type &&) const
- {
- return 101325;
- }
- };
- int
- main()
- {
- auto const l0 = [] (auto &&) { return 0; };
- auto const l1 = [] (auto const &) { return 1; };
- auto const l2 = [] (auto &) { return 2; };
- auto const l3 = [] (auto const &&) { return 3; };
- auto const l = compose_visitors(l0, l1, l2, l3);
- struct A {};
- A const c{};
- A a{};
- assert(0 == l(A{}));
- assert(1 == l(c));
- assert(2 == l(a));
- assert(3 == l(std::move(c)));
- struct R {};
- auto const rvl = add_result_type< R >(l);
- static_assert(std::is_same< decltype(rvl)::result_type, R >{});
- assert(0 == rvl(A{}));
- assert(1 == rvl(c));
- assert(2 == rvl(a));
- assert(3 == rvl(std::move(c)));
- auto const la = compose_visitors(l, [] (A const &) { return -1; });
- assert(0 == la(A{}));
- assert(-1 == la(c));
- assert(2 == la(a));
- assert(3 == la(std::move(c)));
- struct V { auto operator () (A const &) && { return -1; } };
- auto lam = compose_visitors(l, V{});
- assert(1 == lam(c));
- assert(-1 == std::move(lam)(c));
- struct D0 { int x; };
- struct D1 { int x; };
- auto const ld = compose_visitors(l, D0{123}, D1{321});
- assert(ld.D0::x == 123);
- assert(ld.D1::x == 321);
- struct C
- {
- C() = default;
- C(C const &) = delete;
- C(C &&) = delete;
- auto operator () () & { return 100; }
- auto operator () () const & { return 200; }
- };
- C vc;
- assert((compose_visitors(vc)() == 100));
- C const cc{};
- assert((compose_visitors(cc)() == 200));
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement