Theolizer  Version.1.1.3
serializer for C++ / Do you want to update your classes easily ?
THEOLIZER_PROCESS()の使用方法

ここでは、THEOLIZER_PROCESS()による保存/回復の網羅的な使用例(自動テスト)について説明します。
クラスは単純なものを使います。クラスの詳細な使い方はクラスのバリエーション で説明します。
ここではポインタ型とオーナー・ポインタ型の説明と自動テストは行いません。これらについてはオブジェクト追跡について で行います。


1.クラスとenum型の定義

source/reference_and_test/basic/test_basic_process.h で、次のようなクラスとenum型を定義しています。

enum型は従来のenum型と、C++11で追加されたscoped enum型の2つをテストします。

enum NormalEnum
{
eneZero,
eneOne,
eneTwo
};
enum class ScopedEnum : long
{
ZERO,
ONE,
TWO
};

クラス型はテストを容易にするため、非侵入型完全自動を用いています。
同様にメンバ変数をpublicにしたいのでstructを用いています。
(幾つか制約事項があります。クラスのバリエーション にて説明します。)
また、自動テストの記述を簡単化するため、下記を定義しています。

  • 初期化用のコンストラクタ
  • 比較演算子(operator==)
  • std::ostreamへのフレンド出力演算子(operator<<)

struct ClassBasicTest
{
int mInt;
std::string mString;
NormalEnum mNormalEnum;
ClassBasicTest() : mInt(0), mString(""), mNormalEnum(eneZero)
{ }
// 以下は自動テスト(配列)用の定義
ClassBasicTest(int iInt, char const* iString, NormalEnum iNormalEnum) :
mInt(iInt),
mString(iString),
mNormalEnum(iNormalEnum)
{ }
bool operator==(ClassBasicTest const& iRhs) const
{
return (mInt==iRhs.mInt) && (mString==iRhs.mString) && (mNormalEnum==iRhs.mNormalEnum);
}
friend std::ostream& operator<<(std::ostream& iOStream, ClassBasicTest const& iRhs)
{
iOStream <<"("<< iRhs.mInt << ", \"" << iRhs.mString << "\", " << iRhs.mNormalEnum<<")";
return iOStream;
}
};


2.網羅的な使用例(自動テスト)の説明

以下のアイテムを保存し、回復して保存した値と同じ値が回復できたことを、全てのシリアライザの全ての書式指定オプションに対して確認しています。(4.テスト・プログラムの構造 参照)

  • C++言語がサポートする基本型全て
    char, signed char, unsigned char, wchar_t, u16char, u32char,
    short, int, long, long long,
    unsigned short, unsigned int, unsigned long, unsigned long long,
    float, double, long double

  • C++11規格にて定義されている文字列型全て
    std::string, std::wstring, std::u16string, std::u32string
    C言語文字列(例:"foo")はchar型変数の配列として保存されます。

    1バイト文字列リテラルは要注意事項があります。
    Visual Studioの1バイト文字列リテラルはShift-JIS等のNarrow文字列です。UTF-8ではありません。
    Theolizerは1バイト文字列はUTF-8として取り扱いますので、u8"foo"のように必ずu8プリフィクスを付けて下さい。

  • enum型
    従来のenum型、scoped enum型

  • クラス型
    ここでは使い方を示すための1種類のみ。細かいテストはクラスのバリエーション にて実施します。

  • 右辺値(リテラルや式)が保存でき、同じ型の変数へ回復できること
    int, long, long long,
    unsigned int, unsigned long, unsigned long long,
    float, double, long double,
    std::string, std::wstring, std::u16string, std::u32string

  • 配列 上記全ての型に対する1次元、2次元、3次元配列についてテストします。 saveTestArray(), loadTestArray()と言う関数テンプレトを使っています。 型と最下位次元の要素数を指定すると、その型の1次元、2次元、3次元配列を生成して保存し、回復後の値をチェックします。 設定する値とチェックする値は、それぞれの関数呼び出し時にラムダ式で与えています。

保存処理(source/reference_and_test/basic/test_basic_process.cpp)

template<class tSerializer>
void saveBasicProcess(tSerializer& iSerializer)
{
// ---<<< 文字型 >>>---
char aChar = 100;
THEOLIZER_PROCESS(iSerializer, aChar);
signed char aSChar=-101;
THEOLIZER_PROCESS(iSerializer, aSChar);
unsigned char aUChar= 102;
THEOLIZER_PROCESS(iSerializer, aUChar);
wchar_t aWchar =1000;
THEOLIZER_PROCESS(iSerializer, aWchar);
char16_t aChar16=1001;
THEOLIZER_PROCESS(iSerializer, aChar16);
char32_t aChar32=1002;
THEOLIZER_PROCESS(iSerializer, aChar32);
// ---<<< 整数型 >>>---
bool aBool =true;
THEOLIZER_PROCESS(iSerializer, aBool);
short aShort =-2000;
THEOLIZER_PROCESS(iSerializer, aShort);
unsigned short aUShort= 2000;
THEOLIZER_PROCESS(iSerializer, aUShort);
int aInt =-3000;
THEOLIZER_PROCESS(iSerializer, aInt);
unsigned int aUInt= 3000U;
THEOLIZER_PROCESS(iSerializer, aUInt);
long aLong =-4000L;
THEOLIZER_PROCESS(iSerializer, aLong);
unsigned long aULong= 4000UL;
THEOLIZER_PROCESS(iSerializer, aULong);
long long aLongLong =-5000LL;
THEOLIZER_PROCESS(iSerializer, aLongLong);
unsigned long long aULongLong= 5000ULL;
THEOLIZER_PROCESS(iSerializer, aULongLong);
// ---<<< 浮動小数点型 >>>---
float aFloat =1.23456F;
THEOLIZER_PROCESS(iSerializer, aFloat);
double aDouble =1.23456789012345;
THEOLIZER_PROCESS(iSerializer, aDouble);
long double aLongDouble=1.23456789012345678L;
THEOLIZER_PROCESS(iSerializer, aLongDouble);
// ---<<< 文字列型 >>>---
std::string aString=u8"UTF-8";
THEOLIZER_PROCESS(iSerializer, aString);
std::wstring aWstring=L"UTF-16/32";
THEOLIZER_PROCESS(iSerializer, aWstring);
std::u16string aU16string=u"UTF-16";
THEOLIZER_PROCESS(iSerializer, aU16string);
std::u32string aU32string=U"UTF-32";
THEOLIZER_PROCESS(iSerializer, aU32string);
// ---<<< enum型 >>>---
NormalEnum aNormalEnum=eneOne;
THEOLIZER_PROCESS(iSerializer, aNormalEnum);
ScopedEnum aScopedEnum=ScopedEnum::TWO;
THEOLIZER_PROCESS(iSerializer, aScopedEnum);
// ---<<< クラス >>>---
ClassBasicTest aClassBasicTest(10000, "10000", eneTwo);
THEOLIZER_PROCESS(iSerializer, aClassBasicTest);
// ---<<< 右辺値保存 >>>---
THEOLIZER_PROCESS(iSerializer, -3100);
THEOLIZER_PROCESS(iSerializer, 3100U);
THEOLIZER_PROCESS(iSerializer, -4100L);
THEOLIZER_PROCESS(iSerializer, 4100UL);
THEOLIZER_PROCESS(iSerializer, -5100LL);
THEOLIZER_PROCESS(iSerializer, 5100ULL);
THEOLIZER_PROCESS(iSerializer, 2.23456F);
THEOLIZER_PROCESS(iSerializer, 2.23456789012345);
THEOLIZER_PROCESS(iSerializer, 2.23456789012345678L);
THEOLIZER_PROCESS(iSerializer, std::string(u8"rvalue:UTF-8"));
THEOLIZER_PROCESS(iSerializer, std::wstring(L"rvalue:UTF-16/32"));
THEOLIZER_PROCESS(iSerializer, std::u16string(u"rvalue:UTF-16"));
THEOLIZER_PROCESS(iSerializer, std::u32string(U"rvalue:UTF-32"));
THEOLIZER_PROCESS(iSerializer, eneTwo);
THEOLIZER_PROCESS(iSerializer, ScopedEnum::ONE);
THEOLIZER_PROCESS(iSerializer, ClassBasicTest(20000, "20000", eneOne));
// ---<<< 配列保存 >>>---
// 文字型
saveTestArray<char, 5>
(
iSerializer,
[](std::size_t i){return static_cast<char>(i);}
);
saveTestArray<signed char, 6>
(
iSerializer,
[](std::size_t i){return static_cast<signed char>(i);}
);
saveTestArray<unsigned char, 7>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned char>(i);}
);
saveTestArray<wchar_t, 8>
(
iSerializer,
[](std::size_t i){return static_cast<wchar_t>(i);}
);
saveTestArray<char16_t, 9>
(
iSerializer,
[](std::size_t i){return static_cast<char16_t>(i);}
);
saveTestArray<char32_t, 10>
(
iSerializer,
[](std::size_t i){return static_cast<char32_t>(i);}
);
// 整数型
saveTestArray<bool, 4>
(
iSerializer,
[](std::size_t){return static_cast<bool>(true);}
);
saveTestArray<short, 5>
(
iSerializer,
[](std::size_t i){return static_cast<short>(i*10);}
);
saveTestArray<unsigned short, 6>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned short>(i*10);}
);
saveTestArray<int, 7>
(
iSerializer,
[](std::size_t i){return static_cast<int>(i*100);}
);
saveTestArray<unsigned int, 8>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned int>(i*100);}
);
saveTestArray<long, 9>
(
iSerializer,
[](std::size_t i){return static_cast<long>(i*1000);}
);
saveTestArray<unsigned long, 10>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned long>(i*1000);}
);
saveTestArray<long long, 11>
(
iSerializer,
[](std::size_t i){return static_cast<long long>(i*10000);}
);
saveTestArray<unsigned long long, 12>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned long long>(i*10000);}
);
// 浮動小数点型
saveTestArray<float, 5>
(
iSerializer,
[](std::size_t i){return static_cast<float>(i+0.1);}
);
saveTestArray<double, 6>
(
iSerializer,
[](std::size_t i){return i+0.2;}
);
saveTestArray<long double, 7>
(
iSerializer,
[](std::size_t i){return static_cast<long double>(i+0.3);}
);
// 文字列型
saveTestArray<std::string, 5>
(
iSerializer,
[](std::size_t i){return std::to_string(i);}
);
saveTestArray<std::wstring, 6>
(
iSerializer,
[](std::size_t i){return std::to_wstring(i);}
);
saveTestArray<std::u16string, 7>
(
iSerializer,
[](std::size_t i){return theolizer::u8string(std::to_string(i)).get_u16string();}
);
saveTestArray<std::u32string, 8>
(
iSerializer,
[](std::size_t i){return theolizer::u8string(std::to_string(i)).get_u32string();}
);
// enum型
saveTestArray<NormalEnum, 5>
(
iSerializer,
[](std::size_t i){return static_cast<NormalEnum>(i % 3);}
);
saveTestArray<ScopedEnum, 6>
(
iSerializer,
[](std::size_t i){return static_cast<ScopedEnum>(i % 3);}
);
// クラス型
saveTestArray<ClassBasicTest, 5>
(
iSerializer,
[](std::size_t i)
{
return ClassBasicTest
(
static_cast<int>(i),
std::to_string(i).c_str(),
static_cast<NormalEnum>(i % 3)
);
}
);
}

多次元配列の保存処理(source/reference_and_test/basic/common.h)

template<typename tType, std::size_t N, class tSerializer, typename tFunc>
void saveTestArray(tSerializer& iSerializer, tFunc iFunc)
{
std::cout << " saveTestArray<"
<< THEOLIZER_INTERNAL_TYPE_NAME(tType) << ", " << N << ">\n";
// 1次元配列
tType aArray1[N];
for (std::size_t i=0; i < N; ++i)
{
aArray1[i]=iFunc(i);
}
THEOLIZER_PROCESS(iSerializer, aArray1);
// 2次元配列
tType aArray2[2][N];
for (std::size_t j=0; j < 2; ++j)
{
for (std::size_t i=0; i < N; ++i)
{
aArray2[j][i]=iFunc(i+j);
}
}
THEOLIZER_PROCESS(iSerializer, aArray2);
// 3次元配列
tType aArray3[3][2][N];
for (std::size_t k=0; k < 3; ++k)
{
for (std::size_t j=0; j < 2; ++j)
{
for (std::size_t i=0; i < N; ++i)
{
aArray3[k][j][i]=iFunc(i+j+k);
}
}
}
THEOLIZER_PROCESS(iSerializer, aArray3);
}

回復処理(source/reference_and_test/basic/test_basic_process.cpp)

template<class tSerializer>
void loadBasicProcess(tSerializer& iSerializer)
{
// ---<<< 文字型 >>>---
char aChar =0;
THEOLIZER_PROCESS(iSerializer, aChar);
THEOLIZER_EQUAL(aChar, 100);
signed char aSChar=0;
THEOLIZER_PROCESS(iSerializer, aSChar);
THEOLIZER_EQUAL(aSChar, -101);
unsigned char aUChar=0;
THEOLIZER_PROCESS(iSerializer, aUChar);
THEOLIZER_EQUAL(aUChar, 102);
wchar_t aWchar =0;
THEOLIZER_PROCESS(iSerializer, aWchar);
THEOLIZER_EQUAL(aWchar, 1000);
char16_t aChar16=0;
THEOLIZER_PROCESS(iSerializer, aChar16);
THEOLIZER_EQUAL(aChar16, 1001);
char32_t aChar32=0;
THEOLIZER_PROCESS(iSerializer, aChar32);
THEOLIZER_EQUAL(aChar32, 1002);
// ---<<< 整数型 >>>---
bool aBool=false;
THEOLIZER_PROCESS(iSerializer, aBool);
THEOLIZER_EQUAL(aBool, true);
short aShort=0;
THEOLIZER_PROCESS(iSerializer, aShort);
THEOLIZER_EQUAL(aShort, -2000);
unsigned short aUShort=0;
THEOLIZER_PROCESS(iSerializer, aUShort);
THEOLIZER_EQUAL(aUShort, 2000);
int aInt=0;
THEOLIZER_PROCESS(iSerializer, aInt);
THEOLIZER_EQUAL(aInt, -3000);
unsigned int aUInt=0;
THEOLIZER_PROCESS(iSerializer, aUInt);
THEOLIZER_EQUAL(aUInt, 3000U);
long aLong=0;
THEOLIZER_PROCESS(iSerializer, aLong);
THEOLIZER_EQUAL(aLong, -4000L);
unsigned long aULong=0;
THEOLIZER_PROCESS(iSerializer, aULong);
THEOLIZER_EQUAL(aULong, 4000UL);
long long aLongLong=0;
THEOLIZER_PROCESS(iSerializer, aLongLong);
THEOLIZER_EQUAL(aLongLong, -5000LL);
unsigned long long aULongLong=0;
THEOLIZER_PROCESS(iSerializer, aULongLong);
THEOLIZER_EQUAL(aULongLong, 5000ULL);
// ---<<< 浮動小数点型 >>>---
float aFloat;
THEOLIZER_PROCESS(iSerializer, aFloat);
THEOLIZER_EQUAL(aFloat, 1.23456F);
double aDouble;
THEOLIZER_PROCESS(iSerializer, aDouble);
THEOLIZER_EQUAL(aDouble, 1.23456789012345);
long double aLongDouble;
THEOLIZER_PROCESS(iSerializer, aLongDouble);
THEOLIZER_EQUAL(aLongDouble, 1.23456789012345678L);
// ---<<< 文字列型 >>>---
std::string aString;
THEOLIZER_PROCESS(iSerializer, aString);
THEOLIZER_EQUAL(aString, u8"UTF-8");
std::wstring aWstring;
THEOLIZER_PROCESS(iSerializer, aWstring);
THEOLIZER_EQUAL(aWstring, L"UTF-16/32");
std::u16string aU16string;
THEOLIZER_PROCESS(iSerializer, aU16string);
THEOLIZER_EQUAL(aU16string, u"UTF-16");
std::u32string aU32string;
THEOLIZER_PROCESS(iSerializer, aU32string);
THEOLIZER_EQUAL(aU32string, U"UTF-32");
// ---<<< enum型 >>>---
NormalEnum aNormalEnum=eneZero;
THEOLIZER_PROCESS(iSerializer, aNormalEnum);
THEOLIZER_EQUAL(aNormalEnum, eneOne);
ScopedEnum aScopedEnum=ScopedEnum::ZERO;
THEOLIZER_PROCESS(iSerializer, aScopedEnum);
THEOLIZER_EQUAL(aScopedEnum, ScopedEnum::TWO);
// ---<<< クラス >>>---
ClassBasicTest aClassBasicTest;
THEOLIZER_PROCESS(iSerializer, aClassBasicTest);
THEOLIZER_EQUAL(aClassBasicTest.mInt, 10000);
THEOLIZER_EQUAL(aClassBasicTest.mString, "10000");
THEOLIZER_EQUAL(aClassBasicTest.mNormalEnum, eneTwo);
// ---<<< 右辺値保存からの回復 >>>---
THEOLIZER_PROCESS(iSerializer, aInt);
THEOLIZER_EQUAL(aInt, -3100);
THEOLIZER_PROCESS(iSerializer, aUInt);
THEOLIZER_EQUAL(aUInt, 3100);
THEOLIZER_PROCESS(iSerializer, aLong);
THEOLIZER_EQUAL(aLong, -4100L);
THEOLIZER_PROCESS(iSerializer, aULong);
THEOLIZER_EQUAL(aULong, 4100UL);
THEOLIZER_PROCESS(iSerializer, aLongLong);
THEOLIZER_EQUAL(aLongLong, -5100LL);
THEOLIZER_PROCESS(iSerializer, aULongLong);
THEOLIZER_EQUAL(aULongLong, 5100ULL);
THEOLIZER_PROCESS(iSerializer, aFloat);
THEOLIZER_EQUAL(aFloat, 2.23456F);
THEOLIZER_PROCESS(iSerializer, aDouble);
THEOLIZER_EQUAL(aDouble, 2.23456789012345);
THEOLIZER_PROCESS(iSerializer, aLongDouble);
THEOLIZER_EQUAL(aLongDouble, 2.23456789012345678L);
THEOLIZER_PROCESS(iSerializer, aString);
THEOLIZER_EQUAL(aString, u8"rvalue:UTF-8");
THEOLIZER_PROCESS(iSerializer, aWstring);
THEOLIZER_EQUAL(aWstring, L"rvalue:UTF-16/32");
THEOLIZER_PROCESS(iSerializer, aU16string);
THEOLIZER_EQUAL(aU16string, u"rvalue:UTF-16");
THEOLIZER_PROCESS(iSerializer, aU32string);
THEOLIZER_EQUAL(aU32string, U"rvalue:UTF-32");
THEOLIZER_PROCESS(iSerializer, aNormalEnum);
THEOLIZER_EQUAL(aNormalEnum, eneTwo);
THEOLIZER_PROCESS(iSerializer, aScopedEnum);
THEOLIZER_EQUAL(aScopedEnum, ScopedEnum::ONE);
THEOLIZER_PROCESS(iSerializer, aClassBasicTest);
THEOLIZER_EQUAL(aClassBasicTest.mInt, 20000);
THEOLIZER_EQUAL(aClassBasicTest.mString, "20000");
THEOLIZER_EQUAL(aClassBasicTest.mNormalEnum, eneOne);
// ---<<< 配列回復 >>>---
// 文字型
loadTestArray<char, 5>
(
iSerializer,
[](std::size_t i){return static_cast<char>(i);}
);
loadTestArray<signed char, 6>
(
iSerializer,
[](std::size_t i){return static_cast<signed char>(i);}
);
loadTestArray<unsigned char, 7>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned char>(i);}
);
loadTestArray<wchar_t, 8>
(
iSerializer,
[](std::size_t i){return static_cast<wchar_t>(i);}
);
loadTestArray<char16_t, 9>
(
iSerializer,
[](std::size_t i){return static_cast<char16_t>(i);}
);
loadTestArray<char32_t, 10>
(
iSerializer,
[](std::size_t i){return static_cast<char32_t>(i);}
);
// 整数型
loadTestArray<bool, 4>
(
iSerializer,
[](std::size_t){return static_cast<bool>(true);}
);
loadTestArray<short, 5>
(
iSerializer,
[](std::size_t i){return static_cast<short>(i*10);}
);
loadTestArray<unsigned short, 6>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned short>(i*10);}
);
loadTestArray<int, 7>
(
iSerializer,
[](std::size_t i){return static_cast<int>(i*100);}
);
loadTestArray<unsigned int, 8>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned int>(i*100);}
);
loadTestArray<long, 9>
(
iSerializer,
[](std::size_t i){return static_cast<long>(i*1000);}
);
loadTestArray<unsigned long, 10>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned long>(i*1000);}
);
loadTestArray<long long, 11>
(
iSerializer,
[](std::size_t i){return static_cast<long long>(i*10000);}
);
loadTestArray<unsigned long long, 12>
(
iSerializer,
[](std::size_t i){return static_cast<unsigned long long>(i*10000);}
);
// 浮動小数点型
loadTestArray<float, 5>
(
iSerializer,
[](std::size_t i){return static_cast<float>(i+0.1);}
);
loadTestArray<double, 6>
(
iSerializer,
[](std::size_t i){return i+0.2;}
);
loadTestArray<long double, 7>
(
iSerializer,
[](std::size_t i){return static_cast<long double>(i+0.3);}
);
// 文字列型
loadTestArray<std::string, 5>
(
iSerializer,
[](std::size_t i){return std::to_string(i);}
);
loadTestArray<std::wstring, 6>
(
iSerializer,
[](std::size_t i){return std::to_wstring(i);}
);
loadTestArray<std::u16string, 7>
(
iSerializer,
[](std::size_t i){return theolizer::u8string(std::to_string(i)).get_u16string();}
);
loadTestArray<std::u32string, 8>
(
iSerializer,
[](std::size_t i){return theolizer::u8string(std::to_string(i)).get_u32string();}
);
// enum型
loadTestArray<NormalEnum, 5>
(
iSerializer,
[](std::size_t i){return static_cast<NormalEnum>(i % 3);}
);
loadTestArray<ScopedEnum, 6>
(
iSerializer,
[](std::size_t i){return static_cast<ScopedEnum>(i % 3);}
);
// クラス型
loadTestArray<ClassBasicTest, 5>
(
iSerializer,
[](std::size_t i)
{
return ClassBasicTest
(
static_cast<int>(i),
std::to_string(i).c_str(),
static_cast<NormalEnum>(i % 3)
);
}
);
}

多次元配列の回復処理(source/reference_and_test/basic/common.h)

template<typename tType, std::size_t N, class tSerializer, typename tFunc>
void loadTestArray(tSerializer& iSerializer, tFunc iFunc)
{
std::cout << " loadTestArray<"
<< THEOLIZER_INTERNAL_TYPE_NAME(tType) << ", " << N << ">\n";
// 1次元配列
tType aArray1[N]={};
THEOLIZER_PROCESS(iSerializer, aArray1);
for (std::size_t i=0; i < N; ++i)
{
tType aTemp=iFunc(i);
THEOLIZER_EQUAL(aArray1[i], aTemp, i);
}
// 2次元配列
tType aArray2[2][N]={};
THEOLIZER_PROCESS(iSerializer, aArray2);
for (std::size_t j=0; j < 2; ++j)
{
for (std::size_t i=0; i < N; ++i)
{
tType aTemp=iFunc(i+j);
THEOLIZER_EQUAL(aArray2[j][i], aTemp, i, j);
}
}
// 3次元配列
tType aArray3[3][2][N]={};
THEOLIZER_PROCESS(iSerializer, aArray3);
for (std::size_t k=0; k < 3; ++k)
{
for (std::size_t j=0; j < 2; ++j)
{
for (std::size_t i=0; i < N; ++i)
{
tType aTemp=iFunc(i+j+k);
THEOLIZER_EQUAL(aArray3[k][j][i], aTemp, i, j, k);
}
}
}
}