Сериализация boost :: bimap с boost :: dynamic_bitset в качестве пары ключ-значение

Я заинтересован в сериализации 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;
}

Как мне это сделать?.

EDIT_1:

Отображение настроек компилятора и компоновщика в Eclispse(потому что я получаю некоторые ошибки с кодом ответа при условии @sehe).

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

EDIT_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&)'

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. Как вы думаете, является ли действительность итератора при сериализации? (Увидеть Правила аннулирования итераторов)

    oa << left_iter;
    

    Я думаю, что загрузка новой структуры данных из хранилища считается «перераспределением». Итераторы или ссылки на другую структуру данных здесь явно бессмысленны.

  4. Эмм. Теперь это действительно сбивает с толку.

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

    Вы называете это «первым правым элементом», но делаете что-то еще: вы найдете итератор, соответствующий first_left ключ (который вполне может быть последним элементом справа. Также обратите внимание, что, поскольку правая сторона двуногой 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 бессмысленно для бинарных архивов (узлы в них не имеют имен)

Настоящий вопрос

Я полагаю, что реальный вопрос мог быть «как мне сериализовать Bitsets? «. Я рад сообщить вам, что я написал необходимые биты в 2015 году: Как сериализовать boost :: dynamic_bitset? и запрос на прием был принят в Boost начиная с версии 1.64.

Таким образом, вы можете расслабиться, потягивать чай и включать:

#include <boost/dynamic_bitset/serialization.hpp>

Все сделано.

Бонус Раздел

Поскольку эта сериализация обеспечивает сериализацию с минимальным количеством копий, почему бы не использовать ее для питания хэш-функции? Механизм сериализации предоставит вам необходимый частный доступ.

Я злоупотребил сериализацией сантехники для hash<> специализации до: Хешируйте произвольное значение точности (boost :: multiprecision :: cpp_int)

Собираем все вместе

Жить на Колиру

#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 ...

Нет проблем.

ПОСТ СКРИПТУМ

Действительно, избавь себя от неприятностей. Поскольку ваше использование явно указывает на то, что вы не хотите неупорядоченный семантика, просто сделай это упорядоченным:

Жить на Колиру

#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 строк, осталось менее половины кода.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]