multi_type_map.tpp
/*
CLAW - a C++ Library Absolutely Wonderful
CLAW is a free library without any particular aim but being useful to
anyone.
Copyright (C) 2005-2011 Julien Jorge
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
contact: julien.jorge@gamned.org
*/
/**
* \file multi_type_map.tpp
* \brief Implementation of the claw::multi_type_map class.
* \author Julien Jorge
*/
#include <claw/assert.hpp>
#include <claw/meta/same_type.hpp>
namespace claw
{
/*
* Here is the implementation of multi_type_map_wrapper for the case where the
* ValueType is the first type in the type list of the map.
*/
template<typename Key, typename Head, typename Tail>
class multi_type_map_wrapper
< Head, multi_type_map<Key, meta::type_list<Head, Tail> > >
{
typedef Key key_type;
typedef Head value_type;
typedef multi_type_map<Key, meta::type_list<Head, Tail> > map_type;
typedef typename map_type::iterator_type iterator;
typedef typename map_type::const_iterator_type const_iterator;
public:
static void erase( map_type& self, iterator it )
{
self.m_data.erase(it);
}
static std::size_t erase( map_type& self, const key_type& k )
{
return self.m_data.erase(k);
}
static const value_type& get( const map_type& self, const key_type& k )
{
CLAW_PRECOND( exists(self, k) );
return self.m_data.find(k)->second;
}
static value_type& get( map_type& self, const key_type& k )
{
CLAW_PRECOND( exists(self, k) );
return self.m_data.find(k)->second;
}
static void set( map_type& self, const key_type& k, const value_type& v )
{
self.m_data[k] = v;
}
static bool exists( const map_type& self, const key_type& k )
{
return self.m_data.find(k) != self.m_data.end();
}
static iterator begin( map_type& self )
{
return self.m_data.begin();
}
static iterator end( map_type& self )
{
return self.m_data.end();
}
static const_iterator begin( const map_type& self )
{
return self.m_data.begin();
}
static const_iterator end( const map_type& self )
{
return self.m_data.end();
}
}; // class multi_type_map_wrapper
/*
* Here is the implementation of multi_type_map_wrapper for the case where the
* ValueType is not the first type in the type list of the map.
*/
template<typename ValueType, typename Key, typename Head, typename Tail>
class multi_type_map_wrapper
< ValueType, multi_type_map< Key, meta::type_list<Head, Tail> > >:
public multi_type_map_wrapper< ValueType, multi_type_map<Key, Tail> >
{
}; // class multi_type_map_wrapper
/*
* Here is the implementation of multi_type_map_helper for the case where the
* ValueType is the first type in the type list of the map.
*/
template<typename Key, typename Head, typename Tail>
class multi_type_map_helper
< multi_type_map<Key, meta::type_list<Head, Tail> > >
{
typedef Key key_type;
typedef Head value_type;
typedef multi_type_map<Key, meta::type_list<Head, Tail> > map_type;
typedef typename map_type::iterator_type iterator;
typedef typename map_type::const_iterator_type const_iterator;
public:
static void set( map_type& self, const map_type& that )
{
for ( const_iterator it=that.template begin<value_type>();
it!=that.template end<value_type>(); ++it )
self.template set<Head>( it->first, it->second );
multi_type_map_helper< multi_type_map<Key, Tail> >::set( self, that );
} // size()
static std::size_t size( const map_type& self )
{
return self.m_data.size()
+ multi_type_map_helper< multi_type_map<Key, Tail> >::size( self );
} // size()
}; // class multi_type_map_helper
/*
* Here is the implementation of multi_type_map_helper that stops the
* recursivity.
*/
template<typename Key>
class multi_type_map_helper
< multi_type_map< Key, claw::meta::no_type > >
{
private:
typedef multi_type_map<Key, claw::meta::no_type> map_type;
public:
static void set( map_type& self, const map_type& that )
{
// nothing to do
} // set()
static std::size_t size( const map_type& self )
{
return 0;
} // size()
}; // class multi_type_map_helper
} // namespace claw
/*----------------------------------------------------------------------------*/
/**
* \brief Erase a value from the map.
* \param k The key of the value to erase.
* \return The number of removed elements (zero or one).
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
void
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::erase
( typename iterator<ValueType>::type it )
{
multi_type_map_wrapper<ValueType, self_type>::erase(*this, it);
} // multi_type_map::erase()
/*----------------------------------------------------------------------------*/
/**
* \brief Erase a value from the map.
* \param k The key of the value to erase.
* \return The number of removed elements (zero or one).
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
std::size_t
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::erase
( const key_type& k )
{
return multi_type_map_wrapper<ValueType, self_type>::erase(*this, k);
} // multi_type_map::erase()
/*----------------------------------------------------------------------------*/
/**
* \brief Get a value from the map.
* \param k The key of the value to get.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
const ValueType&
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::get
( const key_type& k ) const
{
return multi_type_map_wrapper<ValueType, self_type>::get(*this, k);
} // multi_type_map::get()
/*----------------------------------------------------------------------------*/
/**
* \brief Get a value from the map.
* \param k The key of the value to get.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
ValueType& claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::get
( const key_type& k )
{
return multi_type_map_wrapper<ValueType, self_type>::get(*this, k);
} // multi_type_map::get()
/*----------------------------------------------------------------------------*/
/**
* \brief Set a value in the map.
* \param k The key of the value to set.
* \param v The value to set.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
void claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::set
( const key_type& k, const ValueType& v )
{
return multi_type_map_wrapper<ValueType, self_type>::set(*this, k, v);
} // multi_type_map::set()
/*----------------------------------------------------------------------------*/
/**
* \brief Set a value in the map.
* \param k The key of the value to set.
* \param v The value to set.
*/
template<typename Key, typename Head, typename Tail>
void claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::set
( const self_type& m )
{
multi_type_map_helper<self_type>::set(*this, m);
} // multi_type_map::set()
/*----------------------------------------------------------------------------*/
/**
* \brief Tell if the map contains a value of a given type with a given key.
* \param k The key of the value to get.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
bool claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::exists
( const key_type& k ) const
{
return multi_type_map_wrapper<ValueType, self_type>::exists(*this, k);
} // multi_type_map::exists()
/*----------------------------------------------------------------------------*/
/**
* \brief Return the number of elements in the map.
*/
template<typename Key, typename Head, typename Tail>
std::size_t
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::size() const
{
return multi_type_map_helper<self_type>::size(*this);
} // multi_type_map::size()
/*----------------------------------------------------------------------------*/
/**
* \brief Get an iterator on the beginning of the map for a given type.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
typename claw::multi_type_map
< Key, claw::meta::type_list<Head, Tail> >::template iterator<ValueType>::type
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::begin()
{
return multi_type_map_wrapper<ValueType, self_type>::begin(*this);
} // multi_type_map::begin()
/*----------------------------------------------------------------------------*/
/**
* \brief Get an iterator on the end of the map for a given type.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
typename claw::multi_type_map
< Key, claw::meta::type_list<Head, Tail> >::template iterator<ValueType>::type
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::end()
{
return multi_type_map_wrapper<ValueType, self_type>::end(*this);
} // multi_type_map::end()
/*----------------------------------------------------------------------------*/
/**
* \brief Get an iterator on the beginning of the map for a given type.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
typename
claw::multi_type_map
< Key, claw::meta::type_list<Head, Tail> >
::template iterator<ValueType>::const_type
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::begin() const
{
return multi_type_map_wrapper<ValueType, self_type>::begin(*this);
} // multi_type_map::begin()
/*----------------------------------------------------------------------------*/
/**
* \brief Get an iterator on the end of the map for a given type.
*/
template<typename Key, typename Head, typename Tail>
template<typename ValueType>
typename
claw::multi_type_map
< Key, claw::meta::type_list<Head, Tail> >
::template iterator<ValueType>::const_type
claw::multi_type_map< Key, claw::meta::type_list<Head, Tail> >::end() const
{
return multi_type_map_wrapper<ValueType, self_type>::end(*this);
} // multi_type_map::end()