SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
container_helper.hpp
Go to the documentation of this file.
1 /*
2 Copyright© 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef SIG_UTILCONTAINER_TRAITS_H
9 #define SIG_UTILCONTAINER_TRAITS_H
10 
11 
12 #include "eval.hpp"
13 #include "container_traits.hpp"
14 #include "type_convert.hpp"
15 
16 namespace sig
17 {
18 extern void* enabler;
19 
20 namespace impl{
21 
22 #if SIG_ENABLE_MOVEITERATOR
23 template <class C,
24  class RC = typename impl::remove_const_reference<C>::type,
25  typename std::enable_if<std::is_same<C, RC>::value>::type *& = enabler, // C is not const and not lvalue-reference
26  typename std::enable_if<!std::is_same<typename RC::iterator, typename RC::const_iterator>::value>::type*& = enabler // not to return const-iterator
27 >
28 auto begin(C&& c) ->std::move_iterator<typename RC::iterator>
29 {
30  return std::make_move_iterator(std::begin(c));
31 }
32 
33 template <class C,
34  class RC = typename impl::remove_const_reference<C>::type,
35  typename std::enable_if<(!std::is_same<C, RC>::value) || (std::is_same<typename RC::iterator, typename RC::const_iterator>::value)>::type *& = enabler
36 >
37 auto begin(C&& c) ->decltype(std::begin(c))
38 {
39  return std::begin(c);
40 }
41 
42 template <class C,
43  class RC = typename impl::remove_const_reference<C>::type,
44  typename std::enable_if<std::is_same<C, RC>::value>::type *& = enabler, // C is not const and not lvalue-reference
45  typename std::enable_if<!std::is_same<typename RC::iterator, typename RC::const_iterator>::value>::type*& = enabler // not to return const-iterator
46 >
47 auto end(C&& c) ->std::move_iterator<typename RC::iterator>
48 {
49  return std::make_move_iterator(std::end(c));
50 }
51 
52 template <class C,
53  class RC = typename impl::remove_const_reference<C>::type,
54  typename std::enable_if<(!std::is_same<C, RC>::value) || (std::is_same<typename RC::iterator, typename RC::const_iterator>::value)>::type *& = enabler
55 >
56 auto end(C&& c) ->decltype(std::end(c))
57 {
58  return std::end(c);
59 }
60 
61 #else
62 template <class C>
63 auto begin(C&& c) ->decltype(std::begin(c))
64 {
65  return std::begin(c);
66 }
67 
68 template <class C>
69 auto end(C&& c) ->decltype(std::end(c))
70 {
71  return std::end(c);
72 }
73 #endif
74 
75 #if SIG_MSVC_ENV || (SIG_GCC_ENV && SIG_GCC_GT5_0_0) || (SIG_CLANG_ENV)
76 template <class C,
77  class RC = typename impl::remove_const_reference<C>::type,
78  typename std::enable_if<std::is_same<C, RC>::value>::type *& = enabler,
79  typename std::enable_if<!std::is_same<typename RC::reverse_iterator, typename RC::const_reverse_iterator>::value>::type*& = enabler
80 >
81 auto rbegin(C&& c) ->std::move_iterator<typename RC::reverse_iterator>
82 {
83  return std::make_move_iterator(std::rbegin(c));
84 }
85 
86 template <class C,
87  class RC = typename impl::remove_const_reference<C>::type,
88  typename std::enable_if<(!std::is_same<C, RC>::value) || (std::is_same<typename RC::reverse_iterator, typename RC::const_reverse_iterator>::value)>::type *& = enabler
89 >
90 auto rbegin(C&& c) ->decltype(std::rbegin(c))
91 {
92  return std::rbegin(c);
93 }
94 
95 
96 template <class C,
97  class RC = typename impl::remove_const_reference<C>::type,
98  typename std::enable_if<std::is_same<C, RC>::value>::type *& = enabler, // C is not const and not lvalue-reference
99  typename std::enable_if<!std::is_same<typename RC::reverse_iterator, typename RC::const_reverse_iterator>::value>::type*& = enabler // not to return const-iterator
100 >
101 auto rend(C&& c) ->std::move_iterator<typename RC::reverse_iterator>
102 {
103  return std::make_move_iterator(std::rend(c));
104 }
105 
106 template <class C,
107 class RC = typename impl::remove_const_reference<C>::type,
108  typename std::enable_if<(!std::is_same<C, RC>::value) || (std::is_same<typename RC::reverse_iterator, typename RC::const_reverse_iterator>::value)>::type *& = enabler
109 >
110 auto rend(C&& c) ->decltype(std::rend(c))
111 {
112  return std::rend(c);
113 }
114 #endif
115 
116 
117 template<class It>
118 void increment_iterator(It&& iter)
119 {
120  ++iter;
121 }
122 template<class It, class... Its>
123 void increment_iterator(It&& iter, Its&&... iterators)
124 {
125  ++iter;
126  increment_iterator(iterators...);
127 }
128 
129 
130 // コンテナの型に対応した要素型を得る
131 // ex: vector<T> const& -> T const&, list<T>&& -> T&&
132 template <class C, typename std::enable_if<container_traits<typename remove_const_reference<C>::type>::exist>::type*& = enabler>
134 {
135 private:
136  using R1 = typename std::remove_reference<C>::type; // remove reference
137  using RR = typename std::remove_const<R1>::type; // remove const and reference
138  using ET = typename container_traits<RR>::value_type;
139 
140  using CT = typename std::conditional<
141  std::is_const<R1>::value,
142  typename std::add_const<ET>::type,
143  ET
144  >::type; // add const
145 
146  using CRT = typename std::conditional<
147  std::is_lvalue_reference<C>::value,
148  typename std::add_lvalue_reference<CT>::type,
149  typename std::add_rvalue_reference<CT>::type
150  /*typename std::conditional<
151  std::is_rvalue_reference<R2>::value,
152  typename std::add_rvalue_reference<CT>::type,
153  CT
154  >::type*/
155  >::type; // add reference
156 
157 public:
158  using type = CRT;
159 };
160 
161 
162 template<class It>
163 auto dereference_iterator(It&& iter) ->decltype(*std::forward<It>(iter))
164 {
165 /*
166  if(std::is_same<typename std::add_rvalue_reference<decltype(*iter)>::type, typename std::iterator_traits<It>::value_type&>{}) std::cout << "lval&";
167  if(std::is_same<typename std::add_rvalue_reference<decltype(*iter)>::type, typename std::add_const<typename std::iterator_traits<It>::value_type>::type&>{}) std::cout << "const lval&";
168  if(std::is_same<typename std::add_rvalue_reference<decltype(*iter)>::type, typename std::iterator_traits<It>::value_type&&>{}) std::cout << "rval&";
169 std::cout << std::endl;
170 */
171  return *std::forward<It>(iter);
172 }
173 
174 } //impl
175 
176 // 複数のイテレータに対して、loop回数だけ繰り返しデリファレンス+関数適用して結果をdestに格納
177 template <class C, class F, class... Its>
178 void iterative_make(uint loop, C& dest, F&& func, Its... iterators)
179 {
180  for (uint i = 0; i < loop; ++i, impl::increment_iterator(iterators...)){
181  impl::container_traits<C>::add_element(dest, impl::eval(std::forward<F>(func), impl::dereference_iterator(iterators)...));
182  }
183 }
184 
185 // 複数のイテレータに対して、loop回数だけ繰り返しデリファレンス+関数適用して結果をdestに集約
186 template <class T, class F1, class F2, class... Its>
187 void iterative_fold(uint loop, T& dest, F1&& zip, F2&& fold, Its... iterators)
188 {
189  for (uint i = 0; i < loop; ++i, impl::increment_iterator(iterators...)){
190  dest = std::forward<F2>(fold)(dest, impl::eval(std::forward<F1>(zip), impl::dereference_iterator(iterators)...));
191  }
192 }
193 
194 
195 // 複数のイテレータに対して、loop回数だけ繰り返しデリファレンス+関数適用(副作用あり)
196 template <class F, class... Its>
197 void iterative_assign(uint loop, F&& func, Its... iterators)
198 {
199  for (uint i = 0; i < loop; ++i, impl::increment_iterator(iterators...)){
200  std::forward<F>(func)(impl::dereference_iterator(iterators)...);
201  }
202 }
203 template <class F, class... Its>
204 void iterative_assign(uint loop, int init, F&& func, Its... iterators)
205 {
206  for (uint i = 0; i < loop; ++i, impl::increment_iterator(iterators...)){
207  std::forward<F>(func)(i + init, impl::dereference_iterator(iterators)...);
208  }
209 }
210 
211 
212 template <class C>
213 void erase(C& container, typename impl::sequence_container_traits<C>::value_type const& t)
214 {
215  container.erase(std::remove(std::begin(container), std::end(container), t), std::end(container));
216 }
217 
218 template <class C>
219 void erase(C& container, typename impl::associative_container_traits<C>::value_type const& t)
220 {
221  container.erase(t);
222 }
223 
224 template <class C>
225 void erase(C& container, typename impl::hash_container_traits<C>::value_type const& t)
226 {
227  container.erase(t);
228 }
229 
230 
231 template <class C, class F, typename std::enable_if<impl::sequence_container_traits<C>::exist>::type*& = enabler>
232 void erase_if(C& container, F const& remove_pred)
233 {
234  container.erase(std::remove_if(std::begin(container), std::end(container), remove_pred), std::end(container));
235 }
236 
237 template <class C, class F, typename std::enable_if<impl::associative_container_traits<C>::exist>::type*& = enabler>
238 void erase_if(C& container, F const& remove_pred)
239 {
240  for (auto it = std::begin(container), end = std::end(container); it != end;){
241  if (remove_pred(*it)){
242  it = container.erase(it);
243  }
244  else ++it;
245  }
246 }
247 
248 template <class C, class F, typename std::enable_if<impl::hash_container_traits<C>::exist>::type*& = enabler>
249 void erase_if(C& container, F const& remove_pred)
250 {
251  for (auto it = std::begin(container), end = std::end(container); it != end;){
252  if (remove_pred(*it)){
253  it = container.erase(it);
254  }
255  else ++it;
256  }
257 }
258 
259 
261 
268 template <class RC, class C>
269 auto copy(C&& src) ->RC
270 {
271  RC dest = impl::container_traits<RC>::make(src.size());
272 
273  for (auto it = impl::begin(std::forward<C>(src)), end = impl::end(std::forward<C>(src)); it != end; ++it){
275  }
276 
277  return dest;
278 }
279 
280 }
281 
282 #endif
void increment_iterator(It &&iter)
typename std::remove_const< typename std::remove_reference< T >::type >::type type
auto end(C &&c) -> std::move_iterator< typename RC::iterator >
auto rend(C &&c) -> decltype(std::rend(c))
void * enabler
auto rbegin(C &&c) -> std::move_iterator< typename RC::reverse_iterator >
auto end(C &&c) -> decltype(std::end(c))
void iterative_assign(uint loop, F &&func, Its...iterators)
auto rbegin(C &&c) -> decltype(std::rbegin(c))
auto rend(C &&c) -> std::move_iterator< typename RC::reverse_iterator >
auto zip(Cs &&...lists)
複数のコンテナから、タプルのコンテナを作る
Definition: zip.hpp:43
auto dereference_iterator(It &&iter) -> decltype(*std::forward< It >(iter))
void erase(C &container, typename impl::sequence_container_traits< C >::value_type const &t)
auto eval(F &&f, Args &&...args) -> decltype(f(std::forward< Args >(args)...))
Definition: eval.hpp:37
auto begin(C &&c) -> decltype(std::begin(c))
void erase_if(C &container, F const &remove_pred)
void iterative_fold(uint loop, T &dest, F1 &&zip, F2 &&fold, Its...iterators)
Definition: array.hpp:15
auto copy(C &&src) -> RC
別の種類のコンテナに要素をコピーする
auto begin(C &&c) -> std::move_iterator< typename RC::iterator >
void iterative_make(uint loop, C &dest, F &&func, Its...iterators)