blob: 00106788f4ba71a1223d488a877c2626a1aa7ee2 [file] [log] [blame]
/*=============================================================================
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 <boost/spirit/home/phoenix/stl/container/detail/container.hpp>
#include <boost/spirit/home/phoenix/function/function.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_const.hpp>
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<stl::assign> 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<C>::type type;
};
template <typename C, typename Arg1>
C& operator()(C& c, Arg1 const& arg1) const
{
c.assign(arg1);
return c;
}
template <typename C, typename Arg1, typename Arg2>
C& operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const
{
c.assign(arg1, arg2);
return c;
}
template <typename C, typename Arg1, typename Arg2, typename Arg3>
C& operator()(
C& c
, Arg1 const& arg1
, Arg2 const& arg2
, Arg3 const& arg3) const
{
return c.assign(arg1, arg2, arg3);
}
};
struct at
{
template <typename C, typename Index>
struct result
{
typedef typename const_qualified_reference_of<C>::type type;
};
template <typename C, typename Index>
typename result<C, Index>::type
operator()(C& c, Index const& i) const
{
return c.at(i);
}
};
struct back
{
template <typename C>
struct result
{
typedef
typename const_qualified_reference_of<C>::type
type;
};
template <typename C>
typename result<C>::type
operator()(C& c) const
{
return c.back();
}
};
struct begin
{
template <typename C>
struct result
{
typedef typename const_qualified_iterator_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C& c) const
{
return c.begin();
}
};
struct capacity
{
template <typename C>
struct result
{
typedef typename size_type_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C const& c) const
{
return c.capacity();
}
};
struct clear
{
template <typename C>
struct result
{
typedef void type;
};
template <typename C>
void operator()(C& c) const
{
return c.clear();
}
};
struct empty
{
template <typename C>
struct result
{
typedef bool type;
};
template <typename C>
bool operator()(C const& c) const
{
return c.empty();
}
};
struct end
{
template <typename C>
struct result
{
typedef typename const_qualified_iterator_of<C>::type type;
};
template <typename C>
typename result<C>::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 <typename C, typename Arg1, typename Arg2 = fusion::void_>
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<C>. 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<Arg1, typename iterator_of<C>::type>
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1500)
, iterator_of<C>
#else
, boost::mpl::identity<void>
#endif
, size_type_of<C>
>
map_erase_result;
typedef typename
boost::mpl::eval_if<
has_mapped_type<C>
, map_erase_result
, iterator_of<C>
>::type
type;
};
template <typename C, typename Arg1>
typename result<C, Arg1>::type
operator()(C& c, Arg1 const& arg1) const
{
return c.erase(arg1);
}
template <typename C, typename Arg1, typename Arg2>
typename result<C, Arg1, Arg2>::type
operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const
{
return c.erase(arg1, arg2);
}
};
struct front
{
template <typename C>
struct result
{
typedef typename const_qualified_reference_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C& c) const
{
return c.front();
}
};
struct get_allocator
{
template <typename C>
struct result
{
typedef typename allocator_type_of<C>::type type;
};
template <typename C>
typename result<C>::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 <typename Iter>
// void C::insert(iterator where, Iter first, Iter last);
//
// where M is a std::map and MM is a std::multimap:
//
// 4) pair<iterator, bool> M::insert(value_type const&);
// 5) iterator MM::insert(value_type const&);
//
// where M is a std::map or std::multimap:
//
// 6) template <typename Iter>
// 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<typename C::iterator, bool> type;
};
typedef
boost::mpl::eval_if<
map_insert_returns_pair<C>
, pair_iterator_bool
, iterator_of<C>
>
choice_1;
typedef
boost::mpl::eval_if<
boost::mpl::and_<
boost::is_same<Arg3, fusion::void_>
, boost::mpl::not_<boost::is_same<Arg1, Arg2> > >
, iterator_of<C>
, boost::mpl::identity<void>
>
choice_2;
public:
typedef typename
boost::mpl::eval_if<
boost::is_same<Arg2, fusion::void_>
, choice_1
, choice_2
>::type
type;
};
template <typename C, typename Arg1>
typename result<C, Arg1>::type
operator()(C& c, Arg1 const& arg1) const
{
return c.insert(arg1);
}
template <typename C, typename Arg1, typename Arg2>
typename result<C, Arg1, Arg2>::type
operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const
{
return c.insert(arg1, arg2);
}
template <typename C, typename Arg1, typename Arg2, typename Arg3>
typename result<C, Arg1, Arg2, Arg3>::type
operator()(
C& c, Arg1 const& arg1, Arg2 const& arg2, Arg3 const& arg3) const
{
return c.insert(arg1, arg2, arg3);
}
};
struct key_comp
{
template <typename C>
struct result
{
typedef typename key_compare_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C const& c) const
{
return c.key_comp();
}
};
struct max_size
{
template <typename C>
struct result
{
typedef typename size_type_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C const& c) const
{
return c.max_size();
}
};
struct pop_back
{
template <typename C>
struct result
{
typedef void type;
};
template <typename C>
void operator()(C& c) const
{
return c.pop_back();
}
};
struct pop_front
{
template <typename C>
struct result
{
typedef void type;
};
template <typename C>
void operator()(C& c) const
{
return c.pop_front();
}
};
struct push_back
{
template <typename C, typename Arg>
struct result
{
typedef void type;
};
template <typename C, typename Arg>
void operator()(C& c, Arg const& data) const
{
return c.push_back(data);
}
};
struct push_front
{
template <typename C, typename Arg>
struct result
{
typedef void type;
};
template <typename C, typename Arg>
void operator()(C& c, Arg const& data) const
{
return c.push_front(data);
}
};
struct rbegin
{
template <typename C>
struct result
{
typedef typename
const_qualified_reverse_iterator_of<C>::type
type;
};
template <typename C>
typename result<C>::type
operator()(C& c) const
{
return c.rbegin();
}
};
struct rend
{
template <typename C>
struct result
{
typedef typename
const_qualified_reverse_iterator_of<C>::type
type;
};
template <typename C>
typename result<C>::type
operator()(C& c) const
{
return c.rend();
}
};
struct reserve
{
template <typename C, typename Arg>
struct result
{
typedef void type;
};
template <typename C, typename Arg>
void operator()(C& c, Arg const& count) const
{
return c.reserve(count);
}
};
struct resize
{
template <typename C, typename Arg1, typename Arg2 = fusion::void_>
struct result
{
typedef void type;
};
template <typename C, typename Arg1>
void operator()(C& c, Arg1 const& arg1) const
{
return c.resize(arg1);
}
template <typename C, typename Arg1, typename Arg2>
void operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const
{
return c.resize(arg1, arg2);
}
};
struct size
{
template <typename C>
struct result
{
typedef typename size_type_of<C>::type type;
};
template <typename C>
typename result<C>::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 <typename C, typename Arg1, typename Arg2>
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 <typename C>
struct result
{
typedef typename value_compare_of<C>::type type;
};
template <typename C>
typename result<C>::type
operator()(C const& c) const
{
return c.value_comp();
}
};
} // namespace stl
///////////////////////////////////////////////////////////////////////////////
//
// The lazy functions themselves.
//
///////////////////////////////////////////////////////////////////////////////
function<stl::assign> const assign = stl::assign();
function<stl::at> const at = stl::at();
function<stl::back> const back = stl::back();
function<stl::begin> const begin = stl::begin();
function<stl::capacity> const capacity = stl::capacity();
function<stl::clear> const clear = stl::clear();
function<stl::empty> const empty = stl::empty();
function<stl::end> const end = stl::end();
function<stl::erase> const erase = stl::erase();
function<stl::front> const front = stl::front();
function<stl::get_allocator> const get_allocator = stl::get_allocator();
function<stl::insert> const insert = stl::insert();
function<stl::key_comp> const key_comp = stl::key_comp();
function<stl::max_size> const max_size = stl::max_size();
function<stl::pop_back> const pop_back = stl::pop_back();
function<stl::pop_front> const pop_front = stl::pop_front();
function<stl::push_back> const push_back = stl::push_back();
function<stl::push_front> const push_front = stl::push_front();
function<stl::rbegin> const rbegin = stl::rbegin();
function<stl::rend> const rend = stl::rend();
function<stl::reserve> const reserve = stl::reserve();
function<stl::resize> const resize = stl::resize();
function<stl::size> const size = stl::size();
function<stl::splice> const splice = stl::splice();
function<stl::value_comp> const value_comp = stl::value_comp();
}} // namespace boost::phoenix
#endif // PHOENIX_STL_CONTAINERS_HPP