Boost logo

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