list_inserter.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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/type_traits/conditional.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 ::boost::conditional<
  181. is_same<Argument,assign_detail::forward_n_arguments>::value,
  182. n_arg_type,
  183. single_arg_type >::type arg_type;
  184. public:
  185. list_inserter( Function fun ) : insert_( fun )
  186. {}
  187. template< class Function2, class Arg >
  188. list_inserter( const list_inserter<Function2,Arg>& r )
  189. : insert_( r.fun_private() )
  190. {}
  191. list_inserter( const list_inserter& r ) : insert_( r.insert_ )
  192. {}
  193. list_inserter& operator()()
  194. {
  195. insert_( Argument() );
  196. return *this;
  197. }
  198. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  199. template< class T >
  200. list_inserter& operator=( const T& r )
  201. {
  202. insert_( r );
  203. return *this;
  204. }
  205. template< class T >
  206. list_inserter& operator=( assign_detail::repeater<T> r )
  207. {
  208. return operator,( r );
  209. }
  210. template< class Nullary_function >
  211. list_inserter& operator=( const assign_detail::fun_repeater<Nullary_function>& r )
  212. {
  213. return operator,( r );
  214. }
  215. template< class T >
  216. list_inserter& operator,( const T& r )
  217. {
  218. insert_( r );
  219. return *this;
  220. }
  221. #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
  222. template< class T >
  223. list_inserter& operator,( const assign_detail::repeater<T> & r )
  224. {
  225. return repeat( r.sz, r.val );
  226. }
  227. #else
  228. template< class T >
  229. list_inserter& operator,( assign_detail::repeater<T> r )
  230. {
  231. return repeat( r.sz, r.val );
  232. }
  233. #endif
  234. template< class Nullary_function >
  235. list_inserter& operator,( const assign_detail::fun_repeater<Nullary_function>& r )
  236. {
  237. return repeat_fun( r.sz, r.val );
  238. }
  239. #else
  240. // BOOST_NO_CXX11_RVALUE_REFERENCES
  241. template< class T >
  242. list_inserter& operator=(T&& r)
  243. {
  244. return operator,(boost::forward<T>(r));
  245. }
  246. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  247. template< class T >
  248. list_inserter& operator,(T&& r)
  249. {
  250. typedef BOOST_DEDUCED_TYPENAME ::boost::conditional<
  251. assign_detail::is_repeater< T >::value,
  252. repeater_arg_type,
  253. arg_type >::type tag;
  254. insert(boost::forward<T>(r), tag());
  255. return *this;
  256. }
  257. #else
  258. // we add the tag as the first argument when using variadic templates
  259. template< class T >
  260. list_inserter& operator,(T&& r)
  261. {
  262. typedef BOOST_DEDUCED_TYPENAME ::boost::conditional<
  263. assign_detail::is_repeater< T >::value,
  264. repeater_arg_type,
  265. arg_type >::type tag;
  266. insert(tag(), boost::forward<T>(r));
  267. return *this;
  268. }
  269. #endif
  270. #endif
  271. template< class T >
  272. list_inserter& repeat( std::size_t sz, T r )
  273. {
  274. std::size_t i = 0;
  275. while( i++ != sz )
  276. insert_( r );
  277. return *this;
  278. }
  279. template< class Nullary_function >
  280. list_inserter& repeat_fun( std::size_t sz, Nullary_function fun )
  281. {
  282. std::size_t i = 0;
  283. while( i++ != sz )
  284. insert_( fun() );
  285. return *this;
  286. }
  287. template< class SinglePassIterator >
  288. list_inserter& range( SinglePassIterator first,
  289. SinglePassIterator last )
  290. {
  291. for( ; first != last; ++first )
  292. insert_( *first );
  293. return *this;
  294. }
  295. template< class SinglePassRange >
  296. list_inserter& range( const SinglePassRange& r )
  297. {
  298. return range( boost::begin(r), boost::end(r) );
  299. }
  300. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  301. template< class T >
  302. list_inserter& operator()( const T& t )
  303. {
  304. insert_( t );
  305. return *this;
  306. }
  307. #ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value
  308. #define BOOST_ASSIGN_MAX_PARAMS 5
  309. #endif
  310. #define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1)
  311. #define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T)
  312. #define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t)
  313. #define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t)
  314. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  315. #define BOOST_PP_LOCAL_MACRO(n) \
  316. template< class T, BOOST_ASSIGN_PARAMS1(n) > \
  317. list_inserter& operator()(T t, BOOST_ASSIGN_PARAMS2(n) ) \
  318. { \
  319. BOOST_PP_CAT(insert, BOOST_PP_INC(n))(t, BOOST_ASSIGN_PARAMS3(n), arg_type()); \
  320. return *this; \
  321. } \
  322. /**/
  323. #include BOOST_PP_LOCAL_ITERATE()
  324. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  325. #define BOOST_PP_LOCAL_MACRO(n) \
  326. template< class T, BOOST_ASSIGN_PARAMS1(n) > \
  327. void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), single_arg_type) \
  328. { \
  329. insert_( Argument(t, BOOST_ASSIGN_PARAMS3(n) )); \
  330. } \
  331. /**/
  332. #include BOOST_PP_LOCAL_ITERATE()
  333. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  334. #define BOOST_PP_LOCAL_MACRO(n) \
  335. template< class T, BOOST_ASSIGN_PARAMS1(n) > \
  336. void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), n_arg_type) \
  337. { \
  338. insert_(t, BOOST_ASSIGN_PARAMS3(n) ); \
  339. } \
  340. /**/
  341. #include BOOST_PP_LOCAL_ITERATE()
  342. #else
  343. template< class... Ts >
  344. list_inserter& operator()(Ts&&... ts)
  345. {
  346. insert(arg_type(), boost::forward<Ts>(ts)...);
  347. return *this;
  348. }
  349. template< class T >
  350. void insert(single_arg_type, T&& t)
  351. {
  352. // Special implementation for single argument overload to prevent accidental casts (type-cast using functional notation)
  353. insert_(boost::forward<T>(t));
  354. }
  355. template< class T1, class T2, class... Ts >
  356. void insert(single_arg_type, T1&& t1, T2&& t2, Ts&&... ts)
  357. {
  358. insert_(Argument(boost::forward<T1>(t1), boost::forward<T2>(t2), boost::forward<Ts>(ts)...));
  359. }
  360. template< class... Ts >
  361. void insert(n_arg_type, Ts&&... ts)
  362. {
  363. insert_(boost::forward<Ts>(ts)...);
  364. }
  365. #endif
  366. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  367. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  368. template< class T >
  369. void insert( T&& r, arg_type)
  370. {
  371. insert_( boost::forward<T>(r) );
  372. }
  373. template< class T >
  374. void insert(assign_detail::repeater<T> r, repeater_arg_type)
  375. {
  376. repeat(r.sz, r.val);
  377. }
  378. template< class Nullary_function >
  379. void insert(const assign_detail::fun_repeater<Nullary_function>& r, repeater_arg_type)
  380. {
  381. repeat_fun(r.sz, r.val);
  382. }
  383. #else
  384. template< class T >
  385. void insert(repeater_arg_type, assign_detail::repeater<T> r)
  386. {
  387. repeat(r.sz, r.val);
  388. }
  389. template< class Nullary_function >
  390. void insert(repeater_arg_type, const assign_detail::fun_repeater<Nullary_function>& r)
  391. {
  392. repeat_fun(r.sz, r.val);
  393. }
  394. #endif
  395. #endif
  396. Function fun_private() const
  397. {
  398. return insert_;
  399. }
  400. private:
  401. list_inserter& operator=( const list_inserter& );
  402. Function insert_;
  403. };
  404. template< class Function >
  405. inline list_inserter< Function >
  406. make_list_inserter( Function fun )
  407. {
  408. return list_inserter< Function >( fun );
  409. }
  410. template< class Function, class Argument >
  411. inline list_inserter<Function,Argument>
  412. make_list_inserter( Function fun, Argument* )
  413. {
  414. return list_inserter<Function,Argument>( fun );
  415. }
  416. template< class C >
  417. inline list_inserter< assign_detail::call_push_back<C>,
  418. BOOST_DEDUCED_TYPENAME C::value_type >
  419. push_back( C& c )
  420. {
  421. static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
  422. return make_list_inserter( assign_detail::call_push_back<C>( c ),
  423. p );
  424. }
  425. template< class C >
  426. inline list_inserter< assign_detail::call_push_front<C>,
  427. BOOST_DEDUCED_TYPENAME C::value_type >
  428. push_front( C& c )
  429. {
  430. static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
  431. return make_list_inserter( assign_detail::call_push_front<C>( c ),
  432. p );
  433. }
  434. template< class C >
  435. inline list_inserter< assign_detail::call_insert<C>,
  436. BOOST_DEDUCED_TYPENAME C::value_type >
  437. insert( C& c )
  438. {
  439. static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
  440. return make_list_inserter( assign_detail::call_insert<C>( c ),
  441. p );
  442. }
  443. template< class C >
  444. inline list_inserter< assign_detail::call_push<C>,
  445. BOOST_DEDUCED_TYPENAME C::value_type >
  446. push( C& c )
  447. {
  448. static BOOST_DEDUCED_TYPENAME C::value_type* p = 0;
  449. return make_list_inserter( assign_detail::call_push<C>( c ),
  450. p );
  451. }
  452. template< class C >
  453. inline list_inserter< assign_detail::call_add_edge<C> >
  454. add_edge( C& c )
  455. {
  456. return make_list_inserter( assign_detail::call_add_edge<C>( c ) );
  457. }
  458. } // namespace 'assign'
  459. } // namespace 'boost'
  460. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  461. #undef BOOST_ASSIGN_PARAMS1
  462. #undef BOOST_ASSIGN_PARAMS2
  463. #undef BOOST_ASSIGN_PARAMS3
  464. #undef BOOST_ASSIGN_MAX_PARAMETERS
  465. #endif
  466. #endif