我已将operator==
定义如下:
template <class State>
bool operator==(const std::shared_ptr<const State> &lhs,
const std::shared_ptr<const State> &rhs) {
return *lhs == *rhs;
}
此运算符未实例化(在gdb
中,我无法在return语句中设置断点 - 该行不存在)。
但是,此行中的std::find
应使用此运算符:
return std::find(v.begin(), v.end(), el) != v.end();
我在v
中检查了上一行中gdb
的类型:
(gdb) whatis v
type = const std::vector<std::shared_ptr<Domains::IncWorst const>> &
(gdb) whatis el
type = const std::shared_ptr<Domains::IncWorst const> &
这与我的模板operator==
匹配,而State
为IncWorst
吗?
我实现了一个玩具示例如下,示例有效,所以我无法理解为什么真正的代码没有。
template<class V, typename T>
bool in(const V &v, const T &el) {
return std::find(v.begin(), v.end(), el) != v.end();
}
struct MyState {
MyState(int xx) : x(xx) {}
bool operator==(const MyState &rhs) const {
return x == rhs.x;
}
int x;
};
template <class State>
bool operator==(const std::shared_ptr<const State> &lhs,
const std::shared_ptr<const State> &rhs) {
return *lhs == *rhs;
}
int main() {
std::vector<std::shared_ptr<const MyState>> v{
std::make_shared<const MyState>(5)};
auto p = std::make_shared<const MyState>(5);
std::cout << in(v, p) << std::endl; // outputs 1
return 0;
}
答案 0 :(得分:3)
您的operator==
模板位于错误的命名空间中。
为了能够被ADL找到,它必须位于std
命名空间(这可能是非法的,每[namespace.std]/1个)或Domains
(每[basic.lookup.argdep]/2} )。
但是,这仍然非常危险,因为如果在声明std::find
模板之前和之后实例化任何执行相等比较的模板(例如但不限于operator==
),那么整个程序将根据[temp.point]/8和[basic.def.odr]/6无效。
如果必须为类型的std::shared_ptr
提供运算符重载模板,则更喜欢在声明每个类之后显式实例化它们,这样模板的可能性就会降低在某个地方实例化该类是不可见的:
struct MyState {
// ...
};
template bool operator==<MyState>(
const std::shared_ptr<MyState const>&,
const std::shared_ptr<MyState const>&);
如果有人在其他地方向前宣布MyState
,这可能仍会有问题,但这可能是你能做到的最好的事情。