2

为什么以下代码使用非常量迭代器为该行编译但对于const 迭代器(使用 Visual Studio 2008)失败?

#include <vector>

using std::vector;

int main(int argc, char* argv[])
{
    vector<int> test;

    test.push_back(1);
    test.push_back(2);

    vector<int>::const_iterator cit = test.end();
    std::distance(test.begin(), cit); // error: template parameter is ambiguous

    vector<int>::iterator it = test.end();
    std::distance(test.begin(), it);

    return 0;
}

注意:在 Visual Studio 2008 中,没有向量成员函数cbegin()来避免歧义,而是一个重载begin()方法:

iterator begin()
    {   // return iterator for beginning of mutable sequence
    return (iterator(_Myfirst, this));
    }

const_iterator begin() const
    {   // return iterator for beginning of nonmutable sequence
    return (const_iterator(_Myfirst, this));
    }
4

4 回答 4

2

该模板distance采用一个参数,distance<T>(T first, T last). 由于test.begin()has typeiteratorcithas type const_iterator,不能推导出模板参数。

你既可以用test.cbegin()得到保证const_iterator,也可以用其他方式说static_cast<std::vector<int> const &>(test).begin()

(这就像您曾经说过max<T>(T x, T y)并试图说一样max(1, 2U)——它不会编译,因为它是模棱两可的。)

于 2012-08-06T08:47:30.220 回答
1

注意:在 Visual Studio 2008 中,没有向量成员函数cbegin()来避免歧义,而是一个重载begin()方法:

我认为编译器总是为非常量对象选择非常量重载,而只为常量对象选择 const 方法。

打电话

std::distance(test.begin(), cit);

看重载集 forbegin和 的类型cit,并确定它是否可以匹配。它首先解决了重载(到非常量版本),因此失败了。

表达您的意图的最简洁的方式也适用于编译器可能是:

vector<int> const &cref = test;
vector<int>::const_iterator cit = cref.end();
std::distance(cref.begin(), cit);
于 2012-08-06T09:32:20.200 回答
0

函数模板std::distance只接受一个模板参数,两个函数参数必须相同。的返回类型test.begin()是简单的iterator,不是 const_iterator,所以函数参数的类型是不同的。编译器推导std::vector<int>::iterator第一个和 std::vector<int>::const_iterator第二个,因此推导失败。模板参数推导不考虑可能的转换,除了最简单的转换。

有很多方法可以解决这个问题,但它们都有明显的缺点。(这可能是委员会添加cbeginand cend函数的原因。)目前,您最好的选择可能是放弃const, 并同时使用iterator两者。

于 2012-08-06T08:53:40.743 回答
0

distance必须具有相同时间的模板参数。在这种情况下,它是_Vector_const_iterator。有两种重载begin:const 和非常量。const-version 产生_Vector_const_iterator,但另一个产生_Vector_iterator_Vector_iterator继承自_Vector_const_iterator

因此, const 和非常量重载begin都能够产生_Vector_const_iterator,并且它们都可以被选为非常量对象,即编译器会感到困惑。

这就是我编译它的方式:

    std::distance(((const vector<int>&)test).begin(), cit);
于 2012-08-06T09:00:31.960 回答