Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a template argument is a std::vector<T>::iterator

How to check if a template argument is a std::vector<T>::iterator?

For void type, we have std::is_void. Is there something like that for std::vector<T>::iterator?

like image 951
dot dot dot Avatar asked Nov 09 '16 17:11

dot dot dot


2 Answers

You could create a trait for that:

#include <vector>
#include <list>
#include <type_traits>


template <class T, class = void>
struct is_vector_iterator: std::is_same<T, std::vector<bool>::iterator> { };

template <class T>
struct is_vector_iterator<T, decltype(*std::declval<T>(), std::enable_if_t<!std::is_same<T, std::vector<bool>::iterator>::value>())>: std::is_same<T, typename std::vector<std::decay_t<decltype(*std::declval<T>())>>::iterator> { };

int main() {
    static_assert(is_vector_iterator<std::vector<int>::iterator>::value, "Is not a vector iterator");
    static_assert(is_vector_iterator<std::vector<bool>::iterator>::value, "Is not a vector iterator");
    static_assert(!is_vector_iterator<std::list<int>::iterator>::value, "Is a vector iterator");
    static_assert(!is_vector_iterator<std::list<int>::iterator>::value, "Is a vector iterator");
}

[live demo]

like image 63
W.F. Avatar answered Sep 22 '22 01:09

W.F.


An alternative solution also using std::iterator_traits:

#include <iostream>
#include <vector>
#include <list>

template <typename T>
struct is_vector_iterator 
{
    typedef char yes[1];
    typedef char no[2];

    template <typename C>
    static yes& test(
        typename std::enable_if<
            std::is_same<T, typename std::vector<typename C::value_type>::iterator>::value
        >::type*);

    template <typename>
    static no& test(...);

    static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);

};

int main() {
    std::cout << is_vector_iterator<int>::value << std::endl;
    std::cout << is_vector_iterator<int*>::value << std::endl;
    std::cout << is_vector_iterator<std::list<int>::iterator>::value << std::endl;
    std::cout << is_vector_iterator<std::vector<int>::iterator>::value << std::endl;
    return 0;
}

live demo

like image 31
Pedro Boechat Avatar answered Sep 25 '22 01:09

Pedro Boechat