/*============================================================================= Copyright (c) 2004 Angus Leeming Copyright (c) 2004 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #ifndef PHOENIX_STL_CONTAINER_CONTAINER_HPP #define PHOENIX_STL_CONTAINER_CONTAINER_HPP #include #include #include #include #include #include namespace boost { namespace phoenix { /////////////////////////////////////////////////////////////////////////////// // // STL container member functions // // Lazy functions for STL container member functions // // These functions provide a mechanism for the lazy evaluation of the // public member functions of the STL containers. For an overview of // what is meant by 'lazy evaluation', see the comments in operators.hpp // and functions.hpp. // // Lazy functions are provided for all of the member functions of the // following containers: // // deque - list - map - multimap - vector. // // Indeed, should *your* class have member functions with the same names // and signatures as those listed below, then it will automatically be // supported. To summarize, lazy functions are provided for member // functions: // // assign - at - back - begin - capacity - clear - empty - end - // erase - front - get_allocator - insert - key_comp - max_size - // pop_back - pop_front - push_back - push_front - rbegin - rend - // reserve - resize . size - splice - value_comp. // // The lazy functions' names are the same as the corresponding member // function. Sample usage: // // "Normal" version "Lazy" version // ---------------- -------------- // my_vector.at(5) phoenix::at(arg1, 5) // my_list.size() phoenix::size(arg1) // my_vector1.swap(my_vector2) phoenix::swap(arg1, arg2) // // Notice that member functions with names that clash with a // function in stl algorithms are absent. This will be provided // in Phoenix's algorithm module. // // No support is provided here for lazy versions of operator+=, // operator[] etc. Such operators are not specific to STL containers and // lazy versions can therefore be found in operators.hpp. // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // Lazy member function implementaions. // // The structs below provide the guts of the implementation. Thereafter, // the corresponding lazy function itself is simply: // // function const assign = stl::assign(); // // The structs provide a nested "result" class template whose // "type" typedef enables the lazy function to ascertain the type // to be returned when it is invoked. // // They also provide operator() member functions with signatures // corresponding to those of the underlying member function of // the STL container. // /////////////////////////////////////////////////////////////////////////////// namespace stl { struct assign { template < typename C , typename Arg1 = fusion::void_ , typename Arg2 = fusion::void_ , typename Arg3 = fusion::void_ > struct result { typedef typename add_reference::type type; }; template C& operator()(C& c, Arg1 const& arg1) const { c.assign(arg1); return c; } template C& operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const { c.assign(arg1, arg2); return c; } template C& operator()( C& c , Arg1 const& arg1 , Arg2 const& arg2 , Arg3 const& arg3) const { return c.assign(arg1, arg2, arg3); } }; struct at { template struct result { typedef typename const_qualified_reference_of::type type; }; template typename result::type operator()(C& c, Index const& i) const { return c.at(i); } }; struct back { template struct result { typedef typename const_qualified_reference_of::type type; }; template typename result::type operator()(C& c) const { return c.back(); } }; struct begin { template struct result { typedef typename const_qualified_iterator_of::type type; }; template typename result::type operator()(C& c) const { return c.begin(); } }; struct capacity { template struct result { typedef typename size_type_of::type type; }; template typename result::type operator()(C const& c) const { return c.capacity(); } }; struct clear { template struct result { typedef void type; }; template void operator()(C& c) const { return c.clear(); } }; struct empty { template struct result { typedef bool type; }; template bool operator()(C const& c) const { return c.empty(); } }; struct end { template struct result { typedef typename const_qualified_iterator_of::type type; }; template typename result::type operator()(C& c) const { return c.end(); } }; struct erase { // This mouthful can differentiate between the generic erase // functions (Container == std::deque, std::list, std::vector) and // that specific to the two map-types, std::map and std::multimap. // // where C is a std::deque, std::list, std::vector: // // 1) iterator C::erase(iterator where); // 2) iterator C::erase(iterator first, iterator last); // // where M is a std::map or std::multimap: // // 3) size_type M::erase(const Key& keyval); // 4) void M::erase(iterator where); // 5) void M::erase(iterator first, iterator last); template struct result { // BOOST_MSVC #if branch here in map_erase_result non- // standard behavior. The return type should be void but // VC7.1 prefers to return iterator_of. As a result, // VC7.1 complains of error C2562: // boost::phoenix::stl::erase::operator() 'void' function // returning a value. Oh well... :* typedef boost::mpl::eval_if< boost::is_same::type> #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1500) , iterator_of #else , boost::mpl::identity #endif , size_type_of > map_erase_result; typedef typename boost::mpl::eval_if< has_mapped_type , map_erase_result , iterator_of >::type type; }; template typename result::type operator()(C& c, Arg1 const& arg1) const { return c.erase(arg1); } template typename result::type operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const { return c.erase(arg1, arg2); } }; struct front { template struct result { typedef typename const_qualified_reference_of::type type; }; template typename result::type operator()(C& c) const { return c.front(); } }; struct get_allocator { template struct result { typedef typename allocator_type_of::type type; }; template typename result::type operator()(C const& c) const { return c.get_allocator(); } }; struct insert { // This mouthful can differentiate between the generic insert // functions (Container == deque, list, vector) and those // specific to the two map-types, std::map and std::multimap. // // where C is a std::deque, std::list, std::vector: // // 1) iterator C::insert(iterator where, value_type value); // 2) void C::insert( // iterator where, size_type count, value_type value); // 3) template // void C::insert(iterator where, Iter first, Iter last); // // where M is a std::map and MM is a std::multimap: // // 4) pair M::insert(value_type const&); // 5) iterator MM::insert(value_type const&); // // where M is a std::map or std::multimap: // // 6) template // void M::insert(Iter first, Iter last); template < typename C , typename Arg1 , typename Arg2 = fusion::void_ , typename Arg3 = fusion::void_ > class result { struct pair_iterator_bool { typedef typename std::pair type; }; typedef boost::mpl::eval_if< map_insert_returns_pair , pair_iterator_bool , iterator_of > choice_1; typedef boost::mpl::eval_if< boost::mpl::and_< boost::is_same , boost::mpl::not_ > > , iterator_of , boost::mpl::identity > choice_2; public: typedef typename boost::mpl::eval_if< boost::is_same , choice_1 , choice_2 >::type type; }; template typename result::type operator()(C& c, Arg1 const& arg1) const { return c.insert(arg1); } template typename result::type operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const { return c.insert(arg1, arg2); } template typename result::type operator()( C& c, Arg1 const& arg1, Arg2 const& arg2, Arg3 const& arg3) const { return c.insert(arg1, arg2, arg3); } }; struct key_comp { template struct result { typedef typename key_compare_of::type type; }; template typename result::type operator()(C const& c) const { return c.key_comp(); } }; struct max_size { template struct result { typedef typename size_type_of::type type; }; template typename result::type operator()(C const& c) const { return c.max_size(); } }; struct pop_back { template struct result { typedef void type; }; template void operator()(C& c) const { return c.pop_back(); } }; struct pop_front { template struct result { typedef void type; }; template void operator()(C& c) const { return c.pop_front(); } }; struct push_back { template struct result { typedef void type; }; template void operator()(C& c, Arg const& data) const { return c.push_back(data); } }; struct push_front { template struct result { typedef void type; }; template void operator()(C& c, Arg const& data) const { return c.push_front(data); } }; struct rbegin { template struct result { typedef typename const_qualified_reverse_iterator_of::type type; }; template typename result::type operator()(C& c) const { return c.rbegin(); } }; struct rend { template struct result { typedef typename const_qualified_reverse_iterator_of::type type; }; template typename result::type operator()(C& c) const { return c.rend(); } }; struct reserve { template struct result { typedef void type; }; template void operator()(C& c, Arg const& count) const { return c.reserve(count); } }; struct resize { template struct result { typedef void type; }; template void operator()(C& c, Arg1 const& arg1) const { return c.resize(arg1); } template void operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const { return c.resize(arg1, arg2); } }; struct size { template struct result { typedef typename size_type_of::type type; }; template typename result::type operator()(C const& c) const { return c.size(); } }; struct splice { template < typename C , typename Arg1 , typename Arg2 , typename Arg3 = fusion::void_ , typename Arg4 = fusion::void_ > struct result { typedef void type; }; template void operator()(C& c, Arg1 const& arg1, Arg2& arg2) const { c.splice(arg1, arg2); } template < typename C , typename Arg1 , typename Arg2 , typename Arg3 > void operator()( C& c , Arg1 const& arg1 , Arg2& arg2 , Arg3 const& arg3 ) const { c.splice(arg1, arg2, arg3); } template < typename C , typename Arg1 , typename Arg2 , typename Arg3 , typename Arg4 > void operator()( C& c , Arg1 const& arg1 , Arg2& arg2 , Arg3 const& arg3 , Arg4 const& arg4 ) const { c.splice(arg1, arg2, arg3, arg4); } }; struct value_comp { template struct result { typedef typename value_compare_of::type type; }; template typename result::type operator()(C const& c) const { return c.value_comp(); } }; } // namespace stl /////////////////////////////////////////////////////////////////////////////// // // The lazy functions themselves. // /////////////////////////////////////////////////////////////////////////////// function const assign = stl::assign(); function const at = stl::at(); function const back = stl::back(); function const begin = stl::begin(); function const capacity = stl::capacity(); function const clear = stl::clear(); function const empty = stl::empty(); function const end = stl::end(); function const erase = stl::erase(); function const front = stl::front(); function const get_allocator = stl::get_allocator(); function const insert = stl::insert(); function const key_comp = stl::key_comp(); function const max_size = stl::max_size(); function const pop_back = stl::pop_back(); function const pop_front = stl::pop_front(); function const push_back = stl::push_back(); function const push_front = stl::push_front(); function const rbegin = stl::rbegin(); function const rend = stl::rend(); function const reserve = stl::reserve(); function const resize = stl::resize(); function const size = stl::size(); function const splice = stl::splice(); function const value_comp = stl::value_comp(); }} // namespace boost::phoenix #endif // PHOENIX_STL_CONTAINERS_HPP