在包含自定义类型的集合中查找
Find in a set containing self defined type
我有一个存储自定义数据的集合,我想通过键值搜索它。
这是一个简单的例子:
struct Data {
Data(int x, int y):x(x), y(y){}
int x;
int y;
};
struct Compare {
bool operator() (const Data& lhs, const Data& rhs) {
return lhs.x < rhs.x;
}
};
int main()
{
set<Data, Compare> s;
s.insert(Data(2, 77));
s.insert(Data(3, 15));
s.insert(Data(1, 36));
for (auto i:s)
cout<<i.x<<" "<<i.y<<endl;
auto i = s.find(3); // <-- Not working
auto i = s.find(Node(3, 0));
if (i != s.end())
cout<<"found"<<endl;
else
cout<<"not found"<<endl;
}
此集合仅按 x
排序,但我必须创建一个临时对象以在集合中搜索:s.find(Node(3, 0))
是否可以只按键搜索?即 s.find(3)
?
你为什么不写这样的东西?
Data myFind(const set<Data, Compare>& s, int x) {
auto it = s.find(Node(x, 0));
return *it;
}
您的代码有错误。 std::set
是一个 unique 容器,这意味着它不希望包含两个彼此相等的值。然而,通过给集合一个只使用 x
的比较函数,你已经做到了,所以具有相同 x 分量的两个值将被集合视为相等,无论它们的 y 是否匹配。这将防止您为 x 插入多个值。 (这可能是你想要的......如果是这样,请忽略这部分。)更好的比较会通过查看 y 来打破 x 中的关系(这被称为 "lexicographic" 比较:
struct Compare {
bool operator() (const Data& lhs, const Data& rhs) {
if(lhs.x != rhs.x) return lhs.x < rhs.x;
return lhs.y < rhs.y;
}
};
现在,关于通过与键类型不同的内容进行搜索。由于关联容器搜索函数中的一些新重载,这在 C++14 中成为可能。有关详细信息,请参阅 Raw pointer lookup for sets of unique_ptrs 的第一个答案。基本上,你给你的比较器一个 "is_transparent" 成员来标记它,你让它能够将 Data
s 与你打算搜索的任何类型进行比较。
在c++14中,你可以使用is_transparent
:
Finds an element with key that compares equivalent to the value x.
This overload only participates in overload resolution if the
qualified-id Compare::is_transparent
is valid and denotes a type. It
allows calling this function without constructing an instance of Key
struct Compare {
using is_transparent = std::true_type;
bool operator() (const Data& lhs, const Data& rhs) const {
return lhs.x < rhs.x;
}
bool operator() (const Data& lhs, const int & rhsx) const {
return lhs.x < rhsx;
}
bool operator() (const int & lhsx, const Data& rhs) const {
return lhsx < rhs.x;
}
};
现在您的密码是 valid。
我有一个存储自定义数据的集合,我想通过键值搜索它。
这是一个简单的例子:
struct Data {
Data(int x, int y):x(x), y(y){}
int x;
int y;
};
struct Compare {
bool operator() (const Data& lhs, const Data& rhs) {
return lhs.x < rhs.x;
}
};
int main()
{
set<Data, Compare> s;
s.insert(Data(2, 77));
s.insert(Data(3, 15));
s.insert(Data(1, 36));
for (auto i:s)
cout<<i.x<<" "<<i.y<<endl;
auto i = s.find(3); // <-- Not working
auto i = s.find(Node(3, 0));
if (i != s.end())
cout<<"found"<<endl;
else
cout<<"not found"<<endl;
}
此集合仅按 x
排序,但我必须创建一个临时对象以在集合中搜索:s.find(Node(3, 0))
是否可以只按键搜索?即 s.find(3)
?
你为什么不写这样的东西?
Data myFind(const set<Data, Compare>& s, int x) {
auto it = s.find(Node(x, 0));
return *it;
}
您的代码有错误。 std::set
是一个 unique 容器,这意味着它不希望包含两个彼此相等的值。然而,通过给集合一个只使用 x
的比较函数,你已经做到了,所以具有相同 x 分量的两个值将被集合视为相等,无论它们的 y 是否匹配。这将防止您为 x 插入多个值。 (这可能是你想要的......如果是这样,请忽略这部分。)更好的比较会通过查看 y 来打破 x 中的关系(这被称为 "lexicographic" 比较:
struct Compare {
bool operator() (const Data& lhs, const Data& rhs) {
if(lhs.x != rhs.x) return lhs.x < rhs.x;
return lhs.y < rhs.y;
}
};
现在,关于通过与键类型不同的内容进行搜索。由于关联容器搜索函数中的一些新重载,这在 C++14 中成为可能。有关详细信息,请参阅 Raw pointer lookup for sets of unique_ptrs 的第一个答案。基本上,你给你的比较器一个 "is_transparent" 成员来标记它,你让它能够将 Data
s 与你打算搜索的任何类型进行比较。
在c++14中,你可以使用is_transparent
:
Finds an element with key that compares equivalent to the value x. This overload only participates in overload resolution if the qualified-id
Compare::is_transparent
is valid and denotes a type. It allows calling this function without constructing an instance ofKey
struct Compare {
using is_transparent = std::true_type;
bool operator() (const Data& lhs, const Data& rhs) const {
return lhs.x < rhs.x;
}
bool operator() (const Data& lhs, const int & rhsx) const {
return lhs.x < rhsx;
}
bool operator() (const int & lhsx, const Data& rhs) const {
return lhsx < rhs.x;
}
};
现在您的密码是 valid。