boost.serialization - 免费版本和基类实现

发布于 2024-09-19 00:24:49 字数 1026 浏览 5 评论 0原文

我有一个“生成器”类,它基本上构造了它的子类。要使用这个东西,我只需将其子类化并传递正确的参数来构建我想要构建的对象。我想序列化这些东西,但没有充分的理由为每个子类执行此操作,因为所有数据都在基础中。这是我的例子:

#include <boost/serialization/serialization.hpp>
template < typename T >
struct test_base
{
  // works...
  //template < typename Archive >
  //void serialize(Archive &, unsigned int const)
 // {
  //}
};

template < typename T >
void f(test_base<T> const&) {}

struct test_derived : test_base<int>
{
};

namespace boost { namespace serialization {

template < typename Archive, typename T >
void serialize(Archive &, test_base<T> &, unsigned int const)
{
}

}}

#include <boost/archive/binary_oarchive.hpp>
#include <sstream>
int main()
{
  int x = 5;
  test_derived d;
  //boost::serialization::serialize(x, d, 54); // <- works.

  std::ostringstream str;
  boost::archive::binary_oarchive out(str);
  out & d; // no worky.
}

如果可能的话,我希望免费版本能够工作。是吗?

上面的版本引发了有关序列化不是 test_driven 的成员的错误。

I have a "generator" class that basically constructs its subclass. To use this thing I simply subclass it and pass it the correct parameters to build the object I want built. I want to serialize these things and there's no good reason to do it for each subclass since all the data is in the base. Here's what I've got as example:

#include <boost/serialization/serialization.hpp>
template < typename T >
struct test_base
{
  // works...
  //template < typename Archive >
  //void serialize(Archive &, unsigned int const)
 // {
  //}
};

template < typename T >
void f(test_base<T> const&) {}

struct test_derived : test_base<int>
{
};

namespace boost { namespace serialization {

template < typename Archive, typename T >
void serialize(Archive &, test_base<T> &, unsigned int const)
{
}

}}

#include <boost/archive/binary_oarchive.hpp>
#include <sstream>
int main()
{
  int x = 5;
  test_derived d;
  //boost::serialization::serialize(x, d, 54); // <- works.

  std::ostringstream str;
  boost::archive::binary_oarchive out(str);
  out & d; // no worky.
}

I want the free version to work if possible. Is it?

Version above pukes up error about serialize not being a member of test_derived.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘紸啶 2024-09-26 00:24:49

澄清问题发生的原因:
boost::serialization 必须有实现序列化功能的方法。作为类方法或(在您的情况下)在 boost::serialization 命名空间中定义函数的非侵入式方式。
因此编译器必须以某种方式决定选择哪个实现。因此,boost 有一个 boost::serialization::serialize 模板函数的“默认”实现。
签名:

template<class Archive, class T>
inline void serialize(Archive & ar, T & t, const BOOST_PFTO unsigned int file_version)

在该函数中调用了 T::serialize(...)。因此,当您不想要直观版本时,您必须使用比默认函数模板更明确的内容来覆盖 boost::serialization::serialize 函数。
现在的问题是:
在您的情况下,编译器必须决定是否
a) 选择参数必须隐式转换的版本(test_衍生& 到 test_base&)
b) 使用泛型函数而不进行强制转换(T 是 test_driven&)
您希望编译器使用变体 a) 但编译器更喜欢 b)

解决方案:
我不知道一个真正好的解决方案。我想我会使用一个宏来生成具有显式类型的 serialize(...) 的实现。
如果这对您来说不是一个可能的解决方案,您还可以更明确地告诉编译器要调用什么:

out & *((test_base<int>*)&d);

并将其包装在一些辅助函数中(因为没有人愿意整天看这样的代码)

我希望这是一个清晰的描述并且有帮助

如果我的解释不清楚,这里有一个例子:

#include <iostream>
class Base
{
public:
    virtual ~Base()
    {
    }
};

class Derived : public Base
{
public:
    virtual ~Derived()
    {
    }
};


void foo(Base& bar)
{
    std::cout << "special" << std::endl;
}

template<typename T>
void foo(T& bar)
{
    std::cout << "generic" << std::endl;
}

int main()
{
    Derived derived;
    foo(derived);         // => call to generic implementation
    foo(*((Base*) &bla)); // => call to special 
    return 0;
}

Clarification why the problem happens:
boost::serialization has to ways of implementing the serialize function. As class method or (in your case) the non-intrusive way of defining a function in the boost::serialization namespace.
So the compiler has to somehow decide which implementation to choose. For that reason boost has a 'default' implementation of the boost::serialization::serialize template function.
Signature:

template<class Archive, class T>
inline void serialize(Archive & ar, T & t, const BOOST_PFTO unsigned int file_version)

Within that function there is a call to T::serialize(...). So when you don't want the intusive version you have to override the boost::serialization::serialize function with something more explicit than the default function-template.
Now the problem:
In your case the compiler has to decide if it
a) chooses the version where a parameter has to be casted implicit (test_derived& to test_base&)
b) use the generic function without casting (T is test_derived&)
You want the compiler to use variant a) but the compiler prefers b)

Solution:
I don't know a really good solution. I think i would go with a macro which generates implementations of serialize(...) with the explicit type.
If that isn't a possible solution for you, you could also tell the compiler more explicit what to call:

out & *((test_base<int>*)&d);

and wrap it in some helper function (because no one wants to look at such code all the day)

I hope that is a clear description and helps

In case my explanation was not clear, here is an example:

#include <iostream>
class Base
{
public:
    virtual ~Base()
    {
    }
};

class Derived : public Base
{
public:
    virtual ~Derived()
    {
    }
};


void foo(Base& bar)
{
    std::cout << "special" << std::endl;
}

template<typename T>
void foo(T& bar)
{
    std::cout << "generic" << std::endl;
}

int main()
{
    Derived derived;
    foo(derived);         // => call to generic implementation
    foo(*((Base*) &bla)); // => call to special 
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文