3

I looked through the listing of std::type_traits but I didn't see anything in there pertaining to an std container.

I'm looking to validate that a std container was passed into a template type at compile time.

template < typename T >
void foo( T bar )
{
    static_assert( is_std_container??? );
}
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • no such thing exists, and I dont think it makes any sense. what might make sense would be if it fulfills the concept of a certain type of container, but I would think that needs to wait until concepts (light) – PlasmaHH Jun 18 '14 at 12:16
  • If you only need to support a fixed set of container types, you can just write your own traits class. – ComicSansMS Jun 18 '14 at 12:31
  • 1
    Related/duplicate: http://stackoverflow.com/q/12042824 duplicate: http://stackoverflow.com/q/7617203 duplicate: http://stackoverflow.com/q/9407367 Thanks for searching. – dyp Jun 18 '14 at 13:05

2 Answers2

6

It does not exist.

You can create your own trait if you know the set of container types that should be supported :

template<class T>
struct is_container
{
    static const bool value = false;
};

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

// ... same specializations for other containers.

And you use it like other traits:

cout << is_container<std::vector<int>>::value << endl;
cout << is_container<int>::value << endl;

See it here.

Note that usually you should pass iterators to your functions, not containers. So you keep your code container-independent and much more generic.

quantdev
  • 23,517
  • 5
  • 55
  • 88
5

As already other guys answered in the comments there's no standard way of doing this. However, you could define your own trait system to determine whether a type is std container or not like in the example below:

#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <deque>
#include <unordered_set>
#include <unordered_map>
#include <type_traits>

template <typename T> struct container_traits {
  static bool const value = false;  
};

template <typename... Args>
struct container_traits<std::vector<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::deque<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::list<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::set<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::map<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::unordered_set<Args...>> {
  static bool const value = true;
};

template <typename... Args>
struct container_traits<std::unordered_map<Args...>> {
  static bool const value = true;
};

template<typename T>
struct is_std {
    static constexpr bool const value = container_traits<T>::value;
};

auto main() -> int {
  std::vector<int> v;
  std::cout << std::boolalpha << is_std<decltype(v)>::value << std::endl;
  std::deque<int> dq;
  std::cout << std::boolalpha << is_std<decltype(dq)>::value << std::endl;
  std::set<int> s;
  std::cout << std::boolalpha << is_std<decltype(s)>::value << std::endl;
  std::map<int, int> m;
  std::cout << std::boolalpha << is_std<decltype(m)>::value << std::endl;
  std::unordered_set<int> us;
  std::cout << std::boolalpha << is_std<decltype(us)>::value << std::endl;
  std::unordered_map<int, int> um;
  std::cout << std::boolalpha << is_std<decltype(um)>::value << std::endl;
  std::list<int> l;
  std::cout << std::boolalpha << is_std<decltype(l)>::value << std::endl;
  int i;
  std::cout << std::boolalpha << is_std<decltype(i)>::value << std::endl;
  double d;
  std::cout << std::boolalpha << is_std<decltype(d)>::value << std::endl;

  return 0;
}

DEMO

101010
  • 41,839
  • 11
  • 94
  • 168
  • This is good use of variadic templates to avoid stating the extra constructor parameters for all the containers. std::boolalpha only needs be sent to std::cout once; not every time. – Trevor Hickey Nov 06 '14 at 01:27