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
.
What is a type trait? A type trait is a simple template struct that contains a member constant, which in turn holds the answer to the question the type trait asks or the transformation it performs.
The type-traits library also contains a set of classes that perform a specific transformation on a type; for example, they can remove a top-level const or volatile qualifier from a type. Each class that performs a transformation defines a single typedef-member type that is the result of the transformation.
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.
UPDATE. As @Deduplicator noted, container might not meet AllocatorAwareContainer requirements (e.g.: std::array<T, N>
). That is why check on T::allocator_type
is not neccessary. But you may check any/all Container requirements in a similar way.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With