问题描述
当我刚开始在学校学习链表和双链表时,我正在尝试实现std :: list的学习过程。
这是将代码精简到仅引起问题的部分。 精简以使阅读更好,以便能够分析问题。
有关完整代码(仍在开发中)的链接是: https://www.onlinegdb.com/edit/rJKzbN9ID
#include <iostream>
using namespace std;
template <typename T>
class List
{
//SFINAE
template <typename Iter>
using required_input_iterator = std::enable_if<std::is_base_of_v<std::input_iterator_tag,typename std::iterator_traits<Iter>::iterator_category >>;
public:
using reference = T&;
using const_reference = const T&;
using size_type = std::size_t;
class const_iterator ;
class iterator : public std::input_iterator_tag
{
};
class const_iterator
{
};
List() = default;
List(std::initializer_list<T> i_list);
// iterators
const_iterator end() const noexcept {};
iterator end() noexcept {};
const_iterator cend() const {};
template<typename InputIterator>//,typename = required_input_iterator<InputIterator>>
iterator insert(const_iterator pos,InputIterator first,InputIterator last);
};
template <typename T>
List<T>::List(std::initializer_list<T> i_list)
{
insert(end(),i_list.begin(),i_list.end());
}
template<typename T>
template<typename InputIterator>
typename List<T>::iterator List<T>::insert(const_iterator pos,InputIterator last)
{
//
}
int main()
{
List<int> ll({12,7,34,5});
}
在构造函数中,函数insert()
被调用,但是编译会引发此错误:
error: no matching function for call to 'List<int>::insert(List<int>::iterator,std::initializer_list<int>::const_iterator,std::initializer_list<int>::const_iterator)'
如错误所示,当存在完美的List<int>::iterator
版本时,编译器将选择end()
的{{1}}版本。
如果我注释掉
List<int>::const_iterator
代码工作正常。
我不知道如何解决此错误。 我认为编译器应该选择正确的函数,但事实并非如此。
为什么会发生这种情况以及如何解决?
解决方法
在构造函数的主体内部,不将该对象视为const
。由于不是,这意味着将调用end
的非常量版本。 insert
使用const_iterator
,但是end
的非常量版本返回iterator
,因此代码不会编译。
最简单的解决方法是调用cend
而不是end
,因为cend
总是会给您const_iterator
。
仅当被调用对象是const
或它是该函数的唯一版本时,才会调用const
合格成员函数。否则,将为非const对象选择非const限定函数。
如果对象不是const
,则选择非const
版本的重载。如果不是这种情况,将永远不会选择非const
版本。
iterator
必须在standard中指定的容器中隐式转换为const_iterator
:
X ::迭代器 ...满足转发迭代器要求的任何迭代器类别。 可转换为X :: const_iterator。
因此,在您的const_iterator
中添加一个构造函数通常可以解决您的问题:
class const_iterator {
const_iterator(const iterator&) { /* implement this */ }
};