C ++编译器选择了错误的重载函数

问题描述

当我刚开始在学校学习链表和双链表时,我正在尝试实现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 */ }
};

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...