1 | // Boost.Assign library |
2 | // |
3 | // Copyright Thorsten Ottosen 2003-2004. Use, modification and |
4 | // distribution is subject to the Boost Software License, Version |
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // For more information, see http://www.boost.org/libs/assign/ |
9 | // |
10 | |
11 | #ifndef BOOST_ASSIGN_LIST_INSERTER_HPP |
12 | #define BOOST_ASSIGN_LIST_INSERTER_HPP |
13 | |
14 | #if defined(_MSC_VER) |
15 | # pragma once |
16 | #endif |
17 | |
18 | #include <boost/detail/workaround.hpp> |
19 | |
20 | #include <boost/type_traits/conditional.hpp> |
21 | #include <boost/type_traits/is_same.hpp> |
22 | #include <boost/range/begin.hpp> |
23 | #include <boost/range/end.hpp> |
24 | #include <boost/config.hpp> |
25 | #include <boost/move/utility.hpp> |
26 | #include <cstddef> |
27 | |
28 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
29 | |
30 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> |
31 | #include <boost/preprocessor/repetition/enum_params.hpp> |
32 | #include <boost/preprocessor/cat.hpp> |
33 | #include <boost/preprocessor/iteration/local.hpp> |
34 | #include <boost/preprocessor/arithmetic/inc.hpp> |
35 | |
36 | #endif |
37 | |
38 | namespace boost |
39 | { |
40 | namespace assign_detail |
41 | { |
42 | template< class T > |
43 | struct repeater |
44 | { |
45 | std::size_t sz; |
46 | T val; |
47 | |
48 | repeater( std::size_t sz_, T r ) : sz( sz_ ), val( r ) |
49 | { } |
50 | }; |
51 | |
52 | template< class Fun > |
53 | struct fun_repeater |
54 | { |
55 | std::size_t sz; |
56 | Fun val; |
57 | |
58 | fun_repeater( std::size_t sz_, Fun r ) : sz( sz_ ), val( r ) |
59 | { } |
60 | }; |
61 | |
62 | |
63 | template< class T > |
64 | struct is_repeater : boost::false_type {}; |
65 | |
66 | template< class T > |
67 | struct is_repeater< boost::assign_detail::repeater<T> > : boost::true_type{}; |
68 | |
69 | template< class Fun > |
70 | struct is_repeater< boost::assign_detail::fun_repeater<Fun> > : boost::true_type{}; |
71 | |
72 | |
73 | template< class C > |
74 | class call_push_back |
75 | { |
76 | C& c_; |
77 | public: |
78 | call_push_back( C& c ) : c_( c ) |
79 | { } |
80 | |
81 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
82 | template< class T > |
83 | void operator()( T r ) |
84 | { |
85 | c_.push_back( r ); |
86 | } |
87 | #else |
88 | template< class T > |
89 | void operator()(T&& r) |
90 | { |
91 | c_.push_back(boost::forward<T>(r)); |
92 | } |
93 | #endif |
94 | }; |
95 | |
96 | template< class C > |
97 | class call_push_front |
98 | { |
99 | C& c_; |
100 | public: |
101 | call_push_front( C& c ) : c_( c ) |
102 | { } |
103 | |
104 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
105 | template< class T > |
106 | void operator()( T r ) |
107 | { |
108 | c_.push_front( r ); |
109 | } |
110 | #else |
111 | template< class T > |
112 | void operator()(T&& r) |
113 | { |
114 | c_.push_front(boost::forward<T>(r)); |
115 | } |
116 | #endif |
117 | }; |
118 | |
119 | template< class C > |
120 | class call_push |
121 | { |
122 | C& c_; |
123 | public: |
124 | call_push( C& c ) : c_( c ) |
125 | { } |
126 | |
127 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
128 | template< class T > |
129 | void operator()( T r ) |
130 | { |
131 | c_.push( r ); |
132 | } |
133 | #else |
134 | template< class T > |
135 | void operator()(T&& r) |
136 | { |
137 | c_.push(boost::forward<T>(r)); |
138 | } |
139 | #endif |
140 | }; |
141 | |
142 | template< class C > |
143 | class call_insert |
144 | { |
145 | C& c_; |
146 | public: |
147 | call_insert( C& c ) : c_( c ) |
148 | { } |
149 | |
150 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
151 | template< class T > |
152 | void operator()( T r ) |
153 | { |
154 | c_.insert( r ); |
155 | } |
156 | #else |
157 | template< class T > |
158 | void operator()(T&& r) |
159 | { |
160 | c_.insert(boost::forward<T>(r)); |
161 | } |
162 | #endif |
163 | }; |
164 | |
165 | template< class C > |
166 | class call_add_edge |
167 | { |
168 | C& c_; |
169 | public: |
170 | call_add_edge( C& c ) : c_(c) |
171 | { } |
172 | |
173 | template< class T > |
174 | void operator()( T l, T r ) |
175 | { |
176 | add_edge( l, r, c_ ); |
177 | } |
178 | |
179 | template< class T, class EP > |
180 | void operator()( T l, T r, const EP& ep ) |
181 | { |
182 | add_edge( l, r, ep, c_ ); |
183 | } |
184 | |
185 | }; |
186 | |
187 | struct forward_n_arguments {}; |
188 | |
189 | } // namespace 'assign_detail' |
190 | |
191 | namespace assign |
192 | { |
193 | |
194 | template< class T > |
195 | inline assign_detail::repeater<T> |
196 | repeat( std::size_t sz, T r ) |
197 | { |
198 | return assign_detail::repeater<T>( sz, r ); |
199 | } |
200 | |
201 | template< class Function > |
202 | inline assign_detail::fun_repeater<Function> |
203 | repeat_fun( std::size_t sz, Function r ) |
204 | { |
205 | return assign_detail::fun_repeater<Function>( sz, r ); |
206 | } |
207 | |
208 | |
209 | template< class Function, class Argument = assign_detail::forward_n_arguments > |
210 | class list_inserter |
211 | { |
212 | struct single_arg_type {}; |
213 | struct n_arg_type {}; |
214 | struct repeater_arg_type {}; |
215 | |
216 | typedef BOOST_DEDUCED_TYPENAME ::boost::conditional< |
217 | is_same<Argument,assign_detail::forward_n_arguments>::value, |
218 | n_arg_type, |
219 | single_arg_type >::type arg_type; |
220 | |
221 | public: |
222 | |
223 | list_inserter( Function fun ) : insert_( fun ) |
224 | {} |
225 | |
226 | template< class Function2, class Arg > |
227 | list_inserter( const list_inserter<Function2,Arg>& r ) |
228 | : insert_( r.fun_private() ) |
229 | {} |
230 | |
231 | list_inserter( const list_inserter& r ) : insert_( r.insert_ ) |
232 | {} |
233 | |
234 | list_inserter& operator()() |
235 | { |
236 | insert_( Argument() ); |
237 | return *this; |
238 | } |
239 | |
240 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
241 | template< class T > |
242 | list_inserter& operator=( const T& r ) |
243 | { |
244 | insert_( r ); |
245 | return *this; |
246 | } |
247 | |
248 | template< class T > |
249 | list_inserter& operator=( assign_detail::repeater<T> r ) |
250 | { |
251 | return operator,( r ); |
252 | } |
253 | |
254 | template< class Nullary_function > |
255 | list_inserter& operator=( const assign_detail::fun_repeater<Nullary_function>& r ) |
256 | { |
257 | return operator,( r ); |
258 | } |
259 | |
260 | template< class T > |
261 | list_inserter& operator,( const T& r ) |
262 | { |
263 | insert_( r ); |
264 | return *this; |
265 | } |
266 | |
267 | #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) |
268 | template< class T > |
269 | list_inserter& operator,( const assign_detail::repeater<T> & r ) |
270 | { |
271 | return repeat( r.sz, r.val ); |
272 | } |
273 | #else |
274 | template< class T > |
275 | list_inserter& operator,( assign_detail::repeater<T> r ) |
276 | { |
277 | return repeat( r.sz, r.val ); |
278 | } |
279 | #endif |
280 | |
281 | template< class Nullary_function > |
282 | list_inserter& operator,( const assign_detail::fun_repeater<Nullary_function>& r ) |
283 | { |
284 | return repeat_fun( r.sz, r.val ); |
285 | } |
286 | #else |
287 | // BOOST_NO_CXX11_RVALUE_REFERENCES |
288 | template< class T > |
289 | list_inserter& operator=(T&& r) |
290 | { |
291 | return operator,(boost::forward<T>(r)); |
292 | } |
293 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
294 | template< class T > |
295 | list_inserter& operator,(T&& r) |
296 | { |
297 | typedef BOOST_DEDUCED_TYPENAME ::boost::conditional< |
298 | assign_detail::is_repeater< T >::value, |
299 | repeater_arg_type, |
300 | arg_type >::type tag; |
301 | |
302 | insert(boost::forward<T>(r), tag()); |
303 | return *this; |
304 | } |
305 | #else |
306 | // we add the tag as the first argument when using variadic templates |
307 | template< class T > |
308 | list_inserter& operator,(T&& r) |
309 | { |
310 | typedef BOOST_DEDUCED_TYPENAME ::boost::conditional< |
311 | assign_detail::is_repeater< T >::value, |
312 | repeater_arg_type, |
313 | arg_type >::type tag; |
314 | |
315 | insert(tag(), boost::forward<T>(r)); |
316 | return *this; |
317 | } |
318 | #endif |
319 | #endif |
320 | |
321 | template< class T > |
322 | list_inserter& repeat( std::size_t sz, T r ) |
323 | { |
324 | std::size_t i = 0; |
325 | while( i++ != sz ) |
326 | insert_( r ); |
327 | return *this; |
328 | } |
329 | |
330 | template< class Nullary_function > |
331 | list_inserter& repeat_fun( std::size_t sz, Nullary_function fun ) |
332 | { |
333 | std::size_t i = 0; |
334 | while( i++ != sz ) |
335 | insert_( fun() ); |
336 | return *this; |
337 | } |
338 | |
339 | template< class SinglePassIterator > |
340 | list_inserter& range( SinglePassIterator first, |
341 | SinglePassIterator last ) |
342 | { |
343 | for( ; first != last; ++first ) |
344 | insert_( *first ); |
345 | return *this; |
346 | } |
347 | |
348 | template< class SinglePassRange > |
349 | list_inserter& range( const SinglePassRange& r ) |
350 | { |
351 | return range( boost::begin(r), boost::end(r) ); |
352 | } |
353 | |
354 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
355 | template< class T > |
356 | list_inserter& operator()( const T& t ) |
357 | { |
358 | insert_( t ); |
359 | return *this; |
360 | } |
361 | |
362 | #ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value |
363 | #define BOOST_ASSIGN_MAX_PARAMS 5 |
364 | #endif |
365 | #define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) |
366 | #define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T) |
367 | #define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t) |
368 | #define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t) |
369 | |
370 | #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) |
371 | #define BOOST_PP_LOCAL_MACRO(n) \ |
372 | template< class T, BOOST_ASSIGN_PARAMS1(n) > \ |
373 | list_inserter& operator()(T t, BOOST_ASSIGN_PARAMS2(n) ) \ |
374 | { \ |
375 | BOOST_PP_CAT(insert, BOOST_PP_INC(n))(t, BOOST_ASSIGN_PARAMS3(n), arg_type()); \ |
376 | return *this; \ |
377 | } \ |
378 | /**/ |
379 | |
380 | #include BOOST_PP_LOCAL_ITERATE() |
381 | |
382 | |
383 | #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) |
384 | #define BOOST_PP_LOCAL_MACRO(n) \ |
385 | template< class T, BOOST_ASSIGN_PARAMS1(n) > \ |
386 | void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), single_arg_type) \ |
387 | { \ |
388 | insert_( Argument(t, BOOST_ASSIGN_PARAMS3(n) )); \ |
389 | } \ |
390 | /**/ |
391 | |
392 | #include BOOST_PP_LOCAL_ITERATE() |
393 | |
394 | #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) |
395 | #define BOOST_PP_LOCAL_MACRO(n) \ |
396 | template< class T, BOOST_ASSIGN_PARAMS1(n) > \ |
397 | void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), n_arg_type) \ |
398 | { \ |
399 | insert_(t, BOOST_ASSIGN_PARAMS3(n) ); \ |
400 | } \ |
401 | /**/ |
402 | |
403 | #include BOOST_PP_LOCAL_ITERATE() |
404 | |
405 | #else |
406 | template< class... Ts > |
407 | list_inserter& operator()(Ts&&... ts) |
408 | { |
409 | insert(arg_type(), boost::forward<Ts>(ts)...); |
410 | return *this; |
411 | } |
412 | |
413 | template< class T > |
414 | void insert(single_arg_type, T&& t) |
415 | { |
416 | // Special implementation for single argument overload to prevent accidental casts (type-cast using functional notation) |
417 | insert_(boost::forward<T>(t)); |
418 | } |
419 | |
420 | template< class T1, class T2, class... Ts > |
421 | void insert(single_arg_type, T1&& t1, T2&& t2, Ts&&... ts) |
422 | { |
423 | insert_(Argument(boost::forward<T1>(t1), boost::forward<T2>(t2), boost::forward<Ts>(ts)...)); |
424 | } |
425 | |
426 | template< class... Ts > |
427 | void insert(n_arg_type, Ts&&... ts) |
428 | { |
429 | insert_(boost::forward<Ts>(ts)...); |
430 | } |
431 | |
432 | #endif |
433 | |
434 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
435 | |
436 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
437 | |
438 | template< class T > |
439 | void insert( T&& r, arg_type) |
440 | { |
441 | insert_( boost::forward<T>(r) ); |
442 | } |
443 | |
444 | template< class T > |
445 | void insert(assign_detail::repeater<T> r, repeater_arg_type) |
446 | { |
447 | repeat(r.sz, r.val); |
448 | } |
449 | |
450 | template< class Nullary_function > |
451 | void insert(const assign_detail::fun_repeater<Nullary_function>& r, repeater_arg_type) |
452 | { |
453 | repeat_fun(r.sz, r.val); |
454 | } |
455 | #else |
456 | template< class T > |
457 | void insert(repeater_arg_type, assign_detail::repeater<T> r) |
458 | { |
459 | repeat(r.sz, r.val); |
460 | } |
461 | |
462 | template< class Nullary_function > |
463 | void insert(repeater_arg_type, const assign_detail::fun_repeater<Nullary_function>& r) |
464 | { |
465 | repeat_fun(r.sz, r.val); |
466 | } |
467 | #endif |
468 | #endif |
469 | |
470 | |
471 | Function fun_private() const |
472 | { |
473 | return insert_; |
474 | } |
475 | |
476 | private: |
477 | |
478 | list_inserter& operator=( const list_inserter& ); |
479 | Function insert_; |
480 | }; |
481 | |
482 | template< class Function > |
483 | inline list_inserter< Function > |
484 | make_list_inserter( Function fun ) |
485 | { |
486 | return list_inserter< Function >( fun ); |
487 | } |
488 | |
489 | template< class Function, class Argument > |
490 | inline list_inserter<Function,Argument> |
491 | make_list_inserter( Function fun, Argument* ) |
492 | { |
493 | return list_inserter<Function,Argument>( fun ); |
494 | } |
495 | |
496 | template< class C > |
497 | inline list_inserter< assign_detail::call_push_back<C>, |
498 | BOOST_DEDUCED_TYPENAME C::value_type > |
499 | push_back( C& c ) |
500 | { |
501 | static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; |
502 | return make_list_inserter( assign_detail::call_push_back<C>( c ), |
503 | p ); |
504 | } |
505 | |
506 | template< class C > |
507 | inline list_inserter< assign_detail::call_push_front<C>, |
508 | BOOST_DEDUCED_TYPENAME C::value_type > |
509 | push_front( C& c ) |
510 | { |
511 | static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; |
512 | return make_list_inserter( assign_detail::call_push_front<C>( c ), |
513 | p ); |
514 | } |
515 | |
516 | template< class C > |
517 | inline list_inserter< assign_detail::call_insert<C>, |
518 | BOOST_DEDUCED_TYPENAME C::value_type > |
519 | insert( C& c ) |
520 | { |
521 | static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; |
522 | return make_list_inserter( assign_detail::call_insert<C>( c ), |
523 | p ); |
524 | } |
525 | |
526 | template< class C > |
527 | inline list_inserter< assign_detail::call_push<C>, |
528 | BOOST_DEDUCED_TYPENAME C::value_type > |
529 | push( C& c ) |
530 | { |
531 | static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; |
532 | return make_list_inserter( assign_detail::call_push<C>( c ), |
533 | p ); |
534 | } |
535 | |
536 | template< class C > |
537 | inline list_inserter< assign_detail::call_add_edge<C> > |
538 | add_edge( C& c ) |
539 | { |
540 | return make_list_inserter( assign_detail::call_add_edge<C>( c ) ); |
541 | } |
542 | |
543 | } // namespace 'assign' |
544 | } // namespace 'boost' |
545 | |
546 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
547 | |
548 | #undef BOOST_ASSIGN_PARAMS1 |
549 | #undef BOOST_ASSIGN_PARAMS2 |
550 | #undef BOOST_ASSIGN_PARAMS3 |
551 | #undef BOOST_ASSIGN_MAX_PARAMETERS |
552 | |
553 | #endif |
554 | |
555 | #endif |
556 | |