これは、質問への回答と問題の解決策の提供との間の微妙な境界線ですが、質問への直接の回答ではありませんが、これは役立つと思います。
背景については、この質問をご覧ください。著者は、Boost のソリューションが気に入らなかったと述べており、そこで提案されたソリューションも特に好きではありませんでした。serialize(object, ostream)
オブジェクトをシリアル化するために呼び出すクイック&ダーティなシリアル化ライブラリ(Pythonのマーシャルを考えてください)を書いていました。私は、この関数呼び出しを次の 4 つのいずれかにする必要があることに気付きました。
- 普通の古いデータの場合
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);
}
};
ニーズを単純な一連のルールにまとめることができ、一般的ではない解決策で対応できる場合、この方法はうまくいくと思います。