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

Frank picture Frank · Aug 20, 2012 · Viewed 21.1k times · Source

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.

Answer

Nevermore picture Nevermore · Jul 3, 2015

Look, another SFINAE-based solution for detecting STL-like containers:

template<typename T, typename _ = void>
struct is_container : std::false_type {};

template<typename... Ts>
struct is_container_helper {};

template<typename T>
struct is_container<
        T,
        std::conditional_t<
            false,
            is_container_helper<
                typename T::value_type,
                typename T::size_type,
                typename T::allocator_type,
                typename T::iterator,
                typename T::const_iterator,
                decltype(std::declval<T>().size()),
                decltype(std::declval<T>().begin()),
                decltype(std::declval<T>().end()),
                decltype(std::declval<T>().cbegin()),
                decltype(std::declval<T>().cend())
                >,
            void
            >
        > : public std::true_type {};

Of course, you might change methods and types to be checked.

If you want to detect only STL containers (it means std::vector, std::list, etc) you should do something like this.