c++ - 在 std::find 中使用来自不同命名空间的运算符
问题描述
我有以下自动生成的代码:
#include <vector>
#include <algorithm>
namespace foo{
struct S{};
namespace inner{
bool operator==(const S&,const S&){return true;}
}
}
namespace bar{
void func();
}
S
我现在想使用 STL 的find
算法在容器中搜索对象:
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
但是我收到此错误:
/opt/compiler-explorer/gcc-8.3.0/include/c++/8.3.0/bits/predefined_ops.h:241:17:
error: no match for 'operator==' (operand types are 'foo::S' and 'const foo::S')
{ return *__it == _M_value; }
即使添加后,using foo::inner::operator==;
我也会收到相同的错误:
void bar::func(){
using foo::inner::operator==;
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
但是,当我这样做时,它会起作用:
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find_if(v.begin(),v.end(),[s](foo::S e){
using foo::inner::operator==;
return s==e;
});
}
我的两个问题是:
- 为什么第一个示例给出错误?(添加后
using
) - 如何修复?(不改变生成的代码)
编辑:
感谢 Max 的回答(https://stackoverflow.com/a/55517500/8900666),我找到了解决此问题的方法(有点难看但有效):
// Generated code
#include <vector>
#include <algorithm>
namespace foo{
struct S{};
namespace inner{
bool operator==(const S&,const S&){return true;}
}
}
namespace bar{
void func();
}
// My code
namespace foo{
using inner::operator==;
}
void bar::func(){
std::vector<foo::S> v;
foo::S s;
std::find(v.begin(),v.end(),s);
}
解决方案
问题是参数相关查找(ADL)。
在std::find
模板中的某处,有一个if (*it == value)
、 wherevalue
和it
是依赖类型。这意味着编译器将等到模板被实例化后才寻找正确operator==
的使用方法。
但它查找的地方operator==
或多或少限于(无需深入了解不合格名称查找的细节):
所有封闭的名称空间 - 但在此处搜索会在找到任何
operator==
. (与您无关,但可能会绊倒那些只是将例如std
对象的运算符添加到全局名称空间中的人,例如“支持”operator+
forstd::vector
)。执行 ADL - 搜索对象的名称空间(从哪里
*it
和从哪里来*value
)以查找匹配的operator==
.
但是operator==
无法以这种方式找到您要使用的 - 它位于不同的(更深的)命名空间中。这基本上是生成的代码中的一个错误 -运算符应该始终位于与定义它们操作的对象相同的命名空间中。
所以答案是:
operator==
找不到您的,因为它位于错误的命名空间中。这里没有问题,因为在 lambda 中找到了正确的运算符,并且
std::find_if
直接使用 lambda(根本没有查找)。
推荐阅读
- javascript - 如果可用,我可以从微距相机创建流吗?
- javascript - 如何使用反应查询在按钮单击时调用相关 API?
- java - Java EventEmitter客户端重新连接不起作用
- php - 在 Woocommerce 中显示和设置含税和不含税的价格
- node-red - 在不同的 JSON 对象中合并超过 3 个 csv 文件 node-red
- javascript - 如何使 JavaScript 中添加的元素像 HTML 中添加的元素一样响应 onclick?
- java - 返回 MaterialTimePicker
- docker - 构建图像返回 SSL 连接无法建立,请参阅内部异常
- reactjs - 在生产模式下,反应头盔异步不起作用,反应头盔异步如何工作?
- cairo - 如何通过 Image Magick 在 Cairo Graphics 中包含图像?