这在回答您的问题和为您的问题提供解决方案之间划出了一条细线,但不直接回答您的问题,但我认为您可能会发现这很有帮助。
有关背景,请查看此问题。作者提到他不喜欢 Boost 的解决方案,我也不是特别喜欢那里提出的解决方案。我正在编写一个快速而肮脏的序列化库(想想 python 的元帅),你可以serialize(object, ostream)
在其中调用一个对象来序列化它。我意识到我希望这个函数调用四件事之一:
- 如果
object
是普通的旧数据,只需写出大小和原始数据
- 如果
object
是我用自己的成员函数 ( object::serialize
) 创建的类,则调用该成员函数
- 如果该类型有模板特化,请使用它。
- 如果以上都不成立,则抛出编译错误;序列化功能使用不当。
当我编码时,我会尽量避免那些“棘手”或一目了然难以理解的东西。我认为这个解决方案解决了同样的问题,而无需使用必须思考数小时才能理解的代码:
#include <type_traits>
#include <iostream>
#include <vector>
#include <string>
// Template specialization for a POD object
template<typename T>
typename std::enable_if< std::is_pod<T>::value, bool>::type
serial(const T &out, std::ostream &os)
{
os.write((const char*) &out, sizeof(T));
return os.good();
}
// Non POD objects must have a member function 'serialize(std::ostream)'
template<typename T>
typename std::enable_if< ! std::is_pod<T>::value, bool>::type
serial(const T &out, std::ostream &os)
{
return out.serial(os);
}
// Additional specializations here for common container objects
template<typename T>
bool serial(const std::vector<T> &out, std::ostream &os)
{
const size_t vec_size = out.size();
if(!serial(vec_size, os))
return false;
for(size_t i =0; i < out.size(); ++i)
{
if(!serial(out[i], os))
return false;
}
return true;
}
class SomeClass
{
int something;
std::vector<double> some_numbers;
...
bool serial(std::ostream &os)
{
return serial(something, os) && serial(some_numbers, os);
}
};
如果您可以将您的需求归结为一组简单的规则,并且可以使用稍微不那么通用的解决方案,我认为这种方法效果很好。