是否可以将 Boost 序列化用作仅标头库?

alf*_*lfC 5 c++ boost boost-serialization header-only

下面是使用很棒的Boost.Serialization库的最小示例。

要编译该库,我需要链接到boost_serialization预编译的库。

$ c++ -std=c++11 example.cpp -o example.x -lboost_serialization
                                          ^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

该库经过大量模板化,尽管内部很复杂,但实际代码(函数体)非常简单。只有少数参考文献需要链接,即:

boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::text_oarchive_impl(std::ostream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_oarchive>::~text_oarchive_impl()
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::~text_iarchive_impl()
...
boost::archive::archive_exception::~archive_exception()'
Run Code Online (Sandbox Code Playgroud)

是否有可能在不链接为仅标头库的情况下使用该库?

例如一些未记录的技巧或黑客行为?

这将使其在某些超级计算机集群和环境中使用起来更加简单,而在这些环境中,编译 Boost 并不是那么简单。

#include<sstream>
#include<numeric>
#include<boost/archive/text_oarchive.hpp> // needs linking 
#include<boost/archive/text_iarchive.hpp>
#include<boost/serialization/vector.hpp>

int main(){

    std::vector<double> v(10); std::iota(v.begin(), v.end(), 0);
    std::stringstream ss;
    {
        boost::archive::text_oarchive toa(ss);
        toa << v;
    }
    std::vector<double> v2;
    boost::archive::text_iarchive tia(ss);
    tia >> v2;
    assert(v == v2);
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果库提供仅标头的选项,就像 Boost.Asio 那样(/sf/answers/2851060761/。)


EDIT2:Boost.Serialization 的作者和维护者拒绝了仅将其设为标头的想法。https://github.com/boostorg/serialization/issues/71

alf*_*lfC 0

我最终包含了来自某个版本的 Boost Serialization 的 cpp 源代码。我通过反复试验选择了 cpp 文件。

https://gitlab.com/correaa/boost-mpi3/-/tree/master/include/mpi3/serialization_hack

序列化_hack

基本上,我在包含序列化 hpp 文件的同一位置包含这些 cpp 文件。

#include <boost/archive/detail/common_iarchive.hpp>
#include <boost/archive/detail/common_oarchive.hpp>

#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
//#include <boost/archive/detail/abi_prefix.hpp> // must be the last header

#include <boost/serialization/array.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/string.hpp>

#include <boost/mpl/placeholders.hpp>

#include <any>
#include <optional>

// use this to avoid need for linking -lserialization
#ifdef _MAKE_BOOST_SERIALIZATION_HEADER_ONLY
//#include <boost/archive/detail/decl.hpp>
#if BOOST_VERSION > 106000 && BOOST_VERSION < 106600
#include "../mpi3/serialization_hack/singleton.cpp"
#endif
#if BOOST_VERSION < 105900
#define BOOST_ARCHIVE_DECL
#define BOOST_SERIALIZATION_DECL
#endif
// NOLINTBEGIN(hicpp-use-auto,modernize-use-auto)  external code
#include "../mpi3/serialization_hack/archive_exception.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_archive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iarchive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iserializer.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oarchive.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oserializer.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info.cpp"  // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info_typeid.cpp"  // NOLINT(bugprone-suspicious-include) hack
// NOLINTEND(hicpp-use-auto,modernize-use-auto)

Run Code Online (Sandbox Code Playgroud)

这种方法的一个问题是,我必须修改源代码以适应不同版本的 Boost.Serialization,并且还必须进行一些修改以安抚编译器警告和静态分析器。