Alex Rivera | Logout

How to write a type trait `is_container` or `is_vector`?

Asked 2012-08-20T18:11:40.110
42

Is it possible to write a type trait whose value is true for all common STL structures (e.g., vector, set, map, ...)?

To get started, I'd like to write a type trait that is true for a vector and false otherwise. I tried this, but it doesn't compile:

template<class T, typename Enable = void>
struct is_vector {
  static bool const value = false;
};

template<class T, class U>
struct is_vector<T, typename boost::enable_if<boost::is_same<T, std::vector<U> > >::type> {
  static bool const value = true;
};

The error message is template parameters not used in partial specialization: U.

Edit
Report

3 Answers

24

Actually, after some trial and error I found it's quite simple:

template<class T>
struct is_vector<std::vector<T> > {
  static bool const value = true;
};

I'd still like to know how to write a more general is_container. Do I have to list all types by hand?

answered 2012-08-20T18:31:07.357
20

You would say that it should be simpler than that...

template <typename T, typename _ = void>
struct is_vector { 
    static const bool value = false;
};
template <typename T>
struct is_vector< T,
                  typename enable_if<
                      is_same<T,
                              std::vector< typename T::value_type,
                                           typename T::allocator_type >
                             >::value
                  >::type
                >
{
    static const bool value = true;
};

... But I am not really sure of whether that is simpler or not.

In C++11 you can use type aliases (I think, untested):

template <typename T>
using is_vector = is_same<T, std::vector< typename T::value_type,
                                          typename T::allocator_type > >;

The problem with your approach is that the type U is non-deducible in the context where it is used.

answered 2012-08-20T18:26:54.727
10

Why not do something like this for is_container?

template <typename Container>
struct is_container : std::false_type { };

template <typename... Ts> struct is_container<std::list<Ts...> > : std::true_type { };
template <typename... Ts> struct is_container<std::vector<Ts...> > : std::true_type { };
// ...

That way users can add their own containers by partially-specializing. As for is_vector et-al, just use partial specialization as I did above, but limit it to only one container type, not many.

answered 2012-08-20T22:00:37.660

Your Answer