Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Full SFINAE type trait for containers
#include <vector>
#include <string>
#include <utility>
#include <iostream>
template<typename T>
struct has_const_iterator
typedef char one;
typedef struct { char array[2]; } two;
template<typename C> static one test(typename C::const_iterator*);
template<typename C> static two test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(one);
typedef T type;
template <typename T>
struct has_begin_end
struct Dummy { typedef void const_iterator; };
typedef typename std::conditional<has_const_iterator<T>::value, T, Dummy>::type TType;
typedef typename TType::const_iterator iter;
struct Fallback { iter begin() const; iter end() const; };
struct Derived : TType, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<iter (Fallback::*)() const, &C::begin>*))[1];
template<typename C> static char (&f(...))[2];
template<typename C> static char (&g(ChT<iter (Fallback::*)() const, &C::end>*))[1];
template<typename C> static char (&g(...))[2];
static bool const beg_value = sizeof(f<Derived>(0)) == 2;
static bool const end_value = sizeof(g<Derived>(0)) == 2;
template <typename T>
struct is_container
static const bool value = has_const_iterator<T>::value &&
has_begin_end<T>::beg_value && has_begin_end<T>::end_value;
struct Foo { typedef int const_iterator; };
struct Goo { typedef int const_iterator; const_iterator begin() const; };
typedef std::pair<int, int> PT;
int main()
std::cout << is_container<int>::value << std::endl
<< is_container<Foo>::value << std::endl
<< is_container<Goo>::value << std::endl
<< is_container<PT>::value << std::endl
<< is_container<std::vector<int>>::value << std::endl
<< is_container<std::string>::value << std::endl

louisdx commented Jul 11, 2011

To be extremely pedantic on Line 24, I could have said:

typedef typename std::conditional<std::is_class<T>::value && has_const_iterator<T>::value, T, Dummy>::type TType;

However, I assume that anything that passes has_const_iterator must already be of class type, so I believe that's superfluous.

Also, why isn't static bool evaluation short-circuited?

sytelus commented Jun 5, 2016

The prettyprint library has much more extensive definitions. I've isolated its code so these traits are in just one include file. See my blog post:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment