迭代器 - 为vector::iterator和array::iterator重载函数

5
我将尝试重载某个函数,以便仅接受连续容器的迭代器作为有效参数(这些容器包括std::vector::iterator,std::array::iterator和内建数组迭代器==原始指针)。

但是出于某种原因,我的函数在处理vector和std::array时无法编译:

函数如下:

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
}

使用示例:

std::array<int, 10> arr;
auto it = arr.begin();
catchIterator(it);

std::vector<int> vec;
auto it0 = vec.begin();
catchIterator(it0);

错误:

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  

我正在使用Visual Studio 2015 RTM版的VC++。

这些错误已经很明显了,但我想知道编译器是否不能从it和it0中真正推断出T和N,毕竟它是it/it0类型的一部分。

如何使它工作?

编辑:
我会采用@ForEveR的建议,将容器+迭代器/索引作为参数传递。谢谢!

1个回答

5

你的函数无法工作,因为编译器无法从你传递给函数的迭代器中推断出 TN。 你可以使用 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
}

但是实际上存在一个问题,如果vector::iteratorarray::iterator是相同的类型(例如在gcc上),代码将无法编译,因为编译器不知道应该使用哪个函数。

最好的方法是将容器作为第一个参数传递,迭代器作为第二个参数。

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
}

std::vector的重载很好用,而std::array的重载只有在N为1时才能编译通过,有没有办法也将其泛化? - David Haim
只有当您使用手动大小点调用catchIterator时,才需要@DavidHaim。 - ForEveR
@DavidHaim:应该是这样的,std::array<T,1u>::iterator === std::array<T,N>::iterator - Pixelchemist
@DavidHaim:是的...实际上它的类型是std::_Array_iterator<_Ty,N> - Pixelchemist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接