C++ 编译器选择了错误的重载函数
C++ Compiler picking the wrong overloaded function
我正在尝试实施 std::list,因为我刚开始在学校学习 linked 和双重 linked 列表。
这里的代码被精简到只有导致的部分。
精简是为了更好的阅读,以便能够分析问题。
这里是 link 的完整代码(仍在进行中):
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 first, 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>::const_iterator
版本时,编译器正在选择 end()
的 List<int>::iterator
版本。
如果我注释掉
// iterator end() noexcept {};
代码运行良好。
我不知道如何解决这个错误。
我认为编译器应该选择正确的函数,但它没有。
为什么会发生这种情况,如何解决?
我搜索过类似的错误,但 none 我发现的错误与我的有关。
在构造函数体内,不考虑对象 const
。因为它不是,这意味着将调用 end
的 non-const 版本。 insert
采用 const_iterator
,但 end
returns 的 non-const 版本采用 iterator
,因此代码无法编译。
最简单的解决方法是调用 cend
而不是 end
,因为 cend
总是会给你一个 const_iterator
.
一个 const
合格的成员函数只有在被调用的对象是 const
或它是该函数的唯一版本时才会被调用。否则将为 non-const 个对象选择 non-const 限定函数。
如果对象不是 const
,则选择非 const
版本的重载。如果不是这种情况,则永远不会选择非const
版本。
iterator
s 需要隐式转换为 const_iterator
s 在容器中指定 standard:
X::iterator ... any iterator category that meets the forward iterator requirements.
convertible to X::const_iterator.
因此,在您的 const_iterator
中添加一个构造函数应该可以在一般情况下解决您的问题:
class const_iterator {
const_iterator(const iterator&) { /* implement this */ }
};
我正在尝试实施 std::list,因为我刚开始在学校学习 linked 和双重 linked 列表。
这里的代码被精简到只有导致的部分。 精简是为了更好的阅读,以便能够分析问题。
这里是 link 的完整代码(仍在进行中): 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 first, 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>::const_iterator
版本时,编译器正在选择 end()
的 List<int>::iterator
版本。
如果我注释掉
// iterator end() noexcept {};
代码运行良好。
我不知道如何解决这个错误。 我认为编译器应该选择正确的函数,但它没有。
为什么会发生这种情况,如何解决?
我搜索过类似的错误,但 none 我发现的错误与我的有关。
在构造函数体内,不考虑对象 const
。因为它不是,这意味着将调用 end
的 non-const 版本。 insert
采用 const_iterator
,但 end
returns 的 non-const 版本采用 iterator
,因此代码无法编译。
最简单的解决方法是调用 cend
而不是 end
,因为 cend
总是会给你一个 const_iterator
.
一个 const
合格的成员函数只有在被调用的对象是 const
或它是该函数的唯一版本时才会被调用。否则将为 non-const 个对象选择 non-const 限定函数。
如果对象不是 const
,则选择非 const
版本的重载。如果不是这种情况,则永远不会选择非const
版本。
iterator
s 需要隐式转换为 const_iterator
s 在容器中指定 standard:
X::iterator ... any iterator category that meets the forward iterator requirements. convertible to X::const_iterator.
因此,在您的 const_iterator
中添加一个构造函数应该可以在一般情况下解决您的问题:
class const_iterator {
const_iterator(const iterator&) { /* implement this */ }
};