boost 相关问题

Boost是一系列旨在用于C ++的高质量库。 Boost是免费的,通常被认为是“第二标准库”。

有人知道为什么我在 macOS 上构建 boost 但没有创建 boost:: Fiber 库吗?

我正在编写一些使用 boost:: Fiber 作为协程的代码。该代码在 Windows 上运行良好,但是当我将其(通过 git)克隆到 macOS 时,我发现 cmake 找不到 boost:: Fiber。 在两个窗口上...

回答 2 投票 0

如何使用boost::wave来展开嵌套宏

我正在开发一个Boost Wave应用程序,将“C”源文件中未扩展的宏实例映射到相应的扩展宏文本。 映射需要适用于函数和对象...

回答 1 投票 0

是否保证boost::asio中async_*的处理程序总是被调用?

我在另一个线程中调用 boost::asio::serial_port::async_write_some() 和 asio::io_service::run() 。有一个回调给“async_write_some”。我可以放心地假设,这个回调将是

回答 3 投票 0

尝试通过取消当前的async_read并继续下一个读/写操作来实现空闲超时

我正在使用计时器和 async_read,因此每当计时器用完时,它就会通过执行 ws_.next_layer().cancel() 取消 async_read,以便我可以继续下一个操作。但当我抓住

回答 1 投票 0

无法安装autodock vina(可能是由于boost)

作为我正在编写的脚本的一部分,我需要安装 autodock vina 软件包以实现配体和蛋白质结合。每次我尝试“pip install vina”时,都会收到错误

回答 1 投票 0

Boost Beast Websocket 在连接时多次验证客户端证书

我有一个基于 Boost Beast asio 的 websocket 服务器,它(以缩写形式)像这样启动 ssl_context_.set_options( boost::asio::ssl::context::default_workarounds | 升压::asio::ssl::c...

回答 1 投票 0

C++ 相当于 Rust 的 Result<T, E> 类型?

我喜欢在我的 C++ 代码中使用 std::experimental::Optional,但问题是 value_or 要求默认值与可选值的类型相同。 当我...

回答 6 投票 0

通过自制程序安装时如何使用boost?

这可能是一个非常基本的问题,但这是我第一次遇到这样的问题。我使用的是 M1 macOS Big Sur。我正在尝试为我的程序运行 boost 库。我已经在我的设备上安装了 boost...

回答 2 投票 0

HippoMocks:嘲笑 boost::chrono::steady_clock::now

我有一些代码: boost::system::error_code 时钟错误; const boost::chrono::steady_clock::time_point START = boost::chrono::steady_clock::now(clock_error); 我想模拟 now() 函数...

回答 1 投票 0

HippoMocks:嘲笑 boost::chtono::steady_clock::now

我有一些代码: boost::system::error_code 时钟错误; const boost::chrono::steady_clock::time_point START = boost::chrono::steady_clock::now(clock_error); 我想模拟 now() 函数...

回答 1 投票 0

boost::mysql 销毁连接对象时出错

我正在使用 c++ 的 boost 包中的 Boost.MySQL 库。我在使用本地 io_context 和 ssl_contexts 创建和销毁数据库连接时遇到错误。 请参阅

回答 1 投票 0

使用 boost::multi_index 时嵌套名称说明符中使用的 C++ 不完整类型

我有以下文件: “声明.hpp” 命名空间 ns { 派生类; 使用 DerivedPtr = std::unique_ptr; } “基地.hpp” 命名空间 ns { 用户类; ...

回答 1 投票 0

如何匹配具有可选组且不包含特定组的字符串?

如何用正则表达式匹配以下情况: XYZABC ABC 但不是这些: XYZ*ABC *ABC 为了捕获 ABC 部分(各不相同)? 我已经尝试过以下方法,但它不起作用。 (?:XYZ)?(?!\*)...

回答 1 投票 0

如何减少boost::interprocess::map中创建和插入的时间?

在下面的代码中,我将 msgpack 文件解压到 std::map。这个过程的持续时间几乎是85秒。 #包括 #包括 #包括 #包括 在下面的代码中,我将 msgpack 文件解压到 std::map。这个过程持续时间差不多85秒。 #include <map> #include <vector> #include <string> #include <iostream> #include <exception> #include <msgpack.hpp> #include <boost/variant.hpp> #include <boost/filesystem.hpp> using namespace std::literals; namespace fs = boost::filesystem; enum class TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_, }; class MOVar; typedef boost::variant<std::nullptr_t, int64_t, double, std::string, std::vector<MOVar>, std::map<std::string, MOVar>> MOVarST; class MOVar : public MOVarST { public: MOVar() : MOVarST(nullptr) {} MOVar(double b) { MOVarST::operator=(b); } MOVar(int64_t b) { MOVarST::operator=(b); } MOVar(int b) : MOVar(static_cast<int64_t>(b)) {} MOVar(std::string &&b) { MOVarST::operator=(b); } MOVar(std::vector<MOVar> &b) { MOVarST::operator=(b); } MOVar(std::map<std::string, MOVar> &b) { MOVarST::operator=(b); } const MOVar &operator=(const int64_t &b) { MOVarST::operator=(b); return *this; } const MOVar &operator=(std::string &&b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(std::string &b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(const double &b) { MOVarST::operator=(b); return *this; } const MOVar &operator=(std::vector<MOVar> &&b) { MOVarST::operator=(std::move(b)); return *this; } const MOVar &operator=(std::map<std::string, MOVar> &&b) { MOVarST::operator=(std::move(b)); return *this; } bool is_map() const { return which() == (int)TYPE_MSG::MAP_; } bool is_int64() const { return which() == (int)TYPE_MSG::INT64_; } bool is_nill() const { return which() == (int)TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == (int)TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == (int)TYPE_MSG::STRING_; } bool is_vector() const { return which() == (int)TYPE_MSG::VECTOR_; } const double &_as_double() const { return boost::get<double>(*this); } const int64_t &_as_int64() const { return boost::get<int64_t>(*this); } const std::string &_as_string() const { return boost::get<std::string>(*this); } const std::vector<MOVar> &_as_vector() const { return boost::get<std::vector<MOVar>>(*this); } const std::map<std::string, MOVar> &_as_map() const { return boost::get<std::map<std::string, MOVar>>(*this); } private: }; void convert_msgpack_to_movar(msgpack::object const &o, MOVar &v); namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<MOVar> { msgpack::object const &operator()(msgpack::object const &o, MOVar &v) const { convert_msgpack_to_movar(o, v); return o; } }; } } } int main() { std::map<std::string, MOVar> map; auto fileName = "big_map.msgpack"s; auto startTime = std::chrono::high_resolution_clock::now(); { std::ifstream file(fileName, std::ios::binary); auto fileSize = fs::file_size(fileName); std::vector<char> buffer(fileSize); file.read(buffer.data(), fileSize); msgpack::object_handle oh = msgpack::unpack(buffer.data(), fileSize); msgpack::object deserialized = oh.get(); deserialized.convert(map); } auto endTime = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime); std::cout << "Duration: " << duration.count() << " seconds" << std::endl; } 但是当我尝试用 std::map 替换 boost::interprocess::map 时,时间几乎增加了 12 倍。 我有什么错吗?是否有必要替换我使用 boost 共享内存的方法? (我在第二个过程中检查了两张地图及其结果,两者的结果都是相同的。) #include <fstream> #include <iostream> #include <exception> #include <msgpack.hpp> #include <boost/variant.hpp> #include <boost/filesystem.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/string.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> using namespace std::literals; namespace fs = boost::filesystem; namespace bip = boost::interprocess; enum class TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_, }; auto sharedMemoryName = "MySharedMemory"s; unsigned long long shmSize = 9.8 * 1024 * 1024 * 1024ull; bip::managed_shared_memory segment(bip::open_or_create, sharedMemoryName.data(), shmSize); template <typename T> using Alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; const Alloc<void> allocator(segment.get_segment_manager()); //MOVar class is like last example void Convertor(MAP &map, std::map<std::string, MOVar>::const_iterator &pair); class MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, Alloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, Alloc<PAIR>>; using Vec = bip::vector<MOVarBip, Alloc<MOVarBip>>; typedef boost::variant<std::nullptr_t, int64_t, double, STR, Vec, MAP> MOVarSTBIP; class MOVarBip : public MOVarSTBIP { public: MOVarBip() : MOVarSTBIP(nullptr) {} MOVarBip(int64_t &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(double &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(STR &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(Vec &b) { MOVarSTBIP::operator=(std::move(b)); } MOVarBip(MAP &b) { MOVarSTBIP::operator=(std::move(b)); } const MOVarBip& operator=(int64_t&& b) { MOVarSTBIP::operator=(std::move(b)); return *this; } const MOVarBip& operator=(double&& b) { MOVarSTBIP::operator=(std::move(b)); return *this; } const MOVarBip& operator=(std::string&& b) { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = b.data(); MOVarSTBIP::operator=(std::move(tmpValue)); return *this; } const MOVarBip& operator=(std::vector<MOVar>&& value) { auto &vecBip = *segment.construct<Vec>(bip::anonymous_instance)(allocator); for (auto &item : value) { switch (item.which()) { case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto element = item._as_map().begin(); auto mapEnd = item._as_map().end(); for (; element != mapEnd; ++element) { Convertor(mapBip, element); } MOVarBip valueBip = mapBip; vecBip.push_back(std::move(valueBip)); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = item._as_string().data(); MOVarBip valueBip = tmpValue; vecBip.push_back(std::move(valueBip)); break; } default: { throw std::logic_error("The code doesn't support this scenario for Vec type!"); } } } MOVarSTBIP::operator=(std::move(vecBip)); return *this; } const MOVarBip& operator=(std::map<std::string, MOVar>&& value) { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto itr = value.cbegin(); auto endPoint = value.cend(); for (; itr != endPoint; ++itr) { Convertor(mapBip, itr); } MOVarSTBIP::operator=(std::move(mapBip)); return *this; } bool is_map() const { return which() == (int)TYPE_MSG::MAP_; } bool is_int64() const { return which() == (int)TYPE_MSG::INT64_; } bool is_nill() const { return which() == (int)TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == (int)TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == (int)TYPE_MSG::STRING_; } bool is_vector() const { return which() == (int)TYPE_MSG::VECTOR_; } const double &_as_double() const { return boost::get<double>(*this); } const int64_t &_as_int64() const { return boost::get<int64_t>(*this); } const STR &_as_string() const { return boost::get<STR>(*this); } const Vec &_as_vector() const { return boost::get<Vec>(*this); } const MAP &_as_map() const { return boost::get<MAP>(*this); } private: }; void Convertor(MAP &map, std::map<std::string, MOVar>::const_iterator &pair) { auto &keyBip = *segment.construct<STR>(bip::anonymous_instance)(allocator); keyBip = pair->first.data(); auto &value = pair->second; switch (value.which()) { case static_cast<int>(TYPE_MSG::NULLPTR_): { auto &valueBip = *segment.construct<MOVarBip>(bip::anonymous_instance)(); map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::INT64_): { auto &tmpValue = *segment.construct<int64_t>(bip::anonymous_instance)(); tmpValue = value._as_int64(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::DOUBLE_): { auto &tmpValue = *segment.construct<double>(bip::anonymous_instance)(); tmpValue = value._as_double(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = value._as_string().data(); MOVarBip valueBip = tmpValue; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::VECTOR_): { auto &vecBip = *segment.construct<Vec>(bip::anonymous_instance)(allocator); for (auto &item : value._as_vector()) { switch (item.which()) { case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto element = item._as_map().begin(); auto mapEnd = item._as_map().end(); for (; element != mapEnd; ++element) { Convertor(mapBip, element); } MOVarBip valueBip = mapBip; vecBip.push_back(std::move(valueBip)); break; } case static_cast<int>(TYPE_MSG::STRING_): { auto &tmpValue = *segment.construct<STR>(bip::anonymous_instance)(allocator); tmpValue = item._as_string().data(); MOVarBip valueBip = tmpValue; vecBip.push_back(std::move(valueBip)); break; } default: { throw std::logic_error("The code doesn't support this scenario for Vec type!"); } } } MOVarBip valueBip = vecBip; map.insert({std::move(keyBip), std::move(valueBip)}); break; } case static_cast<int>(TYPE_MSG::MAP_): { auto &mapBip = *segment.construct<MAP>(bip::anonymous_instance)(allocator); auto itr = value._as_map().begin(); auto endPoint = value._as_map().end(); for (; itr != endPoint; ++itr) { Convertor(mapBip, itr); } MOVarBip valueBip = mapBip; map.insert({std::move(keyBip), std::move(valueBip)}); break; } default: { throw std::logic_error("The code doesn't support this scenario!"); break; } } } namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const &operator()(msgpack::object const &o, STR &v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const &operator()(msgpack::object const &o, MOVarBip &v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = (int64_t)(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: { uint64_t temp = o.as<uint64_t>(); if (temp > (uint64_t)0x7FFFFFFFFFFFFFFF) { v = std::to_string(temp); } else { v = ((int64_t)temp); } break; } case msgpack::type::NEGATIVE_INTEGER: v = (o.as<int64_t>()); break; case msgpack::type::FLOAT32: v = ((double)o.as<float>()); break; case msgpack::type::FLOAT64: v = (o.as<double>()); break; case msgpack::type::STR: v = o.as<std::string>(); break; case msgpack::type::BIN: v = o.as<std::string>(); break; case msgpack::type::ARRAY: v = o.as<std::vector<MOVar>>(); break; case msgpack::type::MAP: v = o.as<std::map<std::string, MOVar>>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const &operator()(msgpack::object const &o, MAP &v) const { if (o.type != msgpack::type::MAP) { throw msgpack::type_error(); } msgpack::object_kv *p(o.via.map.ptr); msgpack::object_kv *const pend(o.via.map.ptr + o.via.map.size); auto &tmp = *segment.construct<MAP>(bip::anonymous_instance)(allocator); for (; p != pend; ++p) { auto &key = *segment.construct<STR>(bip::anonymous_instance)(allocator); p->key.convert(key); p->val.convert(tmp[std::move(key)]); } v = std::move(tmp); return o; } }; } } } int main() { auto fileName = "big_map.msgpack"s; startTime = std::chrono::high_resolution_clock::now(); { std::ifstream file(fileName, std::ios::binary); auto fileSize = fs::file_size(fileName); std::vector<char> buffer(fileSize); file.read(buffer.data(), fileSize); auto &bip_map = *segment.construct<MAP>("bip_map")(allocator); msgpack::object_handle oh = msgpack::unpack(buffer.data(), fileSize); msgpack::object deserialized = oh.get(); deserialized.convert(bip_map); } endTime = std::chrono::high_resolution_clock::now(); duration = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime); std::cout << "Duration: " << duration.count() << " seconds" << std::endl; boost::interprocess::shared_memory_object::remove(sharedMemoryName.data()); } 这是代码的输出: 持续时间:72秒(std::map) 持续时间:956秒(boost::interprocess::map) 您通过手动构造匿名实例来否定分配器。这不仅会导致泄漏(您的代码中有大量泄漏),而且效率也较低。 从 MOVar 到 MOVarBip 的所有手动编码转换都可以由单个函数处理,从而避免许多临时操作: template <typename T> void BipConvert(T const& v, MOVarBip& result) { struct Vis { MOVarBip& result; void operator()(MOVar const& v) const { boost::apply_visitor(*this, v); } void operator()(std::nullptr_t) const { result = {}; } void operator()(int64_t v) const { result = v; } void operator()(std::string const& v) const { result = STR(v.c_str(), segment.get_segment_manager()); } void operator()(std::map<std::string, MOVar> const& v) const { result = MAP(segment.get_segment_manager()); for (auto& map = boost::get<MAP>(result); auto& [k, v] : v) BipConvert(v, map.emplace(k).first->second); } void operator()(std::vector<MOVar> const& v) const { result = Vec(segment.get_segment_manager()); for (auto& vec = boost::get<Vec>(result); auto& item : v) BipConvert(item, vec.emplace_back()); } }; Vis{result}(v); } 此外,从可变左值引用中随机移动并不是导致未定义行为错误的秘诀,例如: MOVarBip(STR &b) { MOVarSTBIP::operator=(std::move(b)); } 解决这个问题的最简单方法是按值获取,无论参数的值类别如何,它都会做正确的事情。无论如何,如果您打算支持不同的段,那么除非分配器相等,否则您不应该移动。 简化 反转上述观察,我发现您确实希望有一个引用全局段的全局静态分配器。比如: template <typename T> using BaseAlloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; template <typename T> struct SegmentAlloc : BaseAlloc<T> { SegmentAlloc(bip::managed_shared_memory::segment_manager* mgr = segment->get_segment_manager()) : BaseAlloc<T>(mgr) {} using BaseAlloc<T>::BaseAlloc; template <typename U> struct rebind { using other = SegmentAlloc<U>; }; }; 现在您可以定义变量类型: struct MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, SegmentAlloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using VEC = bip::vector<MOVarBip, SegmentAlloc<MOVarBip>>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, SegmentAlloc<PAIR>>; static void json_dump(MAP const& data, std::string filename); using MOVarSTBIP = boost::variant<std::nullptr_t, int64_t, double, STR, VEC, MAP>; struct MOVarBip : MOVarSTBIP { using Base = MOVarSTBIP; template <typename... Args> explicit MOVarBip(Args&&... args) : Base(std::forward<Args>(args)...) {} using Base::operator=; explicit MOVarBip(std::string_view s) : Base(STR(s.data(), s.size())) {} explicit MOVarBip(std::string s) : Base(STR(s.data(), s.size())) {} bool is_map() const { return which() == TYPE_MSG::MAP_; } bool is_int64() const { return which() == TYPE_MSG::INT64_; } bool is_nill() const { return which() == TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == TYPE_MSG::STRING_; } bool is_vector() const { return which() == TYPE_MSG::VECTOR_; } double const& _as_double() const { return boost::get<double>(*this); } int64_t const& _as_int64() const { return boost::get<int64_t>(*this); } STR const& _as_string() const { return boost::get<STR>(*this); } VEC const& _as_vector() const { return boost::get<VEC>(*this); } MAP const& _as_map() const { return boost::get<MAP>(*this); } double & _as_double() { return boost::get<double>(*this); } int64_t & _as_int64() { return boost::get<int64_t>(*this); } STR & _as_string() { return boost::get<STR>(*this); } VEC & _as_vector() { return boost::get<VEC>(*this); } MAP & _as_map() { return boost::get<MAP>(*this); } }; 无论如何,我总是更喜欢非侵入性的 msgpack 适配,而这里正是它的全部荣耀: namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const& operator()(msgpack::object const& o, STR& v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const& operator()(msgpack::object const& o, MOVarBip& v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = static_cast<int64_t>(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: if (uint64_t temp = o.as<uint64_t>(); temp > 0x7FFFFFFFFFFFFFFF) v = MOVarBip(std::to_string(temp)); else v = static_cast<int64_t>(temp); break; case msgpack::type::NEGATIVE_INTEGER: v = o.as<int64_t>(); break; case msgpack::type::FLOAT32: case msgpack::type::FLOAT64: v = o.as<double>(); break; case msgpack::type::STR: case msgpack::type::BIN: v = o.as<STR>(); break; case msgpack::type::ARRAY: v = o.as<VEC>(); break; case msgpack::type::MAP: v = o.as<MAP>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const& operator()(msgpack::object const& o, MAP& m) const { if (o.type != msgpack::type::MAP) throw msgpack::type_error(); m.clear(); for (auto p = o.via.map.ptr, pend = p + o.via.map.size; p != pend; ++p) { auto [it, uniqueOk] = m.emplace(p->key.as<STR>(), MOVarBip{}); assert(uniqueOk); p->val.convert(it->second); } return o; } }; template <> struct convert<VEC> { msgpack::object const& operator()(msgpack::object const& o, VEC& v) const { if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); for (auto p = o.via.array.ptr, pend = p + o.via.array.size; p != pend; ++p) p->convert(v.emplace_back()); return o; } }; } // namespace adaptor } } // namespace msgpack 我认为它可以更加优化,但我希望这是简化的良好开端。 完整演示 实时编译器资源管理器 // #define MSGPACK_USE_BOOST #include <iostream> #include <msgpack.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/string.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/variant.hpp> using namespace std::literals; namespace bip = boost::interprocess; enum /*class*/ TYPE_MSG : int { NULLPTR_, INT64_, DOUBLE_, STRING_, VECTOR_, MAP_ }; static auto sharedMemoryName = "MySharedMemory"s; static auto shmSize = 9.8 * 1024 * 1024 * 1024ull; static auto segment = std::make_unique<bip::managed_shared_memory>(// bip::open_or_create, sharedMemoryName.data(), shmSize); template <typename T> using BaseAlloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>; template <typename T> struct SegmentAlloc : BaseAlloc<T> { SegmentAlloc(bip::managed_shared_memory::segment_manager* mgr = segment->get_segment_manager()) : BaseAlloc<T>(mgr) {} using BaseAlloc<T>::BaseAlloc; template <typename U> struct rebind { using other = SegmentAlloc<U>; }; }; struct MOVarBip; using STR = bip::basic_string<char, std::char_traits<char>, SegmentAlloc<char>>; using PAIR = std::pair<const STR, MOVarBip>; using VEC = bip::vector<MOVarBip, SegmentAlloc<MOVarBip>>; using MAP = bip::map<STR, MOVarBip, std::less<STR>, SegmentAlloc<PAIR>>; static void json_dump(MAP const& data, std::string filename); using MOVarSTBIP = boost::variant<std::nullptr_t, int64_t, double, STR, VEC, MAP>; struct MOVarBip : MOVarSTBIP { using Base = MOVarSTBIP; template <typename... Args> explicit MOVarBip(Args&&... args) : Base(std::forward<Args>(args)...) {} using Base::operator=; explicit MOVarBip(std::string_view s) : Base(STR(s.data(), s.size())) {} explicit MOVarBip(std::string s) : Base(STR(s.data(), s.size())) {} bool is_map() const { return which() == TYPE_MSG::MAP_; } bool is_int64() const { return which() == TYPE_MSG::INT64_; } bool is_nill() const { return which() == TYPE_MSG::NULLPTR_; } bool is_double() const { return which() == TYPE_MSG::DOUBLE_; } bool is_string() const { return which() == TYPE_MSG::STRING_; } bool is_vector() const { return which() == TYPE_MSG::VECTOR_; } double const& _as_double() const { return boost::get<double>(*this); } int64_t const& _as_int64() const { return boost::get<int64_t>(*this); } STR const& _as_string() const { return boost::get<STR>(*this); } VEC const& _as_vector() const { return boost::get<VEC>(*this); } MAP const& _as_map() const { return boost::get<MAP>(*this); } double & _as_double() { return boost::get<double>(*this); } int64_t & _as_int64() { return boost::get<int64_t>(*this); } STR & _as_string() { return boost::get<STR>(*this); } VEC & _as_vector() { return boost::get<VEC>(*this); } MAP & _as_map() { return boost::get<MAP>(*this); } }; namespace msgpack { MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) { namespace adaptor { template <> struct convert<STR> { msgpack::object const& operator()(msgpack::object const& o, STR& v) const { switch (o.type) { case msgpack::type::BIN: v.assign(o.via.bin.ptr, o.via.bin.size); break; case msgpack::type::STR: v.assign(o.via.str.ptr, o.via.str.size); break; default: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MOVarBip> { msgpack::object const& operator()(msgpack::object const& o, MOVarBip& v) const { switch (o.type) { case msgpack::type::NIL: v = MOVarBip(); break; case msgpack::type::BOOLEAN: v = static_cast<int64_t>(o.as<bool>()); break; case msgpack::type::POSITIVE_INTEGER: if (uint64_t temp = o.as<uint64_t>(); temp > 0x7FFFFFFFFFFFFFFF) v = MOVarBip(std::to_string(temp)); else v = static_cast<int64_t>(temp); break; case msgpack::type::NEGATIVE_INTEGER: v = o.as<int64_t>(); break; case msgpack::type::FLOAT32: case msgpack::type::FLOAT64: v = o.as<double>(); break; case msgpack::type::STR: case msgpack::type::BIN: v = o.as<STR>(); break; case msgpack::type::ARRAY: v = o.as<VEC>(); break; case msgpack::type::MAP: v = o.as<MAP>(); break; case msgpack::type::EXT: throw msgpack::type_error(); break; } return o; } }; template <> struct convert<MAP> { msgpack::object const& operator()(msgpack::object const& o, MAP& m) const { if (o.type != msgpack::type::MAP) throw msgpack::type_error(); m.clear(); for (auto p = o.via.map.ptr, pend = p + o.via.map.size; p != pend; ++p) { auto [it, uniqueOk] = m.emplace(p->key.as<STR>(), MOVarBip{}); assert(uniqueOk); p->val.convert(it->second); } return o; } }; template <> struct convert<VEC> { msgpack::object const& operator()(msgpack::object const& o, VEC& v) const { if (o.type != msgpack::type::ARRAY) throw msgpack::type_error(); for (auto p = o.via.array.ptr, pend = p + o.via.array.size; p != pend; ++p) p->convert(v.emplace_back()); return o; } }; } // namespace adaptor } } // namespace msgpack #include <chrono> #include <fstream> static constexpr auto now = std::chrono::high_resolution_clock::now; static void timed_load(std::string filename, MAP& into) { auto startTime = now(); std::ifstream file(filename, std::ios::binary); std::vector<char> const buffer(std::istreambuf_iterator<char>(file), {}); msgpack::object_handle oh = msgpack::unpack(buffer.data(), buffer.size()); msgpack::object const& deserialized = oh.get(); deserialized.convert(into); std::cout << "Duration: " << (now() - startTime) / 1ms << "ms" << std::endl; } int main() { { auto& bip_map = *segment->find_or_construct<MAP>("bip_map")(); timed_load("big_map.msgpack", bip_map); json_dump(bip_map, "big_map.json"); } segment.reset(); // close before remove bip::shared_memory_object::remove(sharedMemoryName.c_str()); } #include <boost/json.hpp> void json_dump(MAP const& data, std::string filename) { struct Vis { using value = boost::json::value; value operator()(MOVarBip const& var) const { return boost::apply_visitor(*this, var); } value operator()(std::nullptr_t) const { return nullptr; } value operator()(int64_t i) const { return i; } value operator()(double d) const { return d; } value operator()(STR const& s) const { return s.c_str(); } value operator()(VEC const& v) const { boost::json::array arr; for (auto& el : v) arr.push_back((*this)(el)); return arr; } value operator()(MAP const& m) const { boost::json::object obj; for (auto& [k, v] : m) obj[k.c_str()] = (*this)(v); return obj; } }; std::ofstream(filename) << Vis{}(data); } 我已经确认在 ASAN/UBSAN 下它是干净的并且无泄漏。正如您所看到的,我抛出一个 json 转储只是为了验证数据是否可访问且有效。 在我的机器上: 总结 我想这可能是进一步优化的良好基础,例如与您已经找到的 reserve() 一起。

回答 1 投票 0

仅使用 crc 库构建 Boost

我只想使用 crc 库构建 boost,在我的情况下如何构建?我在 Ubuntu 24 上遇到错误 sudo apt-get install build-essential g++ autotools-dev libicu-dev libbz2-dev libboost-all-dev git 克隆 ...

回答 1 投票 0

boost::voronoi 的高精度坐标问题

在尝试 voronoi_advanced_tutorial.cpp 更高精度坐标时,我注意到我的输出图之一出现了数学错误(显然)。该图没有显示这样的

回答 1 投票 0

仅使用 crc 库构建 Boost

我只想使用 crc 库构建 boost,在我的情况下如何构建?我在 Ubuntu 24 上遇到错误 sudo apt-get install build-essential g++ autotools-dev libicu-dev libbz2-dev libboost-all-dev git 克隆...

回答 1 投票 0

_MSC_VER 值与多个 Visual Studio 安装

我有一个使用Boost库的C++项目,该项目是使用Boost_vc142_rev.1.79在MS Visual Studio 2019上构建的。 现在我转移到 Visual Studio 2022,因此我切换到 boost_vc143_rev.1.85。 和 e...

回答 1 投票 0

Boost 普通日志 - 自定义严重性名称

我正在使用具有默认严重性级别的 boost trivial 日志,并且我想为这些默认严重性级别映射自定义文本(例如,使用 warn 而不是警告)。 在我的格式化程序中我使用 <...

回答 1 投票 0

boost::process::async_pipe 或用于进程间通信的管道

我需要使用命名管道进行进程间消息传递。 我知道 async_pipe 可用于命名管道。 但是当我尝试使用 async_pipe 时,我的程序在读取时卡在 io_context::run() 中 为什么是...

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.