Check if template argument is std :: vector <T> :: iterator
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"); } +6
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"); } +3
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; } +3
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.
+2