代码之家  ›  专栏  ›  技术社区  ›  AwaitedOne

将boost::dynamic\u位集序列化为键值对

  •  2
  • AwaitedOne  · 技术社区  · 7 年前

    boost::bimap 包含 boost::dynamic_bitset 这样我就可以保存它,并在需要时重新加载。我已经试过这么做了,但是我犯了很多错误。我随身携带的代码如下。

    // 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;
    }
    

    我怎么做?。

    编辑1:

    在中显示comiler和linker设置 Eclispse (因为我在@sehe提供的答案代码中遇到了一些错误)。

    enter image description here

    enter image description here

    enter image description here

    编辑2

    linux终端上使用的命令 g++ -std=c++14 -Os -Wall -pedantic -pthread main.cpp -lboost_serialization && ./a.out

    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
    

    编辑3 使用 g++ -std=c++14 -Os -Wall -pedantic -pthread main.cpp -lboost_serialization && ldd a.out 我得到以下信息

    /tmp/ccBH8KfT.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/ccBH8KfT.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/ccBH8KfT.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/ccBH8KfT.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/ccBH8KfT.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/ccBH8KfT.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&)'
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   sehe    7 年前
    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;
      

      我认为从存储中加载新的数据结构算作“重新分配”。迭代器或对另一个数据结构的引用在这里显然没有意义。

    4. Erm。现在真的很困惑。

      //  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 的值)

    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 对于二进制存档来说没有意义(其中的节点没有名称)

    真正的问题

    我想,真正的问题可能是“如何序列化 Bitset s“。我很高兴地通知您,我在2015年编写了所需的bits: 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 ... 
    

    没问题。

    后脚本

    真的,省省你自己的麻烦吧。因为你的用法清楚地表明你不想 无序 语义,只需按顺序排列即可:

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

    推荐文章