【问题标题】:Equality operator (==) unsupported on map iterators for non-copyable maps不可复制地图的地图迭代器不支持等式运算符 (==)
【发布时间】:2014-03-12 04:05:20
【问题描述】:

当我有一个不可复制对象的映射时,为什么我不能使用 == 比较迭代器?我想在迭代器上进行相等测试时,它不需要复制(或移动)实际对象。

#include <iostream>
#include <utility>
#include <map>

using namespace std;

class A {
private:
    int i;
public:
    A(int i) : i(i) {}
    A(A&) = delete;
    A(A&& a) : i(a.i) {}
    ~A() {}
    A& operator=(A&) = delete;

    bool operator==(const A& a) const { return i == a.i; }
};

int main() {
    map<int, A> myMap;

    map<int, A>::iterator it = myMap.find(1);
    cout << (it == myMap.end()) << endl;
}

此示例编译失败,在cout 行出现错误。

g++ 给出这个错误:

/usr/include/c++/4.8.2/bits/stl_pair.h: In instantiation of ‘struct std::pair<const int, A>’:
test2.cpp:24:27:   required from here
/usr/include/c++/4.8.2/bits/stl_pair.h:127:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = A]’ declared to take     const reference, but implicit declaration would take non-const
   constexpr pair(const pair&) = default;

clang++ 给出这个错误:

/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2/bits/stl_pair.h:127:17: error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be non-const
      constexpr pair(const pair&) = default;
                ^
test2.cpp:24:14: note: in instantiation of template class 'std::pair<const int, A>' requested here
        cout << (it == myMap.end()) << endl;

但是,如果使用map&lt;int, int&gt; 而不是map&lt;int, A&gt;,它确实有效。将const map&lt;int, A&gt;map&lt;int, A&gt;::const_iterator 一起使用没有帮助。

我尝试在cppreference 上查找 map::iterator::operator== 的确切签名,(map::iterator 是一个 BidirectionalIterator,它是一个 ForwardIterator,它是一个 InputIterator)但该网站对概念中的确切类型签名。

【问题讨论】:

  • 如果你将它与myMap.end()以外的东西进行比较,会发生这种情况吗?
  • 此外,将复制构造函数和赋值运算符设为私有以使某些内容不可复制,而不是将它们公开为实际上不起作用的公共方法,这要干净得多。
  • @aruisdante:我似乎无法将其与myMap.begin() 进行比较,或者对其执行其他操作(例如it-&gt;first)。我没有将它们公开为“不起作用”的公共方法,而是使用deleted functions
  • 哦,傻c++ 11标签。
  • @Datalore 如果您有兴趣,这就是您收到奇怪错误消息的原因:Comparing two map::iterators: why does it need the copy constructor of std::pair? 答案完全不平凡。

标签: c++ c++11


【解决方案1】:

问题在于您删除的方法使 A 不可复制...

#include <iostream>
#include <utility>
#include <map>

using namespace std;

class A {
private:
    int i;
public:
    A(int i) : i(i) {}
    // A(A&) = delete; should be ...
    A(const A&) = delete;
    A(A&& a) : i(a.i) {}
    ~A() {}
    // A& operator=(A&) = delete; should be ...
    A& operator=(const A&) = delete;

    bool operator==(const A& a) const { return i == a.i; }
};

int main() {
    map<int, A> myMap;

    map<int, A>::iterator it = myMap.find(1);
    cout << (it == myMap.end()) << endl;
}

使用 gcc/g++ 4.6.3 验证了这一点

从复制构造函数和赋值运算符中删除“const”导致我的编译器给出与您收到的相同的错误。

我将不得不查找详细信息/引用,以了解为什么以这种方式声明它们,但是复制构造函数和赋值运算符始终采用 const 引用(因为您的实例被分配的值不应该方法修改)。

【讨论】:

  • 呵呵,很好,我还是不明白为什么删除函数的签名会影响类的其他操作。
  • IIRC,它与编译器默认生成的方法有关。复制构造函数和赋值是其中的两个,如果你的方法签名与编译器期望看到的不匹配,它并不是编译器生成的方法的实际替换。
  • 换句话说,你认为你是delete-ing 的东西实际上并没有被删除。
猜你喜欢
  • 1970-01-01
  • 2016-06-28
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多