Search code examples
c++templatessfinae

How to check if a template parameter is an iterator type or not?


template<class T>
struct is_iterator
{
    static const bool value = ??? // What to write ???
};

int main()
{
    assert(false == is_iterator<int>::value);
    assert(true == is_iterator<vector<int>::iterator>::value);
    assert(true == is_iterator<list<int>::iterator>::value);
    assert(true == is_iterator<string::iterator>::value);
    assert(true == is_iterator<char*>::value); // a raw pointer is also an iterator
}

The question is: How to make the five assert statements pass?


Solution

  • template<class T>
    struct is_iterator
    {   
        static T makeT();
        typedef void * twoptrs[2];  // sizeof(twoptrs) > sizeof(void *)
        static twoptrs & test(...); // Common case
        template<class R> static typename R::iterator_category * test(R); // Iterator
        template<class R> static void * test(R *); // Pointer
    
        static const bool value = sizeof(test(makeT())) == sizeof(void *); 
    };