Advertisement
Dukales

compose visitors and data holders even non-copyable/moveable

May 18th, 2015
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.29 KB | None | 0 0
  1. #include <iostream>
  2. #include <utility>
  3. #include <functional>
  4. #include <type_traits>
  5.  
  6. #include <cstdlib>
  7. #include <cassert>
  8.  
  9. namespace details
  10. {
  11.    
  12. template< typename visitor >
  13. struct reference_wrapper
  14. {
  15.    
  16.     reference_wrapper(visitor && _visitor)
  17.         : visitor_(std::forward< visitor >(_visitor))
  18.     { ; }
  19.    
  20.     template< typename ...arguments >
  21.     decltype(std::declval< visitor >()(std::declval< arguments >()...)) // sfinae
  22.     operator () (arguments &&... _arguments) const
  23.     {
  24.         return std::forward< visitor >(visitor_)(std::forward< arguments >(_arguments)...);
  25.     }
  26.    
  27.     template< typename ...arguments >
  28.     decltype(std::declval< visitor >()(std::declval< arguments >()...)) // sfinae
  29.     operator () (arguments &&... _arguments)
  30.     {
  31.         return std::forward< visitor >(visitor_)(std::forward< arguments >(_arguments)...);
  32.     }
  33.    
  34. private :
  35.    
  36.     visitor && visitor_;
  37.    
  38. };
  39.    
  40. template< typename type, typename visitor = std::decay_t< type > >
  41. using effective_type = std::conditional_t< std::is_constructible< visitor, type >{}, visitor, reference_wrapper< type > >;
  42.  
  43. template< typename visitor, typename ...visitors >
  44. struct composite_visitor
  45.     : effective_type< visitor >
  46.     , composite_visitor< visitors... >
  47. {
  48.    
  49.     composite_visitor(visitor && _visitor, visitors &&... _visitors)
  50.         : effective_type< visitor >(std::forward< visitor >(_visitor))
  51.         , composite_visitor< visitors... >{std::forward< visitors >(_visitors)...}
  52.     { ; }
  53.    
  54. };
  55.  
  56. template<  typename visitor >
  57. struct composite_visitor< visitor >
  58.     : effective_type< visitor >
  59. {
  60.  
  61.     composite_visitor(visitor && _visitor)
  62.         : effective_type< visitor >(std::forward< visitor >(_visitor))
  63.     { ; }
  64.    
  65. };
  66.  
  67. }
  68.  
  69. template< typename visitor, typename ...visitors >
  70. details::composite_visitor< visitor, visitors... >
  71. compose_visitors(visitor && _visitor, visitors &&... _visitors)
  72. {
  73.     return {std::forward< visitor >(_visitor), std::forward< visitors >(_visitors)...};
  74. }
  75.  
  76. namespace details
  77. {
  78.  
  79. template< typename R, typename visitor >
  80. struct add_result_type
  81.     : effective_type< visitor >
  82. {
  83.  
  84.     using result_type = R;
  85.  
  86.     add_result_type(visitor && _visitor)
  87.         : effective_type< visitor >(std::forward< visitor >(_visitor))
  88.     { ; }
  89.  
  90. };
  91.  
  92. }
  93.  
  94. template< typename result_type = void, typename visitor = void >
  95. details::add_result_type< result_type, visitor >
  96. add_result_type(visitor && _visitor) // for boost::apply_visitor support
  97. {
  98.     return {std::forward< visitor >(_visitor)};
  99. }
  100.  
  101. struct VV
  102. {
  103.    
  104.     template< typename type >
  105.     auto
  106.     operator () (type &&) const
  107.     {
  108.         return 101325;
  109.     }
  110.  
  111. };
  112.  
  113. int
  114. main()
  115. {
  116.     auto const l0 = [] (auto &&) { return 0; };
  117.     auto const l1 = [] (auto const &) { return 1; };
  118.     auto const l2 = [] (auto &) { return 2; };
  119.     auto const l3 = [] (auto const &&) { return 3; };
  120.     auto const l = compose_visitors(l0, l1, l2, l3);
  121.    
  122.     struct A {};
  123.     A const c{};
  124.     A a{};
  125.    
  126.     assert(0 == l(A{}));
  127.     assert(1 == l(c));
  128.     assert(2 == l(a));
  129.     assert(3 == l(std::move(c)));
  130.    
  131.     struct R {};
  132.     auto const rvl = add_result_type< R >(l);
  133.     static_assert(std::is_same< decltype(rvl)::result_type, R >{});
  134.     assert(0 == rvl(A{}));
  135.     assert(1 == rvl(c));
  136.     assert(2 == rvl(a));
  137.     assert(3 == rvl(std::move(c)));
  138.    
  139.     auto const la = compose_visitors(l, [] (A const &) { return -1; });
  140.     assert(0 == la(A{}));
  141.     assert(-1 == la(c));
  142.     assert(2 == la(a));
  143.     assert(3 == la(std::move(c)));
  144.    
  145.     struct V { auto operator () (A const &) && { return -1; } };
  146.     auto lam = compose_visitors(l, V{});
  147.     assert(1 == lam(c));
  148.     assert(-1 == std::move(lam)(c));
  149.    
  150.     struct D0 { int x; };
  151.     struct D1 { int x; };
  152.     auto const ld = compose_visitors(l, D0{123}, D1{321});
  153.     assert(ld.D0::x == 123);
  154.     assert(ld.D1::x == 321);
  155.    
  156.     struct C
  157.     {
  158.         C() = default;
  159.         C(C const &) = delete;
  160.         C(C &&) = delete;
  161.         auto operator () () & { return 100; }
  162.         auto operator () () const & { return 200; }
  163.     };
  164.     C vc;
  165.     assert((compose_visitors(vc)() == 100));
  166.     C const cc{};
  167.     assert((compose_visitors(cc)() == 200));
  168.     return EXIT_SUCCESS;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement