list_inserter.hpp 14 KB

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