RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 780186
Accepted
Arhadthedev
Arhadthedev
Asked:2020-02-05 01:17:21 +0000 UTC2020-02-05 01:17:21 +0000 UTC 2020-02-05 01:17:21 +0000 UTC

为什么 std::find 不使用我的 operator==?

  • 772

我实现了我的重载operator==以将我std::pair<...>的与std::string. 但由于某种原因,编译器找不到这个重载。它可以与什么连接?

重现错误的代码:

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

typedef std::pair<std::string, int> RegPair;

bool operator==(const RegPair& lhs, const std::string& rhs)
{
    return lhs.first == rhs;
}

int main()
{
    std::vector<RegPair> sequence;
    std::string foo("foo");
    std::find(sequence.begin(), sequence.end(), foo);
}

错误文字:

  • GNU GCC:

    错误:在 '__first. __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* with _Iterator = std::pair, std::allocator >, int>*, _Container = std::vector, std::allocator >, int>, std::分配器,std::allocator >, int> > > == __val'

  • 铛:

    错误:二进制表达式的操作数无效('std::pair, int>' 和 'std::basic_string const')


这个问题是对Why is not std::find() using my operator==?的粗略翻译。”。

c++
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-02-05T01:49:11Z2020-02-05T01:49:11Z

    来自进行翻译的链接的答案不正确/不准确。ADL 搜索不会以任何方式替换/排除常规搜索,而只是对其进行补充。

    正确的情况描述如下:

    1. 正常查找是从标准库中==的函数模板定义调用运算符的位置执行的。std::find它只查找从该位置可见的名称。

      很明显,上面的运算符定义==从那里是不可见的。

    2. ADL 查找是在关联的,并且仅在关联的命名空间上执行的,并且在调用std::find代码中调用函数时查看这些命名空间。关联的命名空间集是根据6.4.2/2中描述的规则构建的。

      std::find在这种情况下,上述运算符的定义从调用点==完全可见。但是这个定义是在全局命名空间中进行的。在这种情况下,只有空格与 ADL 相关联std,因为两个比较参数都属于空格std。因此,ADL 不考虑全局命名空间,也找不到此定义。

      据称 ADL 停止进一步搜索定义operator ==正是因为operator ==已经在内部找到了一些定义的说法std是不正确的。ADL 始终仅在关联的命名空间中查找名称。与常规查找不同,ADL 永远不会将搜索范围扩展到关联的命名空间之外,无论那里是否找到了某些东西。

    同样的问题可以通过下面的小例子来说明

    namespace N
    {
      struct S {};
    }
    
    template <typename T> void foo(T a) 
    {
      bar(a);                         // 1
    }
    
    void bar(N::S s) {}
    
    int main()
    {
      N::S a;
      foo(a);                         // 2
    }
    

    使用此声明顺序,正常的名称查找查找从点 1 可见的名称,但 ADL 查找查找从点 2 可见的名称,但仅在关联的命名空间中。全局命名空间没有关联,所以void bar(N::S s)找不到声明,也没有编译代码。

    在最初的版本中,如果我们以某种方式将全局命名空间“拉”为 ADL 的关联命名空间,那么该运算符==将立即开始通过 ADL 定位。例如,让我们在全局命名空间中声明一些可以转换为的虚构类型std::string并将其用作搜索的键

    ...
    
    struct S : std::string
    {
        using std::string::string;
    };
    
    int main()
    {
        std::vector<RegPair> sequence;
        S foo("foo");
        std::find(sequence.begin(), sequence.end(), foo);
    }
    

    比较运算符的定义不需要更改。代码将立即开始编译并使用此比较运算符。

    另一个看似“无辜”的替换选项将使代码编译,是使该对的第二个成员成为全局命名空间中的类型

    struct X {};
    typedef std::pair<std::string, X> RegPair;
    

    无需更改任何其他内容 - 这已经足以关联 ADL 的全局命名空间。

    • 8
  2. Arhadthedev
    2020-02-05T01:17:21Z2020-02-05T01:17:21Z

    问题是它std::find是一个模板函数,因此operator==ADL(参数类型相关搜索)在搜索时发挥作用。

    两个函数参数 (std::pair和std::string) 都在同一个命名空间 ( ::std) 中,因此 ADL 开始在该命名空间中查找。同时,至少在那里定义一些就足够了operator==,因为名称匹配(名称查找)是在定义合适的重载之前执行的。

    由于operator==肯定会找到一个匹配的名称(<string>至少有一个比较运算符std::string与某物在同一文件中声明),因此算法停止工作。您的重载位于全局命名空间(即外部::std)中,不会到达队列。


    这篇文章是对James McNellis回复的粗略翻译。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5