当 T 在命名空间中时,std::find 在 std::vector<std::reference_wrapper<T>> 上失败并出现 "no match for ‘operator==’" 错误
std::find fails on a std::vector<std::reference_wrapper<T>> with a "no match for ‘operator==’" error when T is in a namespace
我目前正在从事一个大型代码项目,想借此机会了解和使用名称空间。我定义的所有 类 都位于一个名称空间 Test.
中
我的一个 类,在这里称为事物,有一个唯一的 ID。我需要能够保存 std::vector 对某些事物的引用,所以我使用 std::reference_wrappers。在程序中的某些点,我需要从向量中删除某些 std::reference_wrappers,所以我使用 std::find:
#include <algorithm>
#include <functional>
#include <vector>
namespace Test {
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
}
Test::Thing::Thing(int id) : id(id) { }
const int Test::Thing::ID() const {
return id;
}
inline bool operator==(const Test::Thing& lhs, const Test::Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Test::Thing& lhs, const Test::Thing& rhs) {
return !(lhs == rhs);
}
int main() {
Test::Thing t1(5);
Test::Thing t2(7);
auto ref1 = std::ref(t1);
auto ref2 = std::ref(t2);
std::vector<std::reference_wrapper<Test::Thing>> v;
v.push_back(ref1);
v.push_back(ref2);
auto pos = std::find(v.begin(), v.end(), ref2);
}
当我尝试编译它时,出现错误:
error: no match for ‘operator==’ (operand types are ‘std::reference_wrapper<Test::Thing>’ and ‘const std::reference_wrapper<Test::Thing>’)
但是,如果我删除名称空间,代码会正确编译:
#include <functional>
#include <vector>
#include <algorithm>
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
Thing::Thing(int id) : id(id) { }
const int Thing::ID() const {
return id;
}
inline bool operator==(const Thing& lhs, const Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Thing& lhs, const Thing& rhs) {
return !(lhs == rhs);
}
int main() {
Thing t1(5);
Thing t2(7);
auto ref1 = std::ref(t1);
auto ref2 = std::ref(t2);
std::vector<std::reference_wrapper<Thing>> v;
v.push_back(ref1);
v.push_back(ref2);
auto pos = std::find(v.begin(), v.end(), ref2);
}
正确的解决方案是将运算符移动到 Argument-dependent lookup (ADL) 可以找到它们的命名空间中:
namespace Test {
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
inline bool operator==(const Thing& lhs, const Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Thing& lhs, const Thing& rhs) {
return !(lhs == rhs);
}
}
Test::Thing::Thing(int id) : id(id) { }
const int Test::Thing::ID() const {
return id;
}
标准库已经使用 <<
等运算符进行流插入。
我目前正在从事一个大型代码项目,想借此机会了解和使用名称空间。我定义的所有 类 都位于一个名称空间 Test.
中我的一个 类,在这里称为事物,有一个唯一的 ID。我需要能够保存 std::vector 对某些事物的引用,所以我使用 std::reference_wrappers。在程序中的某些点,我需要从向量中删除某些 std::reference_wrappers,所以我使用 std::find:
#include <algorithm>
#include <functional>
#include <vector>
namespace Test {
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
}
Test::Thing::Thing(int id) : id(id) { }
const int Test::Thing::ID() const {
return id;
}
inline bool operator==(const Test::Thing& lhs, const Test::Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Test::Thing& lhs, const Test::Thing& rhs) {
return !(lhs == rhs);
}
int main() {
Test::Thing t1(5);
Test::Thing t2(7);
auto ref1 = std::ref(t1);
auto ref2 = std::ref(t2);
std::vector<std::reference_wrapper<Test::Thing>> v;
v.push_back(ref1);
v.push_back(ref2);
auto pos = std::find(v.begin(), v.end(), ref2);
}
当我尝试编译它时,出现错误:
error: no match for ‘operator==’ (operand types are ‘std::reference_wrapper<Test::Thing>’ and ‘const std::reference_wrapper<Test::Thing>’)
但是,如果我删除名称空间,代码会正确编译:
#include <functional>
#include <vector>
#include <algorithm>
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
Thing::Thing(int id) : id(id) { }
const int Thing::ID() const {
return id;
}
inline bool operator==(const Thing& lhs, const Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Thing& lhs, const Thing& rhs) {
return !(lhs == rhs);
}
int main() {
Thing t1(5);
Thing t2(7);
auto ref1 = std::ref(t1);
auto ref2 = std::ref(t2);
std::vector<std::reference_wrapper<Thing>> v;
v.push_back(ref1);
v.push_back(ref2);
auto pos = std::find(v.begin(), v.end(), ref2);
}
正确的解决方案是将运算符移动到 Argument-dependent lookup (ADL) 可以找到它们的命名空间中:
namespace Test {
class Thing {
private:
const int id;
public:
Thing(int id);
const int ID() const;
};
inline bool operator==(const Thing& lhs, const Thing& rhs) {
return lhs.ID() == rhs.ID();
}
inline bool operator!=(const Thing& lhs, const Thing& rhs) {
return !(lhs == rhs);
}
}
Test::Thing::Thing(int id) : id(id) { }
const int Test::Thing::ID() const {
return id;
}
标准库已经使用 <<
等运算符进行流插入。