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 版本。

iterators 需要隐式转换为 const_iterators 在容器中指定 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 */ }
};