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