我正在尝试创建自己的迷你向量类,并尝试复制其中的一些函数,但在将begin()
和end()
等调用作为参数传递时,我无法使它们以相同的方式运行-编译器无法推导出正确的版本。这里有一个例子:
template<typename T>
class Iterator
{
public:
Iterator() {}
};
template<typename T>
class ConstIterator
{
public:
ConstIterator() {}
};
template <typename T>
class MyList {
public:
MyList() {}
Iterator<T> Begin()
{
return Iterator<T>();
}
ConstIterator<T> Begin() const
{
return Iterator<T>();
}
void Insert(ConstIterator<T> it)
{
}
};
int main() {
MyList<int> myList;
myList.Insert(myList.Begin());
}
在myList.Insert(myList.Begin());
中,它不会尝试使用Begin()
的正确版本,即const版本。
从std::vector实现中可以看出,begin((有两个版本——一个返回iterator
,另一个返回const_iterator
。它们之间唯一的区别是一个是const方法(返回const_iterator的方法(。
_NODISCARD _CONSTEXPR20 iterator begin() noexcept {
auto& _My_data = _Mypair._Myval2;
return iterator(_My_data._Myfirst, _STD addressof(_My_data));
}
_NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept {
auto& _My_data = _Mypair._Myval2;
return const_iterator(_My_data._Myfirst, _STD addressof(_My_data));
}
许多方法,如std::vector::insert,都采用const_iterator参数:
_CONSTEXPR20 iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where
return emplace(_Where, _Val);
}
_CONSTEXPR20 iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where
return emplace(_Where, _STD move(_Val));
}
但是,insert方法中没有任何内容会使编译器使用begin((的const版本。这意味着它必须仅通过返回类型进行推导,但据我所知,这是不可能的?那么它是如何实现的呢?
没有扣除。如果myList
不是const
限定的,则为myList.Begin()
调用Begin()
的非const
版本。否则调用const
版本。如何使用myList.Begin()
的结果并不相关。
标准库通过提供从非常数迭代器到常量迭代器的转换来避免您的问题。例如,您可以为ConstIterator
提供一个接受Iterator
的构造函数,无论如何都必须具有该构造函数才能使Begin()
的const
版本中的return Iterator<T>();
语句正常工作(假设这不是打字错误(。