1 /*=============================================================================
2 Copyright (c) 2004 Angus Leeming
3 Copyright (c) 2004 Joel de Guzman
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #ifndef BOOST_PHOENIX_STL_CONTAINER_CONTAINER_HPP
9 #define BOOST_PHOENIX_STL_CONTAINER_CONTAINER_HPP
11 #include <boost/phoenix/core/limits.hpp>
12 #include <boost/mpl/and.hpp>
13 #include <boost/mpl/not.hpp>
14 #include <boost/mpl/or.hpp>
15 #include <boost/mpl/void.hpp>
16 #include <boost/phoenix/stl/container/detail/container.hpp>
17 #include <boost/phoenix/function/adapt_callable.hpp>
18 #include <boost/type_traits/is_const.hpp>
20 namespace boost { namespace phoenix
22 ///////////////////////////////////////////////////////////////////////////////
24 // STL container member functions
26 // Lazy functions for STL container member functions
28 // These functions provide a mechanism for the lazy evaluation of the
29 // public member functions of the STL containers. For an overview of
30 // what is meant by 'lazy evaluation', see the comments in operators.hpp
33 // Lazy functions are provided for all of the member functions of the
34 // following containers:
36 // deque - list - map - multimap - vector.
38 // Indeed, should *your* class have member functions with the same names
39 // and signatures as those listed below, then it will automatically be
40 // supported. To summarize, lazy functions are provided for member
43 // assign - at - back - begin - capacity - clear - empty - end -
44 // erase - front - get_allocator - insert - key_comp - max_size -
45 // pop_back - pop_front - push_back - push_front - rbegin - rend -
46 // reserve - resize . size - splice - value_comp.
48 // The lazy functions' names are the same as the corresponding member
49 // function. Sample usage:
51 // "Normal" version "Lazy" version
52 // ---------------- --------------
53 // my_vector.at(5) phoenix::at(arg1, 5)
54 // my_list.size() phoenix::size(arg1)
55 // my_vector1.swap(my_vector2) phoenix::swap(arg1, arg2)
57 // Notice that member functions with names that clash with a
58 // function in stl algorithms are absent. This will be provided
59 // in Phoenix's algorithm module.
61 // No support is provided here for lazy versions of operator+=,
62 // operator[] etc. Such operators are not specific to STL containers and
63 // lazy versions can therefore be found in operators.hpp.
65 ///////////////////////////////////////////////////////////////////////////////
67 ///////////////////////////////////////////////////////////////////////////////
69 // Lazy member function implementaions.
71 // The structs below provide the guts of the implementation. Thereafter,
72 // the corresponding lazy function itself is simply:
74 // function<stl::assign> const assign = stl::assign();
76 // The structs provide a nested "result" class template whose
77 // "type" typedef enables the lazy function to ascertain the type
78 // to be returned when it is invoked.
80 // They also provide operator() member functions with signatures
81 // corresponding to those of the underlying member function of
84 ///////////////////////////////////////////////////////////////////////////////
89 template <typename Sig>
97 struct result<This(C&, Arg1 const &)>
99 typedef typename add_reference<C>::type type;
108 struct result<This(C&, Arg1, Arg2)>
110 typedef typename add_reference<C>::type type;
120 struct result<This(C&, Arg1, Arg2, Arg3)>
122 typedef typename add_reference<C>::type type;
125 template <typename C, typename Arg1>
126 C& operator()(C& c, Arg1 const & arg1) const
132 template <typename C, typename Arg1, typename Arg2>
133 C& operator()(C& c, Arg1 arg1, Arg2 arg2) const
135 c.assign(arg1, arg2);
139 template <typename C, typename Arg1, typename Arg2, typename Arg3>
147 return c.assign(arg1, arg2, arg3);
153 template <typename Sig>
156 template <typename This, typename C, typename Index>
157 struct result<This(C&, Index)>
159 //typedef typename const_qualified_reference_of<C>::type type;
160 typedef typename C::value_type & type;
163 template <typename C, typename Index>
164 typename result<at_impl(C&, Index const&)>::type
165 operator()(C& c, Index const &i) const
170 template <typename This, typename C, typename Index>
171 struct result<This(C const&, Index)>
173 typedef typename C::value_type const & type;
176 template <typename C, typename Index>
177 typename result<at_impl(C const&, Index const&)>::type
178 operator()(C const& c, Index const &i) const
186 template <typename Sig>
189 template <typename This, typename C>
190 struct result<This(C&)>
193 typename const_qualified_reference_of<C>::type
197 template <typename C>
198 typename result<back(C&)>::type
199 operator()(C& c) const
207 template <typename Sig>
210 template <typename This, typename C>
211 struct result<This(C&)>
213 typedef typename const_qualified_iterator_of<C>::type type;
216 template <typename C>
217 typename result<begin(C&)>::type
218 operator()(C& c) const
226 template <typename Sig>
229 template <typename This, typename C>
230 struct result<This(C&)>
232 typedef typename size_type_of<C>::type type;
235 template <typename C>
236 typename result<capacity(C&)>::type
237 operator()(C const& c) const
245 typedef void result_type;
247 template <typename C>
248 void operator()(C& c) const
256 typedef bool result_type;
258 template <typename C>
259 bool operator()(C const& c) const
267 template <typename Sig>
270 template <typename This, typename C>
271 struct result<This(C&)>
273 typedef typename const_qualified_iterator_of<C>::type type;
276 template <typename C>
277 typename result<end(C&)>::type
278 operator()(C& c) const
286 template <typename C, typename Arg1, typename Arg2 = mpl::void_>
289 // BOOST_MSVC #if branch here in map_erase_result non-
290 // standard behavior. The return type should be void but
291 // VC7.1 prefers to return iterator_of<C>. As a result,
292 // VC7.1 complains of error C2562:
293 // boost::phoenix::stl::erase::operator() 'void' function
294 // returning a value. Oh well... :*
297 boost::mpl::eval_if_c<
299 typename remove_reference<Arg1>::type
300 , typename iterator_of<C>::type
302 #if defined(BOOST_MSVC)// && (BOOST_MSVC <= 1500)
305 , boost::mpl::identity<void>
312 boost::mpl::eval_if_c<
313 has_mapped_type<C>::value
323 // This mouthful can differentiate between the generic erase
324 // functions (Container == std::deque, std::list, std::vector) and
325 // that specific to the two map-types, std::map and std::multimap.
327 // where C is a std::deque, std::list, std::vector:
329 // 1) iterator C::erase(iterator where);
330 // 2) iterator C::erase(iterator first, iterator last);
332 // where M is a std::map or std::multimap:
334 // 3) size_type M::erase(const Key& keyval);
335 // 4) void M::erase(iterator where);
336 // 5) void M::erase(iterator first, iterator last);
338 template <typename Sig>
341 template <typename This, typename C, typename Arg1>
342 struct result<This(C&, Arg1)>
343 : result_of::erase<C, Arg1>
346 template <typename This, typename C, typename Arg1, typename Arg2>
347 struct result<This(C&, Arg1, Arg2)>
348 : result_of::erase<C, Arg1, Arg2>
351 template <typename C, typename Arg1>
352 typename stl_impl::disable_if_is_void<
353 typename result_of::erase<C, Arg1>::type
355 operator()(C& c, Arg1 arg1) const
357 return c.erase(arg1);
360 template <typename C, typename Arg1>
361 typename stl_impl::enable_if_is_void<
362 typename result_of::erase<C, Arg1>::type
364 operator()(C& c, Arg1 arg1) const
369 template <typename C, typename Arg1, typename Arg2>
370 typename stl_impl::disable_if_is_void<
371 typename result_of::erase<C, Arg1, Arg2>::type
373 operator()(C& c, Arg1 arg1, Arg2 arg2) const
375 return c.erase(arg1, arg2);
378 template <typename C, typename Arg1, typename Arg2>
379 typename stl_impl::enable_if_is_void<
380 typename result_of::erase<C, Arg1, Arg2>::type
382 operator()(C& c, Arg1 arg1, Arg2 arg2) const
390 template <typename Sig>
393 template <typename This, typename C>
394 struct result<This(C&)>
396 typedef typename const_qualified_reference_of<C>::type type;
399 template <typename C>
400 typename result<front(C&)>::type
401 operator()(C& c) const
409 template <typename Sig>
412 template <typename This, typename C>
413 struct result<This(C&)>
415 typedef typename allocator_type_of<C>::type type;
418 template <typename C>
419 typename result<get_allocator(C const&)>::type
420 operator()(C& c) const
422 return c.get_allocator();
431 , typename Arg2 = mpl::void_
432 , typename Arg3 = mpl::void_
436 struct pair_iterator_bool
438 typedef typename std::pair<typename C::iterator, bool> type;
443 map_insert_returns_pair<typename remove_const<C>::type>
450 boost::mpl::eval_if_c<
452 boost::is_same<Arg3, mpl::void_>
453 , boost::mpl::not_<boost::is_same<Arg1, Arg2> >
456 , boost::mpl::identity<void>
463 boost::mpl::eval_if_c<
464 boost::is_same<Arg2, mpl::void_>::value
474 // This mouthful can differentiate between the generic insert
475 // functions (Container == deque, list, vector) and those
476 // specific to the two map-types, std::map and std::multimap.
478 // where C is a std::deque, std::list, std::vector:
480 // 1) iterator C::insert(iterator where, value_type value);
481 // 2) void C::insert(
482 // iterator where, size_type count, value_type value);
483 // 3) template <typename Iter>
484 // void C::insert(iterator where, Iter first, Iter last);
486 // where M is a std::map and MM is a std::multimap:
488 // 4) pair<iterator, bool> M::insert(value_type const&);
489 // 5) iterator MM::insert(value_type const&);
491 // where M is a std::map or std::multimap:
493 // 6) template <typename Iter>
494 // void M::insert(Iter first, Iter last);
496 template <typename Sig>
504 struct result<This(C &, Arg1)>
505 : result_of::insert<C, Arg1>
514 struct result<This(C &, Arg1, Arg2)>
515 : result_of::insert<C, Arg1, Arg2>
525 struct result<This(C &, Arg1, Arg2, Arg3)>
526 : result_of::insert<C, Arg1, Arg2, Arg3>
529 template <typename C, typename Arg1>
530 typename result<insert(C&, Arg1)>::type
531 operator()(C& c, Arg1 arg1) const
533 return c.insert(arg1);
536 template <typename C, typename Arg1, typename Arg2>
537 typename stl_impl::disable_if_is_void<
538 typename result<insert(C&, Arg1, Arg2)>::type
540 operator()(C& c, Arg1 arg1, Arg2 arg2) const
542 return c.insert(arg1, arg2);
545 template <typename C, typename Arg1, typename Arg2>
546 typename stl_impl::enable_if_is_void<
547 typename result<insert(C&, Arg1, Arg2)>::type
549 operator()(C& c, Arg1 arg1, Arg2 arg2) const
551 c.insert(arg1, arg2);
554 template <typename C, typename Arg1, typename Arg2, typename Arg3>
555 typename stl_impl::disable_if_is_void<
556 typename result<insert(C&, Arg1, Arg2, Arg3)>::type
559 C& c, Arg1 arg1, Arg2 arg2, Arg3 arg3) const
561 return c.insert(arg1, arg2, arg3);
564 template <typename C, typename Arg1, typename Arg2, typename Arg3>
565 typename stl_impl::enable_if_is_void<
566 typename result<insert(C&, Arg1, Arg2, Arg3)>::type
569 C& c, Arg1 arg1, Arg2 arg2, Arg3 arg3) const
571 c.insert(arg1, arg2, arg3);
577 template <typename C>
580 typedef typename key_compare_of<C>::type type;
586 template <typename Sig>
589 template <typename This, typename C>
590 struct result<This(C&)>
591 : result_of::key_comp<C>
594 template <typename C>
595 typename result_of::key_comp<C>::type
596 operator()(C& c) const
604 template <typename Sig>
607 template <typename This, typename C>
608 struct result<This(C&)>
610 typedef typename size_type_of<C>::type type;
613 template <typename C>
614 typename result<max_size(C const&)>::type
615 operator()(C& c) const
623 typedef void result_type;
625 template <typename C>
626 void operator()(C& c) const
634 typedef void result_type;
636 template <typename C>
637 void operator()(C& c) const
639 return c.pop_front();
645 typedef void result_type;
647 template <typename C, typename Arg>
648 void operator()(C& c, Arg const& data) const
650 return c.push_back(data);
656 typedef void result_type;
658 template <typename C, typename Arg>
659 void operator()(C& c, Arg const& data) const
661 return c.push_front(data);
667 template <typename Sig>
670 template <typename This, typename C>
671 struct result<This(C&)>
674 const_qualified_reverse_iterator_of<C>::type
678 template <typename C>
679 typename result<rbegin(C&)>::type
680 operator()(C& c) const
688 template <typename Sig>
691 template <typename This, typename C>
692 struct result<This(C&)>
695 const_qualified_reverse_iterator_of<C>::type
699 template <typename C>
700 typename result<rend(C&)>::type
701 operator()(C& c) const
709 typedef void result_type;
711 template <typename C, typename Arg>
712 void operator()(C& c, Arg const& count) const
720 typedef void result_type;
722 template <typename C, typename Arg1>
723 void operator()(C& c, Arg1 const& arg1) const
728 template <typename C, typename Arg1, typename Arg2>
729 void operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const
731 c.resize(arg1, arg2);
737 template <typename Sig>
740 template <typename This, typename C>
741 struct result<This(C&)>
743 typedef typename size_type_of<C>::type type;
746 template <typename C>
747 typename result<size(C&)>::type
748 operator()(C& c) const
756 typedef void result_type;
758 template <typename C, typename Arg1, typename Arg2>
759 void operator()(C& c, Arg1 arg1, Arg2 &arg2) const
761 c.splice(arg1, arg2);
777 c.splice(arg1, arg2, arg3);
795 c.splice(arg1, arg2, arg3, arg4);
802 template <typename C>
805 typedef typename value_compare_of<C>::type type;
811 template <typename Sig>
814 template <typename This, typename C>
815 struct result<This(C&)>
816 : result_of::value_comp<C>
819 template <typename C>
820 typename result_of::value_comp<C>::type
821 operator()(C& c) const
823 return c.value_comp();
829 ///////////////////////////////////////////////////////////////////////////////
831 // The lazy functions themselves.
833 ///////////////////////////////////////////////////////////////////////////////
834 namespace adl_barrier
836 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 2)
837 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 3)
838 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 4)
839 BOOST_PHOENIX_ADAPT_CALLABLE(at, ::boost::phoenix::stl::at_impl, 2)
840 BOOST_PHOENIX_ADAPT_CALLABLE(back, stl::back, 1)
841 BOOST_PHOENIX_ADAPT_CALLABLE(begin, stl::begin, 1)
842 BOOST_PHOENIX_ADAPT_CALLABLE(capacity, stl::capacity, 1)
843 BOOST_PHOENIX_ADAPT_CALLABLE(clear, stl::clear, 1)
844 BOOST_PHOENIX_ADAPT_CALLABLE(empty, stl::empty, 1)
845 BOOST_PHOENIX_ADAPT_CALLABLE(end, stl::end, 1)
846 BOOST_PHOENIX_ADAPT_CALLABLE(erase, stl::erase, 2)
847 BOOST_PHOENIX_ADAPT_CALLABLE(erase, stl::erase, 3)
848 BOOST_PHOENIX_ADAPT_CALLABLE(front, stl::front, 1)
849 BOOST_PHOENIX_ADAPT_CALLABLE(get_allocator, stl::get_allocator, 1)
850 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 2)
851 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 3)
852 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 4)
853 BOOST_PHOENIX_ADAPT_CALLABLE(key_comp, stl::key_comp, 1)
854 BOOST_PHOENIX_ADAPT_CALLABLE(max_size, stl::max_size, 1)
855 BOOST_PHOENIX_ADAPT_CALLABLE(pop_back, stl::pop_back, 1)
856 BOOST_PHOENIX_ADAPT_CALLABLE(pop_front, stl::pop_front, 1)
857 BOOST_PHOENIX_ADAPT_CALLABLE(push_back, stl::push_back, 2)
858 BOOST_PHOENIX_ADAPT_CALLABLE(push_front, stl::push_front, 2)
859 BOOST_PHOENIX_ADAPT_CALLABLE(rbegin, stl::rbegin, 1)
860 BOOST_PHOENIX_ADAPT_CALLABLE(rend, stl::rend, 1)
861 BOOST_PHOENIX_ADAPT_CALLABLE(reserve, stl::reserve, 2)
862 BOOST_PHOENIX_ADAPT_CALLABLE(resize, stl::resize, 2)
863 BOOST_PHOENIX_ADAPT_CALLABLE(resize, stl::resize, 3)
864 BOOST_PHOENIX_ADAPT_CALLABLE(size, stl::size, 1)
865 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 2)
866 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 3)
867 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 4)
868 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 5)
869 BOOST_PHOENIX_ADAPT_CALLABLE(value_comp, stl::value_comp, 1)
872 using namespace phoenix::adl_barrier;
873 }} // namespace boost::phoenix
875 #endif // BOOST_PHOENIX_STL_CONTAINERS_HPP