使用boost :: dynamic_bitset作为键值对序列化boost :: bimap

时间:2017-11-28 11:25:48

标签: c++ serialization boost boost-dynamic-bitset boost-bimap

我有兴趣序列化包含boost::bimap的{​​{1}},以便我可以保存并在需要时加载回来。我已经尝试过这样做,但是我遇到了很多错误。我和我的代码如下。

boost::dynamic_bitset

我该怎么做?。

EDIT_1:

// Example program #include <iostream> #include <string> #include <fstream> #include <boost/bimap.hpp> #include <boost/dynamic_bitset.hpp> #include <boost/bimap/unordered_set_of.hpp> #include <boost/bimap/unordered_multiset_of.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp> #include <boost/serialization/vector.hpp> namespace std { template <typename Block, typename Alloc> struct hash<boost::dynamic_bitset<Block, Alloc> > { using bitset_type = boost::dynamic_bitset<Block, Alloc>; using block_type = typename bitset_type::block_type ; size_t operator()(boost::dynamic_bitset<Block, Alloc> const& bs) const { thread_local static std::vector<block_type> block_data; auto blocks = bs.num_blocks(); block_data.assign(blocks, 0); to_block_range(bs, block_data.begin()); return boost::hash<std::vector<block_type>>()(block_data); } }; } namespace { template <typename Block> struct SerializableType { boost::dynamic_bitset<Block> x; private: friend class boost::serialization::access; template <class Archive> void serialize(Archive &ar, const unsigned int) { ar & BOOST_SERIALIZATION_NVP(x); } }; } namespace bimaps = boost::bimaps; typedef boost::dynamic_bitset<> Bitset; typedef boost::bimap< bimaps::unordered_set_of<Bitset, std::hash<Bitset>>, bimaps::unordered_multiset_of<Bitset, std::hash<Bitset> > > bimap_reference; typedef bimap_reference::value_type position; bimap_reference index; int main() { std::string val = "1010110110101010101"; std::string key = "10010"; boost::dynamic_bitset<> bits = boost::dynamic_bitset<> (val); boost::dynamic_bitset<> pos_bits = boost::dynamic_bitset<> (key); index.insert(position(pos_bits, bits)); std::ofstream ofs("binaryfile"); boost::archive::binary_oarchive oa(ofs); oa << BOOST_SERIALIZATION_NVP(index); index::const_iterator iter = index.begin(); // first left elelemt of bimap boost::dynamic_bitset<> first_left = iter->left; const bimap_reference::left_iterator left_iter = index.left.find(first_left); oa << left_iter; // first right element of bimap auto pos = index.left.find(first_left); const bimap_reference::right_iterator right_iter = index.right.find(pos->second); oa << right_iter; std::cout <<"# done" << std::endl; ofs.close(); std::cout <<"# Loading binary file ... " << std::endl; std::ifstream ifs("binaryfile"); // name of loading file boost::archive::binary_iarchive ia(ifs); ia >> index; bimap_reference::left_iterator left_iter; ia >> left_iter; bimap_reference::right_iterator right_iter; ia >> right_iter; std::cout<<"# done" << std::endl; ifs.close(); return 0; } 中显示编译器和链接器设置(因为我在@sehe提供的答案代码中出现了一些错误。)

enter image description here

enter image description here

enter image description here

EDIT_2

在linux终端上使用的命令Eclispse

g++ -std=c++14 -Os -Wall -pedantic -pthread main.cpp -lboost_serialization && ./a.out

编辑3  使用Errors I get with the first answer code when tried in linux terminal and eclipse IDE. /tmp/cc71hTC2.o: In function `boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::vload(boost::archive::class_name_type&)': main.cpp:(.text._ZN5boost7archive6detail15common_iarchiveINS0_15binary_iarchiveEE5vloadERNS0_15class_name_typeE[_ZN5boost7archive6detail15common_iarchiveINS0_15binary_iarchiveEE5vloadERNS0_15class_name_typeE]+0x1): undefined reference to `boost::archive::basic_binary_iarchive<boost::archive::binary_iarchive>::load_override(boost::archive::class_name_type&)' /tmp/cc71hTC2.o: In function `void boost::serialization::throw_exception<boost::archive::archive_exception>(boost::archive::archive_exception const&)': main.cpp:(.text._ZN5boost13serialization15throw_exceptionINS_7archive17archive_exceptionEEEvRKT_[_ZN5boost13serialization15throw_exceptionINS_7archive17archive_exceptionEEEvRKT_]+0x1a): undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)' /tmp/cc71hTC2.o: In function `boost::exception_detail::error_info_injector<boost::archive::archive_exception>::error_info_injector(boost::exception_detail::error_info_injector<boost::archive::archive_exception> const&)': main.cpp:(.text._ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC2ERKS4_[_ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC5ERKS4_]+0x18): undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)' /tmp/cc71hTC2.o: In function `boost::exception_detail::error_info_injector<boost::archive::archive_exception>::error_info_injector(boost::exception_detail::error_info_injector<boost::archive::archive_exception> const&)': main.cpp:(.text._ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC1ERKS4_[_ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC5ERKS4_]+0x19): undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)' /tmp/cc71hTC2.o: In function `boost::exception_detail::error_info_injector<boost::archive::archive_exception>::error_info_injector(boost::archive::archive_exception const&)': main.cpp:(.text._ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC2ERKS3_[_ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC5ERKS3_]+0xe): undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)' /tmp/cc71hTC2.o: In function `boost::exception_detail::error_info_injector<boost::archive::archive_exception>::error_info_injector(boost::archive::archive_exception const&)': main.cpp:(.text._ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC1ERKS3_[_ZN5boost16exception_detail19error_info_injectorINS_7archive17archive_exceptionEEC5ERKS3_]+0x14): undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)' collect2: error: ld returned 1 exit status 我收到以下信息

g++ -std=c++14 -Os -Wall -pedantic -pthread main.cpp -lboost_serialization && ldd a.out

1 个答案:

答案 0 :(得分:2)

  1. 哇。您并不是要使用该哈希函数来实现性能。

    • 您正在复制每个键/值哈希上的所有块(例如,在查找时,插入时)
    • 更好永远不希望使用协同例程,因为线程本地静态会让你的生活变得悲惨

    请参阅下面的奖励部分

  2. 为什么这种笨拙的舞蹈(简化代码):

    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();
    
  3. 您认为序列化时迭代器的有效性是什么? (见Iterator invalidation rules

    oa << left_iter;
    

    我认为从存储中加载新的数据结构计为&#34;重新分配&#34;。迭代器或对另一个数据结构的引用在这里显然毫无意义。

  4. 呃。现在它真的让人困惑。

    //  first right element of bimap
    auto pos = index.left.find(first_left);
    Index::right_iterator right_iter = index.right.find(pos->second);
    

    你称之为&#34;第一个正确的元素&#34;,但是你做了一些事情:你找到了对应于first_left键的迭代器(它可能是右边的最后一个元素。请注意,由于bimap的右侧是multiset_of,因此可能会有多个匹配,您随机使用第一个。

    (旁注:posleft_iter价值的无用重复)

  5. 见3.

    oa << right_iter;
    
  6. 瓦里亚:

    • 确保以二进制文件打开文件

      std::ofstream ofs("binaryfile", std::ios::binary);
      std::ifstream ifs("binaryfile", std::ios::binary);
      
    • 为什么要为具有值语义index_reference的容器命名?

    • 只是不必要地混淆了
    • SerializableType未使用
    • BOOST_SERIALIZATION_NVP对二进制存档没有意义(节点中没有名称)
  7. 真实问题

    我想,真正的问题可能是&#34;如何序列化Bitset?&#34;。我很高兴地通知您,我在2015年写了所需的位:How to serialize boost::dynamic_bitset?并且拉取请求已被Boost starting with version 1.64接受。

    所以,你可以坐下来,啜饮你的茶,包括:

    #include <boost/dynamic_bitset/serialization.hpp>
    

    全部完成

    奖金部分

    由于该序列化实现了最小拷贝序列化,为什么不使用它来为哈希函数提供动力?序列化机制将为您提供所需的私人访问权限。

    我之前滥用hash<>专精的序列化管道:Hash an arbitrary precision value (boost::multiprecision::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;
        }
    }
    

    打印

    # Writing binary file ... 
    # Loading binary file ... 
    

    没问题。

    POST SCRIPTUM

    真的,省去自己的麻烦。由于您的使用清楚地表明您不想要无序语义,因此只需将其命令:

    <强> 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行,不到代码的一半。