I'm trying to overload a certain function so only iterators of contiguous containers (which are std::vector::iterator ,std::array::iterator ,and built-in arrays iterators == raw pointers) can be a valid argument.
for some reason my functions fail to compile for vector and std::array :
functions:
template <class T,size_t N>
void catchIterator(typename std::array<T, N>::iterator it) {
//do somthing
}
template <class T>
void catchIterator(typename std::vector<T>::iterator it) {
//do somthing
}
example of use :
std::array<int, 10> arr;
auto it = arr.begin();
catchIterator(it);
std::vector<int> vec;
auto it0 = vec.begin();
catchIterator(it0);
Errors :
Error (active) no instance of overloaded function "catchIterator" matches the argument list
Error (active) no instance of overloaded function "catchIterator" matches the argument list
Error C2783 'void catchIterator(std::array<_Ty,_Size>::iterator)': could not deduce template argument for 'T'
Error C2783 'void catchIterator(std::array<_Ty,_Size>::iterator)': could not deduce template argument for 'N'
Error C2672 'catchIterator': no matching overloaded function found
I'm using VC++ with Visual studio 2015 RTM.
The errors are pretty self-explanatory, but I wonder if the compiler couldn't really deduce T and N from it and it0, after all, it is part of it/it0 type..
how can make it work?
Edit:
I'll go with @ForEveR suggestion and pass the container+iterator/index as arguments instead.
thanks!
An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.
Explanation: Iterators are STL components used to point a memory address of a container. They are used to iterate over container classes.
Use an iterator vector<int>::iterator iter; An iterator is used as a pointer to iterate through a sequence such as a string or vector . The pointer can then be incremented to access the next element in the sequence.
Vector's iterators are random access iterators which means they look and feel like plain pointers. You can access the nth element by adding n to the iterator returned from the container's begin() method, or you can use operator [] . std::vector<int> vec(10); std::vector<int>::iterator it = vec.
Your functions cannot work, since compiler cannot deduce T
and N
from iterator, that you send to function.
You can use std::enable_if
.
template <class Iterator>
typename std::enable_if<std::is_same<Iterator, typename std::array<typename std::iterator_traits<Iterator>::value_type, 1>::iterator>::value, void>::type
catchIterator(Iterator it) {
//do somthing
}
template <class Iterator>
typename std::enable_if<std::is_same<Iterator, typename std::vector<typename std::iterator_traits<Iterator>::value_type>::iterator>::value, void>::type
catchIterator(Iterator it) {
//do somthing
}
But there is actually a problem if vector::iterator
and array::iterator
are of the same type (on gcc for example) - code will not compile, since compiler will not know which function it should use.
The best way is to just pass container as first argument and iterator as second.
template <typename T, size_t N>
void catchIterator(const std::array<T, N> &, typename std::array<T, N>::iterator it) {
//do somthing
}
template <typename T>
void catchIterator(const std::vector<T> &, typename std::vector<T>::iterator) {
//do somthing
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With