将 boost::hash 与 boost::property_tree 一起使用?
Using boost::hash with boost::property_tree?
我正在尝试为包含 boost::property_tree (boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >
) 的对象生成哈希值。在 boost 头文件中搜索 属性 树,我找不到任何已定义的 hash_value 函数。我想要实现的基本示例:
class MyClass{
public:
friend std::size_t hash_value(const MyClass & obj);
private:
boost::property_tree m_data;
}
inline std::size_t hash_value(const MyClass & obj){
std::size_t seed = 0;
boost::hash_combine(seed,obj.m_data);
return seed;
}
此代码将无法编译:
"no matching function for call to 'hash_value(const boost::property_tree &)'"
我的问题:在我没有找到的某个头文件中是否为 boost::property_tree 定义了 hash_value。如果不是,通过遍历 property_tree 来散列它的 boost 惯用方法是什么?
我应该使用 ptree 序列化转换为 std::string 并对其进行哈希处理,还是手动遍历树并创建递归哈希?
只需将 hash<>
专门用于 ptree:
#include <boost/property_tree/ptree.hpp>
#include <boost/functional/hash.hpp>
namespace boost {
template<typename Key, typename Data, typename KeyCompare>
struct hash<boost::property_tree::basic_ptree<Key, Data, KeyCompare> > {
size_t operator()(boost::property_tree::basic_ptree<Key, Data, KeyCompare> const& pt) const {
std::size_t seed = 0;
boost::hash_combine(seed, pt.template get_value<std::string>());
boost::hash_range(seed, pt.begin(), pt.end());
return seed;
}
};
}
够了!这是一个小的 MyClass
,它从类似 json 的文字中读取:
#include <boost/property_tree/json_parser.hpp>
class MyClass{
public:
MyClass(std::string const& json) {
std::istringstream iss(json);
read_json(iss, m_data);
}
private:
boost::property_tree::ptree m_data;
friend inline std::size_t hash_value(const MyClass& obj){
std::size_t seed = 0;
boost::hash_combine(seed, obj.m_data);
return seed;
}
};
现在可以测试了
#include <iostream>
int main() {
for (std::string const data : {
R"({"a":[1,2,3],"b":{"nest":"hello","more":"world"}})",
R"({"b":{"nest":"hello","more":"world"},"a":[1,2,3]})",
R"({ })",
R"({})",
})
{
MyClass o(data);
std::cout << "object hash: " << hash_value(o) << " " << data << "\n";
}
}
打印:
object hash: 3573231694259656572 {"a":[1,2,3],"b":{"nest":"hello","more":"world"}}
object hash: 11176663460548092204 {"b":{"nest":"hello","more":"world"},"a":[1,2,3]}
object hash: 3864292196 { }
object hash: 3864292196 {}
注意:哈希和相等性
对于许多容器,hash<> 假设有一个 对应的 相等比较器。如果它们不匹配,你会得到 Undefined Behaviour.
您可能想根据 ptree
的有序(关联)接口来定义 hash_range
:
boost::hash_range(seed, pt.ordered_begin(), pt.not_found()); // CAUTION
这样做的好处是 {"a":1,"b":2}
可以匹配 {"b":2,"a":1}
。
不要这样做,除非你知道自己在做什么。具体来说,您需要将兼容的相等比较器传递给每个使用此散列的 container/algorithm。
如果你这样写,并使用像这样的驱动程序进行测试:
int main() {
MyClass a{ R"({"a":[1,2,3],"b":{"nest":"hello","more":"world"}})" },
b{R"({"b":{"nest":"hello","more":"world"},"a":[1,2,3]})" },
c{R"({ })" },
d{R"({})" };
for (auto& lhs : {a,b,c,d})
for (auto& rhs : {a,b,c,d})
{
std::cout << "hash: " << hash_value(lhs) << " " << hash_value(rhs) << " - equality: " << std::boolalpha << (lhs==rhs) << "\n";
if ((hash_value(lhs) == hash_value(rhs)) != (lhs==rhs))
std::cout << " -- MISMATCH\n";
}
}
它将打印:
hash: 10737438301360613971 10737438301360613971 - equality: true
hash: 10737438301360613971 10737438301360613971 - equality: false
-- MISMATCH
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 10737438301360613971 - equality: false
-- MISMATCH
hash: 10737438301360613971 10737438301360613971 - equality: true
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 3864292196 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
MISMATCH 警告表明相等性和散列不一致。
如果您 运行 具有原始哈希(首屏)的测试驱动程序,它将打印:
hash: 3573231694259656572 3573231694259656572 - equality: true
hash: 3573231694259656572 11176663460548092204 - equality: false
hash: 3573231694259656572 3864292196 - equality: false
hash: 3573231694259656572 3864292196 - equality: false
hash: 11176663460548092204 3573231694259656572 - equality: false
hash: 11176663460548092204 11176663460548092204 - equality: true
hash: 11176663460548092204 3864292196 - equality: false
hash: 11176663460548092204 3864292196 - equality: false
hash: 3864292196 3573231694259656572 - equality: false
hash: 3864292196 11176663460548092204 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3573231694259656572 - equality: false
hash: 3864292196 11176663460548092204 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
我正在尝试为包含 boost::property_tree (boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >
) 的对象生成哈希值。在 boost 头文件中搜索 属性 树,我找不到任何已定义的 hash_value 函数。我想要实现的基本示例:
class MyClass{
public:
friend std::size_t hash_value(const MyClass & obj);
private:
boost::property_tree m_data;
}
inline std::size_t hash_value(const MyClass & obj){
std::size_t seed = 0;
boost::hash_combine(seed,obj.m_data);
return seed;
}
此代码将无法编译: "no matching function for call to 'hash_value(const boost::property_tree &)'"
我的问题:在我没有找到的某个头文件中是否为 boost::property_tree 定义了 hash_value。如果不是,通过遍历 property_tree 来散列它的 boost 惯用方法是什么?
我应该使用 ptree 序列化转换为 std::string 并对其进行哈希处理,还是手动遍历树并创建递归哈希?
只需将 hash<>
专门用于 ptree:
#include <boost/property_tree/ptree.hpp>
#include <boost/functional/hash.hpp>
namespace boost {
template<typename Key, typename Data, typename KeyCompare>
struct hash<boost::property_tree::basic_ptree<Key, Data, KeyCompare> > {
size_t operator()(boost::property_tree::basic_ptree<Key, Data, KeyCompare> const& pt) const {
std::size_t seed = 0;
boost::hash_combine(seed, pt.template get_value<std::string>());
boost::hash_range(seed, pt.begin(), pt.end());
return seed;
}
};
}
够了!这是一个小的 MyClass
,它从类似 json 的文字中读取:
#include <boost/property_tree/json_parser.hpp>
class MyClass{
public:
MyClass(std::string const& json) {
std::istringstream iss(json);
read_json(iss, m_data);
}
private:
boost::property_tree::ptree m_data;
friend inline std::size_t hash_value(const MyClass& obj){
std::size_t seed = 0;
boost::hash_combine(seed, obj.m_data);
return seed;
}
};
现在可以测试了
#include <iostream>
int main() {
for (std::string const data : {
R"({"a":[1,2,3],"b":{"nest":"hello","more":"world"}})",
R"({"b":{"nest":"hello","more":"world"},"a":[1,2,3]})",
R"({ })",
R"({})",
})
{
MyClass o(data);
std::cout << "object hash: " << hash_value(o) << " " << data << "\n";
}
}
打印:
object hash: 3573231694259656572 {"a":[1,2,3],"b":{"nest":"hello","more":"world"}}
object hash: 11176663460548092204 {"b":{"nest":"hello","more":"world"},"a":[1,2,3]}
object hash: 3864292196 { }
object hash: 3864292196 {}
注意:哈希和相等性
对于许多容器,hash<> 假设有一个 对应的 相等比较器。如果它们不匹配,你会得到 Undefined Behaviour.
您可能想根据 ptree
的有序(关联)接口来定义 hash_range
:
boost::hash_range(seed, pt.ordered_begin(), pt.not_found()); // CAUTION
这样做的好处是 {"a":1,"b":2}
可以匹配 {"b":2,"a":1}
。
不要这样做,除非你知道自己在做什么。具体来说,您需要将兼容的相等比较器传递给每个使用此散列的 container/algorithm。
如果你这样写,并使用像这样的驱动程序进行测试:
int main() {
MyClass a{ R"({"a":[1,2,3],"b":{"nest":"hello","more":"world"}})" },
b{R"({"b":{"nest":"hello","more":"world"},"a":[1,2,3]})" },
c{R"({ })" },
d{R"({})" };
for (auto& lhs : {a,b,c,d})
for (auto& rhs : {a,b,c,d})
{
std::cout << "hash: " << hash_value(lhs) << " " << hash_value(rhs) << " - equality: " << std::boolalpha << (lhs==rhs) << "\n";
if ((hash_value(lhs) == hash_value(rhs)) != (lhs==rhs))
std::cout << " -- MISMATCH\n";
}
}
它将打印:
hash: 10737438301360613971 10737438301360613971 - equality: true
hash: 10737438301360613971 10737438301360613971 - equality: false
-- MISMATCH
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 10737438301360613971 - equality: false
-- MISMATCH
hash: 10737438301360613971 10737438301360613971 - equality: true
hash: 10737438301360613971 3864292196 - equality: false
hash: 10737438301360613971 3864292196 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 10737438301360613971 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
MISMATCH 警告表明相等性和散列不一致。
如果您 运行 具有原始哈希(首屏)的测试驱动程序,它将打印:
hash: 3573231694259656572 3573231694259656572 - equality: true
hash: 3573231694259656572 11176663460548092204 - equality: false
hash: 3573231694259656572 3864292196 - equality: false
hash: 3573231694259656572 3864292196 - equality: false
hash: 11176663460548092204 3573231694259656572 - equality: false
hash: 11176663460548092204 11176663460548092204 - equality: true
hash: 11176663460548092204 3864292196 - equality: false
hash: 11176663460548092204 3864292196 - equality: false
hash: 3864292196 3573231694259656572 - equality: false
hash: 3864292196 11176663460548092204 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3573231694259656572 - equality: false
hash: 3864292196 11176663460548092204 - equality: false
hash: 3864292196 3864292196 - equality: true
hash: 3864292196 3864292196 - equality: true