ここでは、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;
signed char aSChar=-101;
unsigned char aUChar= 102;
wchar_t aWchar =1000;
char16_t aChar16=1001;
char32_t aChar32=1002;
bool aBool =true;
short aShort =-2000;
unsigned short aUShort= 2000;
int aInt =-3000;
unsigned int aUInt= 3000U;
long aLong =-4000L;
unsigned long aULong= 4000UL;
long long aLongLong =-5000LL;
unsigned long long aULongLong= 5000ULL;
float aFloat =1.23456F;
double aDouble =1.23456789012345;
long double aLongDouble=1.23456789012345678L;
std::string aString=u8"UTF-8";
std::wstring aWstring=L"UTF-16/32";
std::u16string aU16string=u"UTF-16";
std::u32string aU32string=U"UTF-32";
aString=u8"\"-\\-/-\x08-\x0C-\n-\r-\t-\\\\\\";
aString=u8"<-\"-&&&-\'-\"->\n\r\t ";
NormalEnum aNormalEnum=eneOne;
ScopedEnum aScopedEnum=ScopedEnum::TWO;
ClassBasicTest aClassBasicTest(10000, "10000", eneTwo);
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,
);
saveTestArray<std::u32string, 8>
(
iSerializer,
);
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";
tType aArray1[N];
for (std::size_t i=0; i < N; ++i)
{
aArray1[i]=iFunc(i);
}
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);
}
}
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);
}
}
}
}
回復処理(source/reference_and_test/basic/test_basic_process.cpp)
template<class tSerializer>
void loadBasicProcess(tSerializer& iSerializer)
{
char aChar =0;
signed char aSChar=0;
unsigned char aUChar=0;
wchar_t aWchar =0;
char16_t aChar16=0;
char32_t aChar32=0;
bool aBool=false;
short aShort=0;
unsigned short aUShort=0;
int aInt=0;
unsigned int aUInt=0;
long aLong=0;
unsigned long aULong=0;
long long aLongLong=0;
unsigned long long aULongLong=0;
float aFloat;
double aDouble;
long double aLongDouble;
std::string aString;
std::wstring aWstring;
std::u16string aU16string;
std::u32string aU32string;
aString=u8"";
aString=u8"";
NormalEnum aNormalEnum=eneZero;
ScopedEnum aScopedEnum=ScopedEnum::ZERO;
ClassBasicTest aClassBasicTest;
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,
);
loadTestArray<std::u32string, 8>
(
iSerializer,
);
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";
tType aArray1[N]={};
for (std::size_t i=0; i < N; ++i)
{
tType aTemp=iFunc(i);
}
tType aArray2[2][N]={};
for (std::size_t j=0; j < 2; ++j)
{
for (std::size_t i=0; i < N; ++i)
{
tType aTemp=iFunc(i+j);
}
}
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)
{
tType aTemp=iFunc(i+j+k);
}
}
}
}