fork(3) download
  1. #include <type_traits>
  2. #include <vector>
  3. #include <iterator>
  4. #include <iostream>
  5.  
  6. template<typename C,typename=void> struct can_reserve: std::false_type {};
  7.  
  8. template<typename T, typename A>
  9. struct can_reserve<std::vector<T,A>,void>:
  10. std::true_type
  11. {};
  12.  
  13. template<int n> struct secret_enum { enum class type {}; };
  14. template<int n>
  15. using SecretEnum = typename secret_enum<n>::type;
  16.  
  17. template<bool b, int override_num=1>
  18. using EnableFuncIf = typename std::enable_if< b, SecretEnum<override_num> >::type;
  19. template<bool b, int override_num=1>
  20. using DisableFuncIf = EnableFuncIf< !b, -override_num >;
  21.  
  22. template<typename C, EnableFuncIf< can_reserve<C>::value >... >
  23. void try_reserve( C& c, std::size_t n ) {
  24. c.reserve(n);
  25. }
  26. template<typename C, DisableFuncIf< can_reserve<C>::value >... >
  27. void try_reserve( C& c, std::size_t ) { } // do nothing
  28.  
  29. template<typename C,typename=void>
  30. struct has_size_method:std::false_type {};
  31. template<typename C>
  32. struct has_size_method<C, typename std::enable_if<std::is_same<
  33. decltype( std::declval<C>().size() ),
  34. decltype( std::declval<C>().size() )
  35. >::value>::type>:std::true_type {};
  36.  
  37. namespace adl_aux {
  38. using std::begin; using std::end;
  39. template<typename C>
  40. auto adl_begin(C&&c)->decltype( begin(std::forward<C>(c)) );
  41. template<typename C>
  42. auto adl_end(C&&c)->decltype( end(std::forward<C>(c)) );
  43. }
  44. template<typename C>
  45. struct iterable_traits {
  46. typedef decltype( adl_aux::adl_begin(std::declval<C&>()) ) iterator;
  47. typedef decltype( adl_aux::adl_begin(std::declval<C const&>()) ) const_iterator;
  48. };
  49. template<typename C> using Iterator = typename iterable_traits<C>::iterator;
  50. template<typename C> using ConstIterator = typename iterable_traits<C>::const_iterator;
  51. template<typename I> using IteratorCategory = typename std::iterator_traits<I>::iterator_category;
  52.  
  53. template<typename C, EnableFuncIf< has_size_method<C>::value, 1>... >
  54. std::size_t size_at_least( C&& c ) {
  55. return c.size();
  56. }
  57.  
  58. template<typename C, EnableFuncIf< !has_size_method<C>::value &&
  59. std::is_base_of< std::random_access_iterator_tag, IteratorCategory<Iterator<C>> >::value, 2>... >
  60. std::size_t size_at_least( C&& c ) {
  61. using std::begin; using std::end;
  62. return end(c)-begin(c);
  63. };
  64. template<typename C, EnableFuncIf< !has_size_method<C>::value &&
  65. !std::is_base_of< std::random_access_iterator_tag, IteratorCategory<Iterator<C>> >::value, 3>... >
  66. std::size_t size_at_least( C&& c ) {
  67. return 0;
  68. };
  69.  
  70. template < typename It >
  71. auto try_make_move_iterator(It i, std::true_type)
  72. -> decltype(make_move_iterator(i))
  73. {
  74. return make_move_iterator(i);
  75. }
  76. template < typename It >
  77. It try_make_move_iterator(It i, ...)
  78. {
  79. return i;
  80. }
  81.  
  82.  
  83. #include <iostream>
  84. template<typename C1, typename C2>
  85. C1&& append_containers( C1&& c1, C2&& c2 )
  86. {
  87. using std::begin; using std::end;
  88. try_reserve( c1, size_at_least(c1) + size_at_least(c2) );
  89.  
  90. using is_rvref = std::is_rvalue_reference<C2&&>;
  91. c1.insert( end(c1),
  92. try_make_move_iterator(begin(c2), is_rvref{}),
  93. try_make_move_iterator(end(c2), is_rvref{}) );
  94.  
  95. return std::forward<C1>(c1);
  96. }
  97.  
  98. struct append_infix_op {} append;
  99. template<typename LHS>
  100. struct append_on_right_op {
  101. LHS lhs;
  102. template<typename RHS>
  103. LHS&& operator=( RHS&& rhs ) {
  104. return append_containers( std::forward<LHS>(lhs), std::forward<RHS>(rhs) );
  105. }
  106. };
  107.  
  108. template<typename LHS>
  109. append_on_right_op<LHS> operator+( LHS&& lhs, append_infix_op ) {
  110. return { std::forward<LHS>(lhs) };
  111. }
  112. template<typename LHS,typename RHS>
  113. typename std::remove_reference<LHS>::type operator+( append_on_right_op<LHS>&& lhs, RHS&& rhs ) {
  114. typename std::decay<LHS>::type retval = std::forward<LHS>(lhs.lhs);
  115. return append_containers( std::move(retval), std::forward<RHS>(rhs) );
  116. }
  117.  
  118. template<typename C>
  119. void print_container( C&& c ) {
  120. for( auto&& x:c )
  121. std::cout << x << ",";
  122. std::cout << "\n";
  123. };
  124.  
  125. int main() {
  126. std::vector<int> a = {0,1,2};
  127. std::vector<int> b = {3,4,5};
  128. print_container(a);
  129. print_container(b);
  130. a +append= b;
  131. const int arr[] = {6,7,8};
  132. a +append= arr;
  133. print_container(a);
  134. print_container(b);
  135. std::vector<double> d = ( std::vector<double>{-3.14, -2, -1} +append= a );
  136. print_container(d);
  137. std::vector<double> c = std::move(d) +append+ a;
  138. print_container(c);
  139. print_container(d);
  140. std::vector<double> e = c +append+ std::move(a);
  141. print_container(e);
  142. print_container(a);
  143. }
  144.  
  145.  
Success #stdin #stdout 0s 2992KB
stdin
Standard input is empty
stdout
0,1,2,
3,4,5,
0,1,2,3,4,5,6,7,8,
3,4,5,
-3.14,-2,-1,0,1,2,3,4,5,6,7,8,
-3.14,-2,-1,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,

-3.14,-2,-1,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,
0,1,2,3,4,5,6,7,8,