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

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

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

+5
source share
4 answers

You can create a trait for this:

 #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]

+6
source

Better to use std :: iterator_traits I think:

 #include <list> #include <vector> #include <iterator> template <class It, class = void> struct is_vector_iterator : std::false_type { }; template <class It> struct is_vector_iterator<It, std::enable_if_t< std::is_same< It, typename std::vector< typename std::iterator_traits<It>::value_type >::iterator >::value >> : std::true_type { }; 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"); } 

Demo

+3
source

An alternative solution also uses 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 demonstration

+3
source

You can write a line for this:

 namespace detail { template<typename T> constexpr std::false_type is_vector_iterator(T&&, ...) { return {}; } template<typename T> constexpr auto is_vector_iterator(T&& t, void* = nullptr) -> decltype(std::is_same<typename std::vector<std::decay_t<decltype(*t)>>::iterator, std::decay_t<T>>{}) { return {}; } } template<typename T> struct is_vector_iterator : decltype(detail::is_vector_iterator(declval<T>(), 0)) {}; 

Here I get the decayed type * t to make vector<type>::iterator and check that for equality with T It works, except for vector<bool> , which is not really a vector.

demo

+2
source

Source: https://habr.com/ru/post/1259515/


All Articles