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
?
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
?
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");
}
is_vector_iterator<std::list<int>::iterator>
. –
Fremantle std::vector<bool>::iterator
;) –
Utilitarian std::decay_t<decltype(*std::declval<T>())>
instead of just T::value_type
? –
Biocellate value_type
included (as Bo Persson suggested it is even allowed it to be defined as pointer to contained type)... –
Sinuosity 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;
}
std::list<int>::iterator
. The purpose is to determine if it's a std::vector<T>::iterator
or not. Not just an iterator. –
Ender Better using 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");
}
std::iterator_traits<It>::value_type
instead of It::value_type
? –
Biocellate std::vector<T>::iterator
to be T*
and a pointer doesn't have a value_type
member. –
Ender bool
where *std::declval<It>()
is not a bool&
but a proxy. –
Ender You can write a trait 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'm getting the decayed type of *t to make vector<type>::iterator
and check that for equality with T
. It works with the exception of vector<bool>
which isn't really a vector anyway.
It is possible to implement a custom type trait, is_vector_iterator
, which evaluates to true if the type T
is the same as std::vector<U>::iterator
.
The basic idea is to create a helper type trait that accepts two different types as template parameters. It is partial-specialized for the case in which the second argument is the same as std::vector <U>::iterator
, where the type U
is the value_type
of the iterator. Thus, the helper is specialized for only the type T
. If the above type is not a std::vector
container iterator, the first class is selected; otherwise, the second one is selected.
Example:
namespace detail {
template <typename, typename>
struct is_vector_iterator
: std::false_type {};
template <typename T>
struct is_vector_iterator<T, typename std::vector<typename std::iterator_traits<T>::value_type>::iterator>
: std::true_type {};
}
template <typename T>
struct is_vector_iterator
: detail::is_vector_iterator<T, T> {};
template <typename T>
inline constexpr bool is_vector_iterator_v = is_vector_iterator<T>::value;
© 2022 - 2025 — McMap. All rights reserved.
<T>
didn't show up before I add . Sorry for that. I was thinking about writing custom traits. Liketemplate <template <typename T> std::vector<T> class> struct is_vec_iterator { static const bool value = true; };
– KandacekandaharVecIt
and then verify thattypename std::vector<typename std::iterator_traits<VecIt>::value_type>::iterator
andVecIt
name the same type, but that doesn't guarantee that the thing you got is actually an iterator into a vector, so it's not that useful. – Poperystd::vector<T>::iterator
to beT*
. That could give you lots of false positives for any tests you design. – Mirabel