list_of.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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_OF_HPP
  11. #define BOOST_ASSIGN_LIST_OF_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  13. # pragma once
  14. #endif
  15. #include <boost/assign/assignment_exception.hpp>
  16. #include <boost/range/iterator_range.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/tuple/tuple.hpp>
  19. #include <boost/type_traits/remove_const.hpp>
  20. #include <boost/type_traits/remove_reference.hpp>
  21. #include <boost/type_traits/is_reference.hpp>
  22. #include <boost/static_assert.hpp>
  23. #include <boost/type_traits/detail/yes_no_type.hpp>
  24. #include <boost/type_traits/decay.hpp>
  25. #include <boost/type_traits/is_array.hpp>
  26. #include <boost/mpl/if.hpp>
  27. #include <deque>
  28. #include <cstddef>
  29. #include <utility>
  30. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  31. #include <boost/preprocessor/repetition/enum_params.hpp>
  32. #include <boost/preprocessor/iteration/local.hpp>
  33. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  34. // BCB requires full type definition for is_array<> to work correctly.
  35. #include <boost/array.hpp>
  36. #endif
  37. namespace boost
  38. {
  39. // this here is necessary to avoid compiler error in <boost/array.hpp>
  40. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  41. template< class T, std::size_t sz >
  42. class array;
  43. #endif
  44. namespace assign_detail
  45. {
  46. /////////////////////////////////////////////////////////////////////////
  47. // Part 0: common conversion code
  48. /////////////////////////////////////////////////////////////////////////
  49. template< class T >
  50. struct assign_decay
  51. {
  52. //
  53. // Add constness to array parameters
  54. // to support string literals properly
  55. //
  56. typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
  57. ::boost::is_array<T>,
  58. ::boost::decay<const T>,
  59. ::boost::decay<T> >::type type;
  60. };
  61. template< class T, std::size_t sz >
  62. type_traits::yes_type assign_is_array( const array<T,sz>* );
  63. type_traits::no_type assign_is_array( ... );
  64. template< class T, class U >
  65. type_traits::yes_type assign_is_pair( const std::pair<T,U>* );
  66. type_traits::no_type assign_is_pair( ... );
  67. struct array_type_tag
  68. {
  69. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  70. private:
  71. char dummy_; // BCB would by default use 8 bytes
  72. #endif
  73. };
  74. struct adapter_type_tag
  75. {
  76. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  77. private:
  78. char dummy_; // BCB would by default use 8 bytes
  79. #endif
  80. };
  81. struct pair_type_tag
  82. {
  83. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  84. private:
  85. char dummy_; // BCB would by default use 8 bytes
  86. #endif
  87. };
  88. struct default_type_tag
  89. {
  90. #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
  91. private:
  92. char dummy_; // BCB would by default use 8 bytes
  93. #endif
  94. };
  95. template< class DerivedTAssign, class Iterator >
  96. class converter
  97. {
  98. public: // Range operations
  99. typedef Iterator iterator;
  100. typedef Iterator const_iterator;
  101. iterator begin() const
  102. {
  103. return static_cast<const DerivedTAssign*>(this)->begin();
  104. }
  105. iterator end() const
  106. {
  107. return static_cast<const DerivedTAssign*>(this)->end();
  108. }
  109. public:
  110. template< class Container >
  111. Container convert_to_container() const
  112. {
  113. static Container* c = 0;
  114. BOOST_STATIC_CONSTANT( bool, is_array_flag = sizeof( assign_detail::assign_is_array( c ) )
  115. == sizeof( type_traits::yes_type ) );
  116. typedef BOOST_DEDUCED_TYPENAME mpl::if_c< is_array_flag,
  117. array_type_tag,
  118. default_type_tag >::type tag_type;
  119. return convert<Container>( c, tag_type() );
  120. }
  121. private:
  122. template< class Container >
  123. Container convert( const Container*, default_type_tag ) const
  124. {
  125. #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
  126. // old Dinkumware doesn't support iterator type as template
  127. Container result;
  128. iterator it = begin(),
  129. e = end();
  130. while( it != e )
  131. {
  132. result.insert( result.end(), *it );
  133. ++it;
  134. }
  135. return result;
  136. #else
  137. return Container( begin(), end() );
  138. #endif
  139. }
  140. template< class Array >
  141. Array convert( const Array*, array_type_tag ) const
  142. {
  143. typedef BOOST_DEDUCED_TYPENAME Array::value_type value_type;
  144. #if BOOST_WORKAROUND(BOOST_INTEL, <= 910 ) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580 )
  145. BOOST_DEDUCED_TYPENAME remove_const<Array>::type ar;
  146. #else
  147. Array ar;
  148. #endif
  149. const std::size_t sz = ar.size();
  150. if( sz < static_cast<const DerivedTAssign*>(this)->size() )
  151. throw assign::assignment_exception( "array initialized with too many elements" );
  152. std::size_t n = 0;
  153. iterator i = begin(),
  154. e = end();
  155. for( ; i != e; ++i, ++n )
  156. ar[n] = *i;
  157. for( ; n < sz; ++n )
  158. ar[n] = value_type();
  159. return ar;
  160. }
  161. template< class Adapter >
  162. Adapter convert_to_adapter( const Adapter* = 0 ) const
  163. {
  164. Adapter a;
  165. iterator i = begin(),
  166. e = end();
  167. for( ; i != e; ++i )
  168. a.push( *i );
  169. return a;
  170. }
  171. private:
  172. struct adapter_converter;
  173. friend struct adapter_converter;
  174. struct adapter_converter
  175. {
  176. const converter& gl;
  177. adapter_converter( const converter& this_ ) : gl( this_ )
  178. {}
  179. adapter_converter( const adapter_converter& r )
  180. : gl( r.gl )
  181. { }
  182. template< class Adapter >
  183. operator Adapter() const
  184. {
  185. return gl.convert_to_adapter<Adapter>();
  186. }
  187. };
  188. public:
  189. template< class Container >
  190. Container to_container( Container& c ) const
  191. {
  192. return convert( &c, default_type_tag() );
  193. }
  194. adapter_converter to_adapter() const
  195. {
  196. return adapter_converter( *this );
  197. }
  198. template< class Adapter >
  199. Adapter to_adapter( Adapter& a ) const
  200. {
  201. return this->convert_to_adapter( &a );
  202. }
  203. template< class Array >
  204. Array to_array( Array& a ) const
  205. {
  206. return convert( &a, array_type_tag() );
  207. }
  208. };
  209. template< class T, class I, class Range >
  210. inline bool operator==( const converter<T,I>& l, const Range& r )
  211. {
  212. return ::boost::iterator_range_detail::equal( l, r );
  213. }
  214. template< class T, class I, class Range >
  215. inline bool operator==( const Range& l, const converter<T,I>& r )
  216. {
  217. return r == l;
  218. }
  219. template< class T, class I, class Range >
  220. inline bool operator!=( const converter<T,I>& l, const Range& r )
  221. {
  222. return !( l == r );
  223. }
  224. template< class T, class I, class Range >
  225. inline bool operator!=( const Range& l, const converter<T,I>& r )
  226. {
  227. return !( l == r );
  228. }
  229. template< class T, class I, class Range >
  230. inline bool operator<( const converter<T,I>& l, const Range& r )
  231. {
  232. return ::boost::iterator_range_detail::less_than( l, r );
  233. }
  234. template< class T, class I, class Range >
  235. inline bool operator<( const Range& l, const converter<T,I>& r )
  236. {
  237. return ::boost::iterator_range_detail::less_than( l, r );
  238. }
  239. template< class T, class I, class Range >
  240. inline bool operator>( const converter<T,I>& l, const Range& r )
  241. {
  242. return r < l;
  243. }
  244. template< class T, class I, class Range >
  245. inline bool operator>( const Range& l, const converter<T,I>& r )
  246. {
  247. return r < l;
  248. }
  249. template< class T, class I, class Range >
  250. inline bool operator<=( const converter<T,I>& l, const Range& r )
  251. {
  252. return !( l > r );
  253. }
  254. template< class T, class I, class Range >
  255. inline bool operator<=( const Range& l, const converter<T,I>& r )
  256. {
  257. return !( l > r );
  258. }
  259. template< class T, class I, class Range >
  260. inline bool operator>=( const converter<T,I>& l, const Range& r )
  261. {
  262. return !( l < r );
  263. }
  264. template< class T, class I, class Range >
  265. inline bool operator>=( const Range& l, const converter<T,I>& r )
  266. {
  267. return !( l < r );
  268. }
  269. template< class T, class I, class Elem, class Traits >
  270. inline std::basic_ostream<Elem,Traits>&
  271. operator<<( std::basic_ostream<Elem, Traits>& Os,
  272. const converter<T,I>& r )
  273. {
  274. return Os << ::boost::make_iterator_range( r.begin(), r.end() );
  275. }
  276. /////////////////////////////////////////////////////////////////////////
  277. // Part 1: flexible, but inefficient interface
  278. /////////////////////////////////////////////////////////////////////////
  279. template< class T >
  280. class generic_list :
  281. public converter< generic_list< BOOST_DEDUCED_TYPENAME assign_decay<T>::type >,
  282. BOOST_DEDUCED_TYPENAME std::deque<BOOST_DEDUCED_TYPENAME
  283. assign_decay<T>::type>::iterator >
  284. {
  285. typedef BOOST_DEDUCED_TYPENAME assign_decay<T>::type Ty;
  286. typedef std::deque<Ty> impl_type;
  287. mutable impl_type values_;
  288. public:
  289. typedef BOOST_DEDUCED_TYPENAME impl_type::iterator iterator;
  290. typedef iterator const_iterator;
  291. typedef BOOST_DEDUCED_TYPENAME impl_type::value_type value_type;
  292. typedef BOOST_DEDUCED_TYPENAME impl_type::size_type size_type;
  293. typedef BOOST_DEDUCED_TYPENAME impl_type::difference_type difference_type;
  294. public:
  295. iterator begin() const { return values_.begin(); }
  296. iterator end() const { return values_.end(); }
  297. bool empty() const { return values_.empty(); }
  298. size_type size() const { return values_.size(); }
  299. private:
  300. void push_back( value_type r ) { values_.push_back( r ); }
  301. public:
  302. generic_list& operator,( const Ty& u )
  303. {
  304. this->push_back( u );
  305. return *this;
  306. }
  307. generic_list& operator()()
  308. {
  309. this->push_back( Ty() );
  310. return *this;
  311. }
  312. generic_list& operator()( const Ty& u )
  313. {
  314. this->push_back( u );
  315. return *this;
  316. }
  317. #ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value
  318. #define BOOST_ASSIGN_MAX_PARAMS 5
  319. #endif
  320. #define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1)
  321. #define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class U)
  322. #define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, U, const& u)
  323. #define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, u)
  324. #define BOOST_ASSIGN_PARAMS4(n) BOOST_PP_ENUM_PARAMS(n, U)
  325. #define BOOST_ASSIGN_PARAMS2_NO_REF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, U, u)
  326. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  327. #define BOOST_PP_LOCAL_MACRO(n) \
  328. template< class U, BOOST_ASSIGN_PARAMS1(n) > \
  329. generic_list& operator()(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \
  330. { \
  331. this->push_back( Ty(u, BOOST_ASSIGN_PARAMS3(n))); \
  332. return *this; \
  333. } \
  334. /**/
  335. #include BOOST_PP_LOCAL_ITERATE()
  336. template< class U >
  337. generic_list& repeat( std::size_t sz, U u )
  338. {
  339. std::size_t i = 0;
  340. while( i++ != sz )
  341. this->push_back( u );
  342. return *this;
  343. }
  344. template< class Nullary_function >
  345. generic_list& repeat_fun( std::size_t sz, Nullary_function fun )
  346. {
  347. std::size_t i = 0;
  348. while( i++ != sz )
  349. this->push_back( fun() );
  350. return *this;
  351. }
  352. template< class SinglePassIterator >
  353. generic_list& range( SinglePassIterator first,
  354. SinglePassIterator last )
  355. {
  356. for( ; first != last; ++first )
  357. this->push_back( *first );
  358. return *this;
  359. }
  360. template< class SinglePassRange >
  361. generic_list& range( const SinglePassRange& r )
  362. {
  363. return range( boost::begin(r), boost::end(r) );
  364. }
  365. template< class Container >
  366. operator Container() const
  367. {
  368. return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();
  369. }
  370. };
  371. /////////////////////////////////////////////////////////////////////////
  372. // Part 2: efficient, but inconvenient interface
  373. /////////////////////////////////////////////////////////////////////////
  374. template< class T >
  375. struct assign_reference
  376. {
  377. assign_reference()
  378. { /* intentionally empty */ }
  379. assign_reference( T& r ) : ref_(&r)
  380. { }
  381. void operator=( T& r )
  382. {
  383. ref_ = &r;
  384. }
  385. operator T&() const
  386. {
  387. return *ref_;
  388. }
  389. void swap( assign_reference& r )
  390. {
  391. std::swap( *ref_, *r.ref_ );
  392. }
  393. T& get_ref() const
  394. {
  395. return *ref_;
  396. }
  397. private:
  398. T* ref_;
  399. };
  400. template< class T >
  401. inline bool operator<( const assign_reference<T>& l,
  402. const assign_reference<T>& r )
  403. {
  404. return l.get_ref() < r.get_ref();
  405. }
  406. template< class T >
  407. inline bool operator>( const assign_reference<T>& l,
  408. const assign_reference<T>& r )
  409. {
  410. return l.get_ref() > r.get_ref();
  411. }
  412. template< class T >
  413. inline void swap( assign_reference<T>& l,
  414. assign_reference<T>& r )
  415. {
  416. l.swap( r );
  417. }
  418. template< class T, int N >
  419. struct static_generic_list :
  420. public converter< static_generic_list<T,N>, assign_reference<T>* >
  421. {
  422. private:
  423. typedef T internal_value_type;
  424. public:
  425. typedef assign_reference<internal_value_type> value_type;
  426. typedef value_type* iterator;
  427. typedef value_type* const_iterator;
  428. typedef std::size_t size_type;
  429. typedef std::ptrdiff_t difference_type;
  430. static_generic_list( T& r ) :
  431. current_(1)
  432. {
  433. refs_[0] = r;
  434. }
  435. static_generic_list& operator()( T& r )
  436. {
  437. insert( r );
  438. return *this;
  439. }
  440. iterator begin() const
  441. {
  442. return &refs_[0];
  443. }
  444. iterator end() const
  445. {
  446. return &refs_[current_];
  447. }
  448. size_type size() const
  449. {
  450. return static_cast<size_type>( current_ );
  451. }
  452. bool empty() const
  453. {
  454. return false;
  455. }
  456. template< class ForwardIterator >
  457. static_generic_list& range( ForwardIterator first,
  458. ForwardIterator last )
  459. {
  460. for( ; first != last; ++first )
  461. this->insert( *first );
  462. return *this;
  463. }
  464. template< class ForwardRange >
  465. static_generic_list& range( ForwardRange& r )
  466. {
  467. return range( boost::begin(r), boost::end(r) );
  468. }
  469. template< class ForwardRange >
  470. static_generic_list& range( const ForwardRange& r )
  471. {
  472. return range( boost::begin(r), boost::end(r) );
  473. }
  474. template< class Container >
  475. operator Container() const
  476. {
  477. return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();
  478. }
  479. private:
  480. void insert( T& r )
  481. {
  482. refs_[current_] = r;
  483. ++current_;
  484. }
  485. static_generic_list();
  486. mutable assign_reference<internal_value_type> refs_[N];
  487. int current_;
  488. };
  489. } // namespace 'assign_detail'
  490. namespace assign
  491. {
  492. template< class T >
  493. inline assign_detail::generic_list<T>
  494. list_of()
  495. {
  496. return assign_detail::generic_list<T>()( T() );
  497. }
  498. template< class T >
  499. inline assign_detail::generic_list<T>
  500. list_of( const T& t )
  501. {
  502. return assign_detail::generic_list<T>()( t );
  503. }
  504. template< int N, class T >
  505. inline assign_detail::static_generic_list< BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type,N>
  506. ref_list_of( T& t )
  507. {
  508. return assign_detail::static_generic_list<BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type,N>( t );
  509. }
  510. template< int N, class T >
  511. inline assign_detail::static_generic_list<const BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type,N>
  512. cref_list_of( const T& t )
  513. {
  514. return assign_detail::static_generic_list<const BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type,N>( t );
  515. }
  516. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  517. #define BOOST_PP_LOCAL_MACRO(n) \
  518. template< class T, class U, BOOST_ASSIGN_PARAMS1(n) > \
  519. inline assign_detail::generic_list<T> \
  520. list_of(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \
  521. { \
  522. return assign_detail::generic_list<T>()(u, BOOST_ASSIGN_PARAMS3(n)); \
  523. } \
  524. /**/
  525. #include BOOST_PP_LOCAL_ITERATE()
  526. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS)
  527. #define BOOST_PP_LOCAL_MACRO(n) \
  528. template< class U, BOOST_ASSIGN_PARAMS1(n) > \
  529. inline assign_detail::generic_list< tuple<U, BOOST_ASSIGN_PARAMS4(n)> > \
  530. tuple_list_of(U u, BOOST_ASSIGN_PARAMS2_NO_REF(n) ) \
  531. { \
  532. return assign_detail::generic_list< tuple<U, BOOST_ASSIGN_PARAMS4(n)> >()( tuple<U,BOOST_ASSIGN_PARAMS4(n)>( u, BOOST_ASSIGN_PARAMS3(n) )); \
  533. } \
  534. /**/
  535. #include BOOST_PP_LOCAL_ITERATE()
  536. template< class Key, class T >
  537. inline assign_detail::generic_list< std::pair
  538. <
  539. BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<Key>::type,
  540. BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type
  541. > >
  542. map_list_of( const Key& k, const T& t )
  543. {
  544. typedef BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<Key>::type k_type;
  545. typedef BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type t_type;
  546. return assign_detail::generic_list< std::pair<k_type,t_type> >()( k, t );
  547. }
  548. template< class F, class S >
  549. inline assign_detail::generic_list< std::pair
  550. <
  551. BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<F>::type,
  552. BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<S>::type
  553. > >
  554. pair_list_of( const F& f, const S& s )
  555. {
  556. return map_list_of( f, s );
  557. }
  558. } // namespace 'assign'
  559. } // namespace 'boost'
  560. #undef BOOST_ASSIGN_PARAMS1
  561. #undef BOOST_ASSIGN_PARAMS2
  562. #undef BOOST_ASSIGN_PARAMS3
  563. #undef BOOST_ASSIGN_PARAMS4
  564. #undef BOOST_ASSIGN_PARAMS2_NO_REF
  565. #undef BOOST_ASSIGN_MAX_PARAMETERS
  566. #endif