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 <cstddef>
26 
27 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
28 #include <boost/preprocessor/repetition/enum_params.hpp>
29 #include <boost/preprocessor/cat.hpp>
30 #include <boost/preprocessor/iteration/local.hpp>
31 #include <boost/preprocessor/arithmetic/inc.hpp>
32 
33 namespace boost
34 {
35 namespace assign_detail
36 {
37     template< class T >
38     struct repeater
39     {
40         std::size_t  sz;
41         T            val;
42 
repeaterboost::assign_detail::repeater43         repeater( std::size_t sz_, T r ) : sz( sz_ ), val( r )
44         { }
45     };
46 
47     template< class Fun >
48     struct fun_repeater
49     {
50         std::size_t  sz;
51         Fun          val;
52 
fun_repeaterboost::assign_detail::fun_repeater53         fun_repeater( std::size_t sz_, Fun r ) : sz( sz_ ), val( r )
54         { }
55     };
56 
57     template< class C >
58     class call_push_back
59     {
60         C& c_;
61     public:
call_push_back(C & c)62         call_push_back( C& c ) : c_( c )
63         { }
64 
65         template< class T >
operator ()(T r)66         void operator()( T r )
67         {
68             c_.push_back( r );
69         }
70     };
71 
72     template< class C >
73     class call_push_front
74     {
75         C& c_;
76     public:
call_push_front(C & c)77         call_push_front( C& c ) : c_( c )
78         { }
79 
80         template< class T >
operator ()(T r)81         void operator()( T r )
82         {
83             c_.push_front( r );
84         }
85     };
86 
87     template< class C >
88     class call_push
89     {
90         C& c_;
91     public:
call_push(C & c)92         call_push( C& c ) : c_( c )
93         { }
94 
95         template< class T >
operator ()(T r)96         void operator()( T r )
97         {
98             c_.push( r );
99         }
100     };
101 
102     template< class C >
103     class call_insert
104     {
105         C& c_;
106     public:
call_insert(C & c)107         call_insert( C& c ) : c_( c )
108         { }
109 
110         template< class T >
operator ()(T r)111         void operator()( T r )
112         {
113             c_.insert( r );
114         }
115     };
116 
117     template< class C >
118     class call_add_edge
119     {
120         C& c_;
121     public:
call_add_edge(C & c)122         call_add_edge( C& c ) : c_(c)
123         { }
124 
125         template< class T >
operator ()(T l,T r)126         void operator()( T l, T r )
127         {
128             add_edge( l, r, c_ );
129         }
130 
131         template< class T, class EP >
operator ()(T l,T r,const EP & ep)132         void operator()( T l, T r, const EP& ep )
133         {
134             add_edge( l, r, ep, c_ );
135         }
136 
137     };
138 
139     struct forward_n_arguments {};
140 
141 } // namespace 'assign_detail'
142 
143 namespace assign
144 {
145 
146     template< class T >
147     inline assign_detail::repeater<T>
repeat(std::size_t sz,T r)148     repeat( std::size_t sz, T r )
149     {
150         return assign_detail::repeater<T>( sz, r );
151     }
152 
153     template< class Function >
154     inline assign_detail::fun_repeater<Function>
repeat_fun(std::size_t sz,Function r)155     repeat_fun( std::size_t sz, Function r )
156     {
157         return assign_detail::fun_repeater<Function>( sz, r );
158     }
159 
160 
161     template< class Function, class Argument = assign_detail::forward_n_arguments >
162     class list_inserter
163     {
164         struct single_arg_type {};
165         struct n_arg_type      {};
166 
167         typedef BOOST_DEDUCED_TYPENAME mpl::if_c< is_same<Argument,assign_detail::forward_n_arguments>::value,
168                                                   n_arg_type,
169                                                   single_arg_type >::type arg_type;
170 
171     public:
172 
list_inserter(Function fun)173         list_inserter( Function fun ) : insert_( fun )
174         {}
175 
176         template< class Function2, class Arg >
list_inserter(const list_inserter<Function2,Arg> & r)177         list_inserter( const list_inserter<Function2,Arg>& r )
178         : insert_( r.fun_private() )
179         {}
180 
list_inserter(const list_inserter & r)181         list_inserter( const list_inserter& r ) : insert_( r.insert_ )
182         {}
183 
operator ()()184         list_inserter& operator()()
185         {
186             insert_( Argument() );
187             return *this;
188         }
189 
190         template< class T >
operator =(const T & r)191         list_inserter& operator=( const T& r )
192         {
193             insert_( r );
194             return *this;
195         }
196 
197         template< class T >
operator =(assign_detail::repeater<T> r)198         list_inserter& operator=( assign_detail::repeater<T> r )
199         {
200             return operator,( r );
201         }
202 
203         template< class Nullary_function >
operator =(const assign_detail::fun_repeater<Nullary_function> & r)204         list_inserter& operator=( const assign_detail::fun_repeater<Nullary_function>& r )
205         {
206             return operator,( r );
207         }
208 
209         template< class T >
operator ,(const T & r)210         list_inserter& operator,( const T& r )
211         {
212             insert_( r  );
213             return *this;
214         }
215 
216 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
217         template< class T >
operator ,(const assign_detail::repeater<T> & r)218         list_inserter& operator,( const assign_detail::repeater<T> & r )
219         {
220             return repeat( r.sz, r.val );
221         }
222 #else
223         template< class T >
operator ,(assign_detail::repeater<T> r)224         list_inserter& operator,( assign_detail::repeater<T> r )
225         {
226             return repeat( r.sz, r.val );
227         }
228 #endif
229 
230         template< class Nullary_function >
operator ,(const assign_detail::fun_repeater<Nullary_function> & r)231         list_inserter& operator,( const assign_detail::fun_repeater<Nullary_function>& r )
232         {
233             return repeat_fun( r.sz, r.val );
234         }
235 
236         template< class T >
repeat(std::size_t sz,T r)237         list_inserter& repeat( std::size_t sz, T r )
238         {
239             std::size_t i = 0;
240             while( i++ != sz )
241                 insert_( r );
242             return *this;
243         }
244 
245         template< class Nullary_function >
repeat_fun(std::size_t sz,Nullary_function fun)246         list_inserter& repeat_fun( std::size_t sz, Nullary_function fun )
247         {
248             std::size_t i = 0;
249             while( i++ != sz )
250                 insert_( fun() );
251             return *this;
252         }
253 
254         template< class SinglePassIterator >
range(SinglePassIterator first,SinglePassIterator last)255         list_inserter& range( SinglePassIterator first,
256                               SinglePassIterator last )
257         {
258             for( ; first != last; ++first )
259                 insert_( *first );
260             return *this;
261         }
262 
263         template< class SinglePassRange >
range(const SinglePassRange & r)264         list_inserter& range( const SinglePassRange& r )
265         {
266             return range( boost::begin(r), boost::end(r) );
267         }
268 
269         template< class T >
operator ()(const T & t)270         list_inserter& operator()( const T& t )
271         {
272             insert_( t );
273             return *this;
274         }
275 
276 #ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value
277 #define BOOST_ASSIGN_MAX_PARAMS 5
278 #endif
279 #define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1)
280 #define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T)
281 #define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t)
282 #define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t)
283 
284 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
285 #define BOOST_PP_LOCAL_MACRO(n) \
286     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
287     list_inserter& operator()(T t, BOOST_ASSIGN_PARAMS2(n) ) \
288         { \
289             BOOST_PP_CAT(insert, BOOST_PP_INC(n))(t, BOOST_ASSIGN_PARAMS3(n), arg_type()); \
290             return *this; \
291         } \
292         /**/
293 
294 #include BOOST_PP_LOCAL_ITERATE()
295 
296 
297 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
298 #define BOOST_PP_LOCAL_MACRO(n) \
299     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
300     void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), single_arg_type) \
301     { \
302         insert_( Argument(t, BOOST_ASSIGN_PARAMS3(n) )); \
303     } \
304     /**/
305 
306 #include BOOST_PP_LOCAL_ITERATE()
307 
308 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
309 #define BOOST_PP_LOCAL_MACRO(n) \
310     template< class T, BOOST_ASSIGN_PARAMS1(n) > \
311     void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), n_arg_type) \
312     { \
313         insert_(t, BOOST_ASSIGN_PARAMS3(n) ); \
314     } \
315     /**/
316 
317 #include BOOST_PP_LOCAL_ITERATE()
318 
319 
fun_private() const320         Function fun_private() const
321         {
322             return insert_;
323         }
324 
325     private:
326 
327         list_inserter& operator=( const list_inserter& );
328         Function insert_;
329     };
330 
331     template< class Function >
332     inline list_inserter< Function >
make_list_inserter(Function fun)333     make_list_inserter( Function fun )
334     {
335         return list_inserter< Function >( fun );
336     }
337 
338     template< class Function, class Argument >
339     inline list_inserter<Function,Argument>
make_list_inserter(Function fun,Argument *)340     make_list_inserter( Function fun, Argument* )
341     {
342         return list_inserter<Function,Argument>( fun );
343     }
344 
345     template< class C >
346     inline list_inserter< assign_detail::call_push_back<C>,
347                           BOOST_DEDUCED_TYPENAME C::value_type >
push_back(C & c)348     push_back( C& c )
349     {
350         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
351         return make_list_inserter( assign_detail::call_push_back<C>( c ),
352                                    p );
353     }
354 
355     template< class C >
356     inline list_inserter< assign_detail::call_push_front<C>,
357                           BOOST_DEDUCED_TYPENAME C::value_type >
push_front(C & c)358     push_front( C& c )
359     {
360         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
361         return make_list_inserter( assign_detail::call_push_front<C>( c ),
362                                    p );
363     }
364 
365     template< class C >
366     inline list_inserter< assign_detail::call_insert<C>,
367                           BOOST_DEDUCED_TYPENAME C::value_type >
insert(C & c)368     insert( C& c )
369     {
370         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
371         return make_list_inserter( assign_detail::call_insert<C>( c ),
372                                    p );
373     }
374 
375     template< class C >
376     inline list_inserter< assign_detail::call_push<C>,
377                           BOOST_DEDUCED_TYPENAME C::value_type >
push(C & c)378     push( C& c )
379     {
380         static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
381         return make_list_inserter( assign_detail::call_push<C>( c ),
382                                    p );
383     }
384 
385     template< class C >
386     inline list_inserter< assign_detail::call_add_edge<C> >
add_edge(C & c)387     add_edge( C& c )
388     {
389         return make_list_inserter( assign_detail::call_add_edge<C>( c ) );
390     }
391 
392 } // namespace 'assign'
393 } // namespace 'boost'
394 
395 #undef BOOST_ASSIGN_PARAMS1
396 #undef BOOST_ASSIGN_PARAMS2
397 #undef BOOST_ASSIGN_PARAMS3
398 #undef BOOST_ASSIGN_MAX_PARAMETERS
399 
400 #endif
401