【问题标题】:C++ Compiler picking the wrong overloaded functionC++ 编译器选择了错误的重载函数
【发布时间】:2020-10-06 18:16:56
【问题描述】:

我正在尝试实施 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 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&lt;int&gt;::const_iterator 版本时,编译器会选择List&lt;int&gt;::iterator 版本的end()

如果我注释掉

// iterator end() noexcept {};

代码运行良好。

我不知道如何解决这个错误。 我认为编译器应该选择正确的函数,但它没有。

为什么会发生这种情况以及如何解决?

我已经搜索过类似的错误,但我发现的都与我的错误无关。

【问题讨论】:

    标签: c++ compiler-errors stdlist


    【解决方案1】:

    在构造函数体内,对象不被视为const。因为不是,这意味着将调用end 的非常量版本。 insert 接受 const_iterator 但非 const 版本的 end 返回 iterator,因此代码无法编译。

    最简单的解决方法是调用cend 而不是end,因为cend 总是会给你一个const_iterator


    只有当它被调用的对象是const,或者它是函数的唯一版本时,才会调用const 限定的成员函数。否则将为非常量对象选择非常量限定函数。

    【讨论】:

      【解决方案2】:

      如果对象不是const,则选择非const 版本的重载。如果不是这种情况,就永远不会选择非const 版本。

      iterators 需要在standard 中指定的容器中隐式转换为const_iterators:

      X​::​iterator ... 满足前向迭代器要求的任何迭代器类别。 可转换为 X​::​const_iterator。

      因此,在您的 const_iterator 中添加构造函数应该可以解决一般情况下的问题:

      class const_iterator {
        const_iterator(const iterator&) { /* implement this */ }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多