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
38namespace boost
39{
40namespace 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
191namespace 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

source code of boost/libs/assign/include/boost/assign/list_inserter.hpp