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