|
Boost : |
From: Thorsten Ottosen (nesotto_at_[hidden])
Date: 2003-03-07 18:17:58
Hereby at least a partial solution which so far works with gcc3.2 and comeau
4.3.0.1.
The complete source can be found in the sandbox :
boost-sandbox/libs/sequence_algo/test/container_traits.hpp
boost-sandbox/boost/sequence_algo/container_traits.hpp
my code does not include <vector>, <list> or <map>, but it does need
<iterator>.
Some of the functionality of the container_traits are shown here:
template< typename C >
bool is_container()
{
return boost::container_traits<C>::is_container();
}
template< typename C >
bool is_sequence()
{
return boost::container_traits<C>::is_sequence();
}
template< typename C >
bool is_contiguous_sequence()
{
return boost::container_traits<C>::is_contiguous_sequence();
}
template< typename C >
bool is_associative()
{
return boost::container_traits<C>::is_associative();
}
int main()
{
using namespace boost;
using namespace std;
typedef list<int> list_t;
typedef vector<int> vector_t;
typedef map<int,int> map_t;
assert( is_container<vector_t>() );
assert( is_sequence<vector_t>() );
assert( is_sequence<list_t>() );
assert( !is_sequence<map_t>() );
assert( is_contiguous_sequence<vector_t>() );
assert( !is_contiguous_sequence<list_t>() );
assert( !is_contiguous_sequence<map_t>() );
assert( is_associative<map_t>() );
assert( !is_associative<vector_t>() );
assert( !is_associative<list_t>() );
}
--------------
The implementation uses SFINAE and relys on some assumptions that I'm not a
100% sure about. The core of the implementation is this:
template< typename C >
true_t is_container( const C&, const typename C::iterator& =
typename C::iterator() );
template< typename T, std::size_t sz >
true_t is_container( const T (&)[sz] );
false_t is_container( ... );
template< typename C >
true_t is_associative_container( const C&,
const typename C::key_type =
typename C::key_type() );
false_t is_associative_container( ... );
template< typename C >
struct tag_generator
{
static C& c;
BOOST_STATIC_CONSTANT( bool, is_container_ = sizeof( true_t )
== sizeof( is_container( c ) ) );
BOOST_STATIC_CONSTANT( bool, is_associative_container_ =
sizeof( true_t ) ==
sizeof( is_associative_container( c ) ) );
BOOST_STATIC_CONSTANT( bool, is_sequence_container_ =
is_container_ &&
not is_associative_container_ );
enum { has_random_access_iterator_ =
::boost::is_same< std::random_access_iterator_tag,
typename std::iterator_traits<
typename container_traits<C>::iterator >
::iterator_category
>::value };
BOOST_STATIC_CONSTANT( bool, is_contiguous_sequence_container_
= ::boost::is_array<C>::value ||
is_sequence_container_ &&
has_random_access_iterator_ );
};
Comments are more than welcome.
regards
Thorsten
PS: How do you all use BOOST_STATIC_CONSTANT together with typetraits that
takes two parameters? As you can see I had to fall back on an enum.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk