-
哇。您的目标并不是使用该哈希函数来提高性能。
- 您正在复制每个键/值哈希上的所有块(例如,在查找时、在插入时)
- you better永远不要使用协同例程,因为线程局部静态会让你的生活变得悲惨
请参阅下面我的奖励部分
-
为什么这个尴尬的舞蹈(简化代码):
auto iter = index.begin();
// first left element of bimap
BS first_left = iter->left;
Index::left_iterator left_iter = index.left.find(first_left);
出什么问题了
auto left_iter = index.left.begin();
-
您认为序列化后迭代器的有效性如何? (看迭代器失效规则)
oa << left_iter;
我认为从存储中加载新的数据结构算作“重新分配”。迭代器或对另一个数据结构的引用在这里显然没有意义。
-
嗯。现在真的是越来越混乱了。
// first right element of bimap
auto pos = index.left.find(first_left);
Index::right_iterator right_iter = index.right.find(pos->second);
您将其称为“第一个右侧元素”,但您执行了其他操作:找到与first_left
键(很可能是右侧的最后一个元素。另请注意,由于 bimap 的右侧是multiset_of
,可能有多个匹配项,您随机使用第一个。
(边注:pos
是无用的重复left_iter
的值)
-
See 3.
oa << right_iter;
-
Varia:
-
确保以二进制方式打开文件
std::ofstream ofs("binaryfile", std::ios::binary);
std::ifstream ifs("binaryfile", std::ios::binary);
为什么用值语义来命名容器index_reference
?这只是不必要的混乱
-
SerializableType
未使用
-
BOOST_SERIALIZATION_NVP
对于二进制档案毫无意义(节点中没有名称)
真正的问题
我想,真正的问题可能是“我如何序列化Bitset
s?”。我很高兴地告诉你,我在 2015 年写了所需的部分:如何序列化 boost::dynamic_bitset?并且拉取请求已被 Boost 接受从 1.64 版本开始.
因此,您可以坐下来,喝茶并包括:
#include <boost/dynamic_bitset/serialization.hpp>
All done.
奖金部分
既然该序列化实现了最小副本序列化,为什么不使用它来支持哈希函数呢?序列化机制将为您提供所需的私有访问。
我滥用序列化管道hash<>
之前的专业:散列任意精度值 (boost::multi precision::cpp_int)
把它们放在一起
Live On Coliru
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/unordered_multiset_of.hpp>
#include <boost/bimap/unordered_set_of.hpp>
#include <boost/dynamic_bitset/serialization.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/stream_buffer.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/functional/hash.hpp>
namespace serial_hashing { // see https://stackoverflow.com/questions/30097385/hash-an-arbitrary-precision-value-boostmultiprecisioncpp-int
namespace io = boost::iostreams;
struct hash_sink {
hash_sink(size_t& seed_ref) : _ptr(&seed_ref) {}
typedef char char_type;
typedef io::sink_tag category;
std::streamsize write(const char* s, std::streamsize n) {
boost::hash_combine(*_ptr, boost::hash_range(s, s+n));
return n;
}
private:
size_t* _ptr;
};
template <typename T> struct hash_impl {
size_t operator()(T const& v) const {
using namespace boost;
size_t seed = 0;
{
iostreams::stream<hash_sink> os(seed);
archive::binary_oarchive oa(os, archive::no_header | archive::no_codecvt);
oa << v;
}
return seed;
}
};
}
namespace std {
template <typename Block, typename Alloc> struct hash<boost::dynamic_bitset<Block, Alloc> >
: serial_hashing::hash_impl<boost::dynamic_bitset<Block, Alloc> >
{};
} // namespace std
namespace bimaps = boost::bimaps;
using Bitset = boost::dynamic_bitset<>;
typedef boost::bimap<
bimaps::unordered_set_of<Bitset, std::hash<Bitset> >,
bimaps::unordered_multiset_of<Bitset, std::hash<Bitset> > > Index;
int main() {
using namespace std::string_literals;
{
std::cout << "# Writing binary file ... " << std::endl;
Index index;
index.insert({Bitset("10010"s), Bitset("1010110110101010101"s)});
std::ofstream ofs("binaryfile", std::ios::binary);
boost::archive::binary_oarchive oa(ofs);
oa << index;
}
{
std::cout << "# Loading binary file ... " << std::endl;
std::ifstream ifs("binaryfile", std::ios::binary); // name of loading file
boost::archive::binary_iarchive ia(ifs);
Index index;
ia >> index;
}
}
Prints
# Writing binary file ...
# Loading binary file ...
没问题。
后脚本
真的,省点麻烦吧。由于您的使用方式明确表明您不想要无序的语义,只需使其有序:
Live On Coliru
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
#include <boost/dynamic_bitset/serialization.hpp>
#include <fstream>
#include <iostream>
namespace bimaps = boost::bimaps;
using Bitset = boost::dynamic_bitset<>;
typedef boost::bimap<bimaps::set_of<Bitset>, bimaps::multiset_of<Bitset>> Index;
int main() {
using namespace std::string_literals;
{
std::cout << "# Writing binary file ... " << std::endl;
Index index;
index.insert({Bitset("10010"s), Bitset("1010110110101010101"s)});
std::ofstream ofs("binaryfile", std::ios::binary);
boost::archive::binary_oarchive oa(ofs);
oa << index;
}
{
std::cout << "# Loading binary file ... " << std::endl;
std::ifstream ifs("binaryfile", std::ios::binary); // name of loading file
boost::archive::binary_iarchive ia(ifs);
Index index;
ia >> index;
}
}
减少到 36 行,只剩下不到一半的代码。