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/mpl/if.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 
repeaterboost::assign_detail::repeater48         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 
fun_repeaterboost::assign_detail::fun_repeater58         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:
call_push_back(C & c)78         call_push_back( C& c ) : c_( c )
79         { }
80 
81 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
82         template< class T >
operator ()(T r)83         void operator()( T r )
84         {
85             c_.push_back( r );
86         }
87 #else
88         template< class T >
operator ()(T && r)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:
call_push_front(C & c)101         call_push_front( C& c ) : c_( c )
102         { }
103 
104 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
105         template< class T >
operator ()(T r)106         void operator()( T r )
107         {
108             c_.push_front( r );
109         }
110 #else
111         template< class T >
operator ()(T && r)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:
call_push(C & c)124         call_push( C& c ) : c_( c )
125         { }
126 
127 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
128         template< class T >
operator ()(T r)129         void operator()( T r )
130         {
131             c_.push( r );
132         }
133 #else
134         template< class T >
operator ()(T && r)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:
call_insert(C & c)147         call_insert( C& c ) : c_( c )
148         { }
149 
150 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
151         template< class T >
operator ()(T r)152         void operator()( T r )
153         {
154             c_.insert( r );
155         }
156 #else
157         template< class T >
operator ()(T && r)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:
call_add_edge(C & c)170         call_add_edge( C& c ) : c_(c)
171         { }
172 
173         template< class T >
operator ()(T l,T r)174         void operator()( T l, T r )
175         {
176             add_edge( l, r, c_ );
177         }
178 
179         template< class T, class EP >
operator ()(T l,T r,const EP & 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>
repeat(std::size_t sz,T r)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>
repeat_fun(std::size_t sz,Function r)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 mpl::if_c< is_same<Argument,assign_detail::forward_n_arguments>::value,
217                                                   n_arg_type,
218                                                   single_arg_type >::type arg_type;
219 
220     public:
221 
list_inserter(Function fun)222         list_inserter( Function fun ) : insert_( fun )
223         {}
224 
225         template< class Function2, class Arg >
list_inserter(const list_inserter<Function2,Arg> & r)226         list_inserter( const list_inserter<Function2,Arg>& r )
227         : insert_( r.fun_private() )
228         {}
229 
list_inserter(const list_inserter & r)230         list_inserter( const list_inserter& r ) : insert_( r.insert_ )
231         {}
232 
operator ()()233         list_inserter& operator()()
234         {
235             insert_( Argument() );
236             return *this;
237         }
238 
239 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
240         template< class T >
operator =(const T & r)241         list_inserter& operator=( const T& r )
242         {
243             insert_( r );
244             return *this;
245         }
246 
247         template< class T >
operator =(assign_detail::repeater<T> r)248         list_inserter& operator=( assign_detail::repeater<T> r )
249         {
250             return operator,( r );
251         }
252 
253         template< class Nullary_function >
operator =(const assign_detail::fun_repeater<Nullary_function> & r)254         list_inserter& operator=( const assign_detail::fun_repeater<Nullary_function>& r )
255         {
256             return operator,( r );
257         }
258 
259         template< class T >
operator ,(const T & r)260         list_inserter& operator,( const T& r )
261         {
262             insert_( r  );
263             return *this;
264         }
265 
266 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
267         template< class T >
operator ,(const assign_detail::repeater<T> & r)268         list_inserter& operator,( const assign_detail::repeater<T> & r )
269         {
270             return repeat( r.sz, r.val );
271         }
272 #else
273         template< class T >
operator ,(assign_detail::repeater<T> r)274         list_inserter& operator,( assign_detail::repeater<T> r )
275         {
276             return repeat( r.sz, r.val );
277         }
278 #endif
279 
280         template< class Nullary_function >
operator ,(const assign_detail::fun_repeater<Nullary_function> & r)281         list_inserter& operator,( const assign_detail::fun_repeater<Nullary_function>& r )
282         {
283             return repeat_fun( r.sz, r.val );
284         }
285 #else
286         // BOOST_NO_CXX11_RVALUE_REFERENCES
287         template< class T >
operator =(T && r)288         list_inserter& operator=(T&& r)
289         {
290             return operator,(boost::forward<T>(r));
291         }
292 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
293         template< class T >
operator ,(T && r)294         list_inserter& operator,(T&& r)
295         {
296             typedef BOOST_DEDUCED_TYPENAME mpl::if_c< assign_detail::is_repeater< T >::value,
297                 repeater_arg_type,
298                 arg_type >::type tag;
299 
300             insert(boost::forward<T>(r), tag());
301             return *this;
302         }
303 #else
304         // we add the tag as the first argument when using variadic templates
305         template< class T >
operator ,(T && r)306         list_inserter& operator,(T&& r)
307         {
308             typedef BOOST_DEDUCED_TYPENAME mpl::if_c< assign_detail::is_repeater< T >::value,
309                 repeater_arg_type,
310                 arg_type >::type tag;
311 
312             insert(tag(), boost::forward<T>(r));
313             return *this;
314         }
315 #endif
316 #endif
317 
318         template< class T >
repeat(std::size_t sz,T r)319         list_inserter& repeat( std::size_t sz, T r )
320         {
321             std::size_t i = 0;
322             while( i++ != sz )
323                 insert_( r );
324             return *this;
325         }
326 
327         template< class Nullary_function >
repeat_fun(std::size_t sz,Nullary_function fun)328         list_inserter& repeat_fun( std::size_t sz, Nullary_function fun )
329         {
330             std::size_t i = 0;
331             while( i++ != sz )
332                 insert_( fun() );
333             return *this;
334         }
335 
336         template< class SinglePassIterator >
range(SinglePassIterator first,SinglePassIterator last)337         list_inserter& range( SinglePassIterator first,
338                               SinglePassIterator last )
339         {
340             for( ; first != last; ++first )
341                 insert_( *first );
342             return *this;
343         }
344 
345         template< class SinglePassRange >
range(const SinglePassRange & r)346         list_inserter& range( const SinglePassRange& r )
347         {
348             return range( boost::begin(r), boost::end(r) );
349         }
350 
351 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
352         template< class T >
operator ()(const T & t)353         list_inserter& operator()( const T& t )
354         {
355             insert_( t );
356             return *this;
357         }
358 
359 #ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value
360 #define BOOST_ASSIGN_MAX_PARAMS 5
361 #endif
362 #define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1)
363 #define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T)
364 #define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t)
365 #define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t)
366 
367 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
368 #define BOOST_PP_LOCAL_MACRO(n) \
369     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
370     list_inserter& operator()(T t, BOOST_ASSIGN_PARAMS2(n) ) \
371         { \
372             BOOST_PP_CAT(insert, BOOST_PP_INC(n))(t, BOOST_ASSIGN_PARAMS3(n), arg_type()); \
373             return *this; \
374         } \
375         /**/
376 
377 #include BOOST_PP_LOCAL_ITERATE()
378 
379 
380 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
381 #define BOOST_PP_LOCAL_MACRO(n) \
382     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
383     void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), single_arg_type) \
384     { \
385         insert_( Argument(t, BOOST_ASSIGN_PARAMS3(n) )); \
386     } \
387     /**/
388 
389 #include BOOST_PP_LOCAL_ITERATE()
390 
391 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
392 #define BOOST_PP_LOCAL_MACRO(n) \
393     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
394     void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), n_arg_type) \
395     { \
396         insert_(t, BOOST_ASSIGN_PARAMS3(n) ); \
397     } \
398     /**/
399 
400 #include BOOST_PP_LOCAL_ITERATE()
401 
402 #else
403         template< class... Ts >
operator ()(Ts &&...ts)404         list_inserter& operator()(Ts&&... ts)
405         {
406             insert(arg_type(), boost::forward<Ts>(ts)...);
407             return *this;
408         }
409 
410         template< class T >
insert(single_arg_type,T && t)411         void insert(single_arg_type, T&& t)
412         {
413             // Special implementation for single argument overload to prevent accidental casts (type-cast using functional notation)
414             insert_(boost::forward<T>(t));
415         }
416 
417         template< class T1, class T2, class... Ts >
insert(single_arg_type,T1 && t1,T2 && t2,Ts &&...ts)418         void insert(single_arg_type, T1&& t1, T2&& t2, Ts&&... ts)
419         {
420             insert_(Argument(boost::forward<T1>(t1), boost::forward<T2>(t2), boost::forward<Ts>(ts)...));
421         }
422 
423         template< class... Ts >
insert(n_arg_type,Ts &&...ts)424         void insert(n_arg_type, Ts&&... ts)
425         {
426             insert_(boost::forward<Ts>(ts)...);
427         }
428 
429 #endif
430 
431 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
432 
433 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
434 
435         template< class T >
insert(T && r,arg_type)436         void insert( T&& r, arg_type)
437         {
438             insert_( boost::forward<T>(r) );
439         }
440 
441         template< class T >
insert(assign_detail::repeater<T> r,repeater_arg_type)442         void insert(assign_detail::repeater<T> r, repeater_arg_type)
443         {
444             repeat(r.sz, r.val);
445         }
446 
447         template< class Nullary_function >
insert(const assign_detail::fun_repeater<Nullary_function> & r,repeater_arg_type)448         void insert(const assign_detail::fun_repeater<Nullary_function>& r, repeater_arg_type)
449         {
450             repeat_fun(r.sz, r.val);
451         }
452 #else
453         template< class T >
insert(repeater_arg_type,assign_detail::repeater<T> r)454         void insert(repeater_arg_type, assign_detail::repeater<T> r)
455         {
456             repeat(r.sz, r.val);
457         }
458 
459         template< class Nullary_function >
insert(repeater_arg_type,const assign_detail::fun_repeater<Nullary_function> & r)460         void insert(repeater_arg_type, const assign_detail::fun_repeater<Nullary_function>& r)
461         {
462             repeat_fun(r.sz, r.val);
463         }
464 #endif
465 #endif
466 
467 
fun_private() const468         Function fun_private() const
469         {
470             return insert_;
471         }
472 
473     private:
474 
475         list_inserter& operator=( const list_inserter& );
476         Function insert_;
477     };
478 
479     template< class Function >
480     inline list_inserter< Function >
make_list_inserter(Function fun)481     make_list_inserter( Function fun )
482     {
483         return list_inserter< Function >( fun );
484     }
485 
486     template< class Function, class Argument >
487     inline list_inserter<Function,Argument>
make_list_inserter(Function fun,Argument *)488     make_list_inserter( Function fun, Argument* )
489     {
490         return list_inserter<Function,Argument>( fun );
491     }
492 
493     template< class C >
494     inline list_inserter< assign_detail::call_push_back<C>,
495                           BOOST_DEDUCED_TYPENAME C::value_type >
push_back(C & c)496     push_back( C& c )
497     {
498         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
499         return make_list_inserter( assign_detail::call_push_back<C>( c ),
500                                    p );
501     }
502 
503     template< class C >
504     inline list_inserter< assign_detail::call_push_front<C>,
505                           BOOST_DEDUCED_TYPENAME C::value_type >
push_front(C & c)506     push_front( C& c )
507     {
508         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
509         return make_list_inserter( assign_detail::call_push_front<C>( c ),
510                                    p );
511     }
512 
513     template< class C >
514     inline list_inserter< assign_detail::call_insert<C>,
515                           BOOST_DEDUCED_TYPENAME C::value_type >
insert(C & c)516     insert( C& c )
517     {
518         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
519         return make_list_inserter( assign_detail::call_insert<C>( c ),
520                                    p );
521     }
522 
523     template< class C >
524     inline list_inserter< assign_detail::call_push<C>,
525                           BOOST_DEDUCED_TYPENAME C::value_type >
push(C & c)526     push( C& c )
527     {
528         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
529         return make_list_inserter( assign_detail::call_push<C>( c ),
530                                    p );
531     }
532 
533     template< class C >
534     inline list_inserter< assign_detail::call_add_edge<C> >
add_edge(C & c)535     add_edge( C& c )
536     {
537         return make_list_inserter( assign_detail::call_add_edge<C>( c ) );
538     }
539 
540 } // namespace 'assign'
541 } // namespace 'boost'
542 
543 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
544 
545 #undef BOOST_ASSIGN_PARAMS1
546 #undef BOOST_ASSIGN_PARAMS2
547 #undef BOOST_ASSIGN_PARAMS3
548 #undef BOOST_ASSIGN_MAX_PARAMETERS
549 
550 #endif
551 
552 #endif
553