I have a problem where I need to detect whether a given type is an instance of a known nested type such as std::vector::iterator at compile time. I’d like to create the type trait is_std_vector_iterator:
#include <type_traits>
#include <vector>
template<typename T> struct is_std_vector_iterator : std::false_type {};
template<typename T, typename Allocator>
struct is_std_vector_iterator<typename std::vector<T,Allocator>::iterator>
: std::true_type
{};
int main()
{
return 0;
}
But I receive the compiler error:
$ g++ -std=c++0x test.cpp
test.cpp:7: error: template parameters not used in partial specialization:
test.cpp:7: error: ‘T’
test.cpp:7: error: ‘Allocator’
Is it possible to check for a dependent type like std::vector<T,Allocator>::iterator?
Here’s a motivating use case of such a trait:
template<typename Iterator>
Iterator my_copy(Iterator first, Iterator last, Iterator result, std::true_type)
{
// iterators are just pointer wrappers; call memcpy
memcpy(&*result, &*first, sizeof(typename Iterator::value_type) * last - first);
return result + last - first;
}
template<typename Iterator>
Iterator my_copy(Iterator first, Iterator last, Iterator result, std::false_type)
{
// use a general copy
return std::copy(first, last, result);
}
template<typename Iterator>
Iterator my_copy(Iterator first, Iterator last, Iterator result)
{
// dispatch based on the type of Iterator
return my_copy(first, last, result, typename is_std_vector_iterator<Iterator1>::type())
}
Well, in the simplest case scenario it could look something like this:
But the real problem comes when someone decides to use allocator different from default one. Since you want to check iterator against some well known type, not a well known template, then you can basically use this and possibly extend it with some allocators that you are aware of. Otherwise, a template instantiated with different types is a different type, and I am not sure if there is a way to test if a type is an instance of template specialized with some arbitrary parameter, there is probably no such way.
On the other hand, you may solve this problem differently. For example, what difference it makes whether this is
std::vector<...>iterator or not? It might make sense to check whether it is random access or not, etc.UPDATE:
For continuously laid out memory, I’d say the best bet is to use iterator traits and check for random access tag. For example:
This one will be definitely simpler and even more solid than checking against
std::vectorwith allocators. However, even in this case someone can fool you if they really want, buy providing you random access iterator that provides seamless access to different chunks of memory, and you will have big problems once you convert that into a pointer use pointer arithmetics rather than iterator’s overloaded operators. You can protect yourself against that only by comparing memory addresses while changing both raw pointer and iterator, but there is no juice.Hope it helps.