no message

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@35 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
magmaikh 2002-08-15 02:07:50 +00:00
parent 8c599321c7
commit 69936e7e81
27 changed files with 2073 additions and 495 deletions

View file

@ -0,0 +1,31 @@
extern void Test_TypeList();
extern void Test_SmallObj();
extern void Test_Functor();
extern void Test_Singleton();
extern void Test_SmartPtr();
extern void Test_ObjectFactory();
extern void Test_AbstractFactory();
extern void Test_Vistor();
extern void Test_MultiMethods();
extern void Test_Threads();
#include <stdlib.h>
int main()
{
Test_TypeList();
Test_SmartPtr();
Test_Singleton();
Test_Threads();
/*Test_SmallObj();
Test_Functor();
*/
/*Test_ObjectFactory();
Test_AbstractFactory();
Test_Vistor();
Test_MultiMethods();
*/
system("pause");
};

View file

@ -2,8 +2,8 @@
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="LokiRegressionTest"
ProjectGUID="{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}"
Name="AllTest"
ProjectGUID="{59800972-3512-4147-9E8F-F5239C241F77}"
Keyword="Win32Proj">
<Platforms>
<Platform
@ -23,20 +23,18 @@
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
WarningLevel="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/LokiTest.exe"
OutputFile="$(OutDir)/AllTest.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/LokiTest.pdb"
ProgramDatabaseFile="$(OutDir)/AllTest.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
@ -69,8 +67,6 @@
StringPooling="TRUE"
RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE"
ForceConformanceInForLoopScope="TRUE"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
@ -79,7 +75,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/LokiTest.exe"
OutputFile="$(OutDir)/AllTest.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
@ -104,60 +100,34 @@
</Configurations>
<Files>
<Filter
Name="Source Files"
Name="Test"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="..\..\SDK\Engine\Loki\Loki.hpp">
RelativePath="AllTest.cpp">
</File>
<File
RelativePath="LokiTest.cpp">
RelativePath="..\Test_Singleton.cpp">
</File>
<File
RelativePath="LokiTest.h">
RelativePath="..\Test_SmartPtr.cpp">
</File>
<File
RelativePath="LokiTestTypes.h">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath="LokiTest_TypeList.h">
RelativePath="..\Test_Threads.cpp">
</File>
<File
RelativePath="LokiTest_TypeManip.h">
RelativePath="..\Test_TypeList.cpp">
</File>
<File
RelativePath="LokiTest_TypeTraits.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
</Filter>
<Filter
Name="Loki"
Filter="">
<File
RelativePath="..\..\SDK\Loki\NullType.h">
RelativePath="..\..\..\Singleton.cpp">
</File>
<File
RelativePath="..\..\SDK\Loki\VC7\TypeInfo.h">
</File>
<File
RelativePath="..\..\SDK\Loki\VC7\TypeList.h">
</File>
<File
RelativePath="..\..\SDK\Loki\VC7\TypeManip.h">
</File>
<File
RelativePath="..\..\SDK\Loki\VC7\TypeTraits.h">
RelativePath="..\..\..\SmallObj.cpp">
</File>
</Filter>
<File
RelativePath="ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>

View file

@ -1,81 +0,0 @@
// LokiTest.cpp : Defines the entry point for the console application.
//
#include <conio.h>
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
//#define LOKI_USE_REFERENCE
#include <Loki\static_check.h>
#include <Loki\NullType.h>
#include <Loki\TypeInfo.h>
#include <Loki\TypeManip.h>
#include <Loki\TypeList.h>
#include <Loki\TypeTraits.h>
//The test use macros so that you can comment out any test
// that result in compilation errors and continue testing
// the remaining components
//TODO break into seperate files, use boost methods to test
// successful & unsuccessful compilations
#include "LokiTestTypes.h"
#include "LokiTest_TypeManip.h"
#include "LokiTest_TypeList.h"
#include "LokiTest_TypeInfo.h"
#include "LokiTest_TypeTraits.h"
//LOKI_TEST_TYPE2TYPE_HEADER
LOKI_TEST_TYPE2TYPE_HEADER_BROKEN_PATTERN_MATCHING
int main(int argc, char* argv[])
{
argc;
argv;
//Compile-Time Assertions
STATIC_CHECK(true, ThisShouldCompile);
//STATIC_CHECK(false, ThisShouldNotCompile);
LOKI_TEST_NULLTYPE;
//Test TypeManip
LOKI_TEST_INT2TYPE;
//LOKI_TEST_TYPE2TYPE;
LOKI_TEST_TYPE2TYPE_BROKEN_PATTERN_MATCHING;
LOKI_TEST_SELECT;
#pragma warning(push)
#pragma warning(disable:4127) //constant conditionals
LOKI_TEST_CONVERSION;
#pragma warning(pop)
//TypeInfo
LOKI_TEST_TYPEINFO;
//TypeTraits
#pragma warning(push)
#pragma warning(disable:4127) //constant conditionals
{
//TODO figure out correct results
cout<<"Testing TypeTraits"<<endl;
DUMP_TRAITS(int);
DUMP_TRAITS(float);
DUMP_TRAITS(volatile unsigned int);
DUMP_TRAITS(const float);
cout<<"Are the const & volatile qualifers handled correctly?"<<endl;
cout<<endl<<endl;
}
#pragma warning(pop)
//Test TypeList
#pragma warning(push)
#pragma warning(disable:4127) //constant conditionals
LOKI_TEST_LENGTH;
#pragma warning(pop)
getch();
return 0;
}
//*/

View file

@ -1,37 +0,0 @@
#pragma once
#ifndef __LOKITESTTYPES_H
#define __LOKITESTTYPES_H
//Types to use in the test
namespace Loki
{
namespace RegressionTest
{
struct Complex
{
float r,i;
};
struct Complex_Convertable
{
Complex_Convertable(){}
Complex_Convertable(float x) : r(x), i(0) {}
float r,i;
};
struct TwoWay
{
TwoWay(double x) : r(x) {}
operator double(){return r;}
double r;
};
struct SuperClass
{
};
struct SubClass : SuperClass
{
};
typedef TYPELIST_1(Loki::NullType) tyNullList;
typedef TYPELIST_1(void) tyList1;
typedef TYPELIST_2(int, double) tyList2;
typedef TYPELIST_5(std::vector<int>, Loki::RegressionTest::Complex, void, int, double) tyList5;
}
}
#endif

View file

@ -1,58 +0,0 @@
namespace Loki
{
namespace Test
{
struct CTBaseType
{
};
struct CTDerivedType : CTBaseType
{
};
struct RTBaseType
{
virtual ~RTBaseType(){}
virtual const char*const name(){return "BaseType";}
};
struct RTDerivedType : RTBaseType
{
virtual const char*const name(){return "DerivedType";}
};
}//ns Test
}//ns Loki
//TODO Test the other operators and before
#define LOKI_TEST_TYPEINFO\
{\
cout<<"Testing TypeInfo"<<endl;\
Loki::TypeInfo type_CTDerived(typeid(Loki::Test::CTDerivedType));\
\
Loki::Test::CTDerivedType* pDerived=0; pDerived;\
if(typeid(*pDerived) == type_CTDerived)\
cout<<"Compile-time TypeInfo works"<<endl;\
else\
cout<<"Compile-time TypeInfo is ***BROKEN***"<<endl;\
\
try\
{\
Loki::TypeInfo type_RTDerived(typeid(Loki::Test::RTDerivedType));\
Loki::Test::RTBaseType* pBase = new Loki::Test::RTDerivedType;\
pBase;\
if(typeid(*pBase) == type_RTDerived)\
cout<<"Run-time TypeInfo works"<<endl;\
else\
{\
cout<<"Run-time TypeInfo is ***BROKEN***"<<endl;\
cout<<"Is RTTI enabled?"<<endl;\
cout<<"Compiler thinks pBase points to a ";\
cout<<typeid(*pBase).name()<<endl;\
}\
delete pBase;\
}\
catch(...)\
{\
cout<<"Run-time TypeInfo is ***BROKEN***"<<endl;\
cout<<"Run-time TypeInfo check threw - Is RTTI enabled?"<<endl;\
}\
cout<<endl<<endl;\
}

View file

@ -1,79 +0,0 @@
#define LOKI_TEST_LENGTH\
{\
cout<<"Testing Length"<<endl;\
cout<<"Length of List1: "<<Loki::TL::Length<Loki::RegressionTest::tyList1>::value<<endl;\
cout<<"Length of List2: "<<Loki::TL::Length<Loki::RegressionTest::tyList2>::value<<endl;\
cout<<"Length of List5: "<<Loki::TL::Length<Loki::RegressionTest::tyList5>::value<<endl;\
if ( (Loki::TL::Length<Loki::RegressionTest::tyList1>::value==1) &&\
(Loki::TL::Length<Loki::RegressionTest::tyList2>::value==2) &&\
(Loki::TL::Length<Loki::RegressionTest::tyList5>::value==5) )\
cout<<"Normal cases work"<<endl;\
else\
cout<<"Normal cases are ***BROKEN***"<<endl;\
cout<<"Length of NullType: "<<Loki::TL::Length<Loki::NullType>::value<<endl;\
cout<<"Length of NullList: "<<Loki::TL::Length<Loki::RegressionTest::tyNullList>::value<<endl;\
if ( (Loki::TL::Length<Loki::NullType>::value==0) &&\
(Loki::TL::Length<Loki::RegressionTest::tyNullList>::value==0) )\
cout<<"Pathological cases work"<<endl;\
else\
cout<<"Pathological cases are ***BROKEN***"<<endl;\
cout<<endl<<endl;\
}
/*
void TypeAt()
{
cout<<endl<<"Testing TypeAt"<<endl;
//typedef TypeAt<List2, -1>::Result FailsToCompile;
typedef TypeAt<List2, 0>::Result FirstType;
typedef TypeAt<List2, 1>::Result SecondType;
typedef TypeAt<List2, 2>::Result ThirdType;
typedef TypeAt<List2, 3>::Result FourthType;
typedef TypeAt<List2, 4>::Result FifthType;
cout<<typeid(FirstType).name()<<endl;
cout<<typeid(SecondType).name()<<endl;
cout<<typeid(ThirdType).name()<<endl;
cout<<typeid(FourthType).name()<<endl;
cout<<typeid(FifthType).name()<<endl;
}
/*
void IndexOf()
{
cout<<endl<<"Testing IndexOf"<<endl;
cout<<"IndexOf int: "<<IndexOf<List2, int>::value<<endl;
cout<<"IndexOf double: "<<IndexOf<List2, double>::value<<endl;
cout<<"IndexOf vector: "<<IndexOf<List2, vector<int> >::value<<endl;
cout<<"IndexOf Complex: "<<IndexOf<List2, Complex>::value<<endl;
cout<<"IndexOf long: "<<IndexOf<List2, long>::value<<endl;
}
/*
void Append()
{
cout <<endl<<"Testing Append" << endl;
typedef Append<NullType, NullType>::Result List0;
typedef Append<List0, bool>::Result List1;
typedef Append<List1, double>::Result List2;
typedef Append<List2, NullType>:: Result List3;
cout << Length<List0>::value << endl;
cout << Length<List1>::value << "\t";
cout << typeid(TypeAt<List1, Length<List1>::value -1 >::Result).name() << endl;
cout << Length<List2>::value << "\t";
cout << typeid(TypeAt<List2, Length<List2>::value -1>::Result).name() << endl;
cout << Length<List3>::value << "\t";
cout << typeid(TypeAt<List3, Length<List3>::value -1>::Result).name() << endl;
}
/*
void Erase()
{
cout <<endl<< "Testing Erase" << endl;
cout <<"Erase is broken, notice the size goes up"<<endl;
cout << Length<List1>::value << "\t"
<< typeid(TypeAt<List1, Length<List1>::value -1 >::Result).name() << endl;
cout << Length<List2>::value << "\t"
<< typeid(TypeAt<List2, Length<List2>::value -1>::Result).name() << endl;
cout << Length<List3>::value << "\t"
<< typeid(TypeAt<List3, Length<List3>::value -1>::Result).name() << endl;
}
*/

View file

@ -1,164 +0,0 @@
#include "LokiTestTypes.h"
using std::endl;
using std::cout;
//You're not using a C++ compiler if this fails.
//Requires #include <Loki\NullType.h>
#define LOKI_TEST_NULLTYPE\
{\
Loki::NullType nullTest;\
cout<<"Testing NullType"<<endl;\
cout<<"Sizeof nullType: "<<sizeof(nullTest)<<endl;\
cout<<endl<<endl;\
}
#define LOKI_TEST_SELECT\
{\
cout<<"Testing Select"<<endl;\
typedef Loki::Select<true, void, Loki::NullType>::Result TrueType;\
typedef Loki::Select<false, int, double>::Result FalseType;\
cout<<"True case: "<<typeid(TrueType).name()<<endl;\
cout<<"False case: "<<typeid(FalseType).name()<<endl;\
cout<<endl<<endl;\
}
//TODO Need more test cases for _STRICT varaints
//TODO What is the proper conversion results to/from void?
#define LOKI_TEST_CONVERSION\
{\
cout<<"Testing Conversion"<<endl;\
typedef Loki::Conversion<int, int> tySame;\
typedef Loki::Conversion<int, Loki::RegressionTest::Complex> tyNoCon;\
typedef Loki::Conversion<int, Loki::RegressionTest::Complex_Convertable> tyCon;\
typedef Loki::Conversion<int, Loki::RegressionTest::TwoWay> ty2Way;\
typedef Loki::Conversion<void, int> tyVoid;\
cout<< tySame::sameType<<" <int, int>::sameType" <<endl;\
cout<< tySame::exists<<" <int, int>::exists" <<endl;\
cout<< tySame::exists2Way<<" <int, int>::exists2Way" <<endl;\
if (tySame::sameType && tySame::exists && tySame::exists2Way)\
cout<<"Works for same type"<<endl;\
else\
cout<<"Same type is ***BROKEN***"<<endl;\
cout<<endl;\
\
cout<< tyNoCon::sameType<<" <int, Complex>::sameType" <<endl;\
cout<< tyNoCon::exists<<" <int, Complex>::exists" <<endl;\
cout<< tyNoCon::exists2Way<<" <int, Complex>::exists2Way" <<endl;\
if (!tyNoCon::sameType && !tyNoCon::exists && !tyNoCon::exists2Way)\
cout<<"Works for non-convertibles"<<endl;\
else\
cout<<"Non-convertibles is ***BROKEN***"<<endl;\
cout<<endl;\
\
cout<< tyCon::sameType<<" <int, Complex_Convertable>::sameType" <<endl;\
cout<< tyCon::exists<<" <int, Complex_Convertable>::exists" <<endl;\
cout<< tyCon::exists2Way<<" <int, Complex_Convertable>::exists2Way" <<endl;\
if (!tyCon::sameType && tyCon::exists && !tyCon::exists2Way)\
cout<<"Works for one-way convertible"<<endl;\
else\
cout<<"One-way convertible is ***BROKEN***"<<endl;\
cout<<endl;\
\
cout<< ty2Way::sameType<<" <int, TwoWay>::sameType" <<endl;\
cout<< ty2Way::exists<<" <int, TwoWay>::exists" <<endl;\
cout<< ty2Way::exists2Way<<" <int, TwoWay>::exists2Way" <<endl;\
if (!ty2Way::sameType && ty2Way::exists && ty2Way::exists2Way)\
cout<<"Works for two-way convertibles"<<endl;\
else\
cout<<"Two-way convertibles is ***BROKEN***"<<endl;\
cout<<endl;\
\
cout<< tyVoid::sameType<<" <void, int>::sameType" <<endl;\
cout<< tyVoid::exists<<" <void, int>::exists" <<endl;\
cout<< tyVoid::exists2Way<<" <void, int>::exists2Way" <<endl;\
if (!tyVoid::sameType && !tyVoid::exists && !tyVoid::exists2Way)\
cout<<"Works for void"<<endl;\
else\
cout<<"Void conversion is ***BROKEN***"<<endl;\
cout<<"What is the correct behavior here?"<<endl;\
cout<<endl;\
\
cout<< SUPERSUBCLASS(Loki::RegressionTest::SuperClass, Loki::RegressionTest::SubClass)<<" SuperSubClass Super&Sub"<<endl;\
cout<< SUPERSUBCLASS_STRICT(Loki::RegressionTest::SuperClass, Loki::RegressionTest::SubClass)<<" SuperSubClass_Strict Super&Sub"<<endl;\
cout<< SUPERSUBCLASS(void, Loki::RegressionTest::SubClass)<<" to void*"<<endl;\
cout<< SUPERSUBCLASS_STRICT(void, Loki::RegressionTest::SubClass)<<" _Strict to void*"<<endl;\
cout<< SUPERSUBCLASS(Loki::RegressionTest::SubClass, Loki::RegressionTest::SuperClass)<<" SubSuperClass Sub&Super"<<endl;\
cout<<endl<<endl;\
}
#define LOKI_TEST_INT2TYPE\
{\
cout<<"Testing Int2Type"<<endl;\
typedef Loki::Int2Type<0> tyZero;\
typedef Loki::Int2Type<1> tyOne;\
typedef Loki::Int2Type<-1> tyNegOne;\
cout<<" Zero: "<<typeid(tyZero).name()<<endl;\
cout<<" One: "<<typeid(tyOne).name()<<endl;\
cout<<"Neg One: "<<typeid(tyNegOne).name()<<endl;\
cout<<endl<<endl;\
}
//I think this example is an undesirable way to solve this
// problem, but we're just exercising Type2Type
//MSVC7 has a template pattern matching problem that prevents this
// example solution from compiling correctly.
// Type2Type does work, but the solution it was created for doesn't
#define LOKI_TEST_TYPE2TYPE_HEADER\
struct Widget\
{\
Widget(int x, int reserved)\
{\
assert(reserved==-1);\
}\
};\
struct NewWidget\
{\
NewWidget(int x)\
{}\
};\
template<class T, class U>\
T* Create(const U& arg, Loki::Type2Type<T>)\
{\
return new T(arg);\
}\
template<class U>\
Widget* Create(const U& arg, Loki::Type2Type<Widget>)\
{\
return new Widget(arg, -1);\
}
#define LOKI_TEST_TYPE2TYPE\
{\
cout<<"Testing Type2Type"<<endl;\
NewWidget* pNewWidget = Create(4, Loki::Type2Type<NewWidget>() );\
delete pNewWidget;\
Widget* pWidget = Create(100, Loki::Type2Type<Widget>() );\
delete pWidget;\
cout<<"Used Type2Type"<<endl;\
}
#define LOKI_TEST_TYPE2TYPE_HEADER_BROKEN_PATTERN_MATCHING\
struct Widget\
{\
Widget(int x, int reserved)\
{\
cc=x;\
assert(reserved==-1);\
}\
int cc;\
};\
template<class U>\
Widget* Create(const U& arg, Loki::Type2Type<Widget>)\
{\
return new Widget(arg, -1);\
}
#define LOKI_TEST_TYPE2TYPE_BROKEN_PATTERN_MATCHING\
{\
cout<<"Testing Type2Type"<<endl;\
Widget* pWidget = Create(100, Loki::Type2Type<Widget>() );\
delete pWidget;\
cout<<"Used Type2Type"<<endl;\
cout<<endl<<endl;\
}

View file

@ -1,27 +0,0 @@
#define DUMP_TRAIT(type, trait)\
if(Loki::TypeTraits<type>::trait)\
cout<<#trait<<", ";
#define DUMP_TRAITS(type)\
{\
cout<<"("<<#type<<") ";\
DUMP_TRAIT(type, isPointer);\
DUMP_TRAIT(type, isReference);\
DUMP_TRAIT(type, isMemberPointer);\
DUMP_TRAIT(type, isStdUnsignedInt);\
DUMP_TRAIT(type, isStdSignedInt);\
DUMP_TRAIT(type, isStdIntegral);\
DUMP_TRAIT(type, isStdFloat);\
DUMP_TRAIT(type, isStdArith);\
DUMP_TRAIT(type, isStdFundamental);\
DUMP_TRAIT(type, isUnsignedInt);\
DUMP_TRAIT(type, isSignedInt);\
DUMP_TRAIT(type, isIntegral);\
DUMP_TRAIT(type, isFloat);\
DUMP_TRAIT(type, isArith);\
DUMP_TRAIT(type, isFundamental);\
DUMP_TRAIT(type, isConst);\
DUMP_TRAIT(type, isVolatile);\
cout<<endl;\
}

View file

@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 7.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LokiRegressionTest", "LokiRegressionTest.vcproj", "{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AllTest", "AllTest\AllTest.vcproj", "{59800972-3512-4147-9E8F-F5239C241F77}"
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
@ -9,10 +9,10 @@ Global
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}.Debug.ActiveCfg = Debug|Win32
{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}.Debug.Build.0 = Debug|Win32
{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}.Release.ActiveCfg = Release|Win32
{E7FC3709-2BA7-4EAB-AF6B-B3ABC9BE493B}.Release.Build.0 = Release|Win32
{59800972-3512-4147-9E8F-F5239C241F77}.Debug.ActiveCfg = Debug|Win32
{59800972-3512-4147-9E8F-F5239C241F77}.Debug.Build.0 = Debug|Win32
{59800972-3512-4147-9E8F-F5239C241F77}.Release.ActiveCfg = Release|Win32
{59800972-3512-4147-9E8F-F5239C241F77}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

View file

@ -0,0 +1,235 @@
//
// in this source code I will demonstrate via example the "canonical" and compliant way of
// simulating class template partial specialization and function templates partial ordering
// both are not implemented in VC7 and from the simulation you will see that they are closely related
// in the example I will simulate the Append class template which have 4 specializations
// Part of the sample was also tested with Comeau C/C++ 4.3.0 online
// although the code is perfectly compliant many compilers (like bcc 5.6 and gcc 3.03 which support partial stuff) can't
// handle it (maybe some workaround can help).
//
#include <stdlib.h>
#include <cstdio>
#include <typeinfo>
#include <Loki\Typelist.h>
#include <Loki\static_check.h>
using namespace ::Loki;
//
// Simulating function templates partial ordering (14.5.5.2):
// The following simple example demonstrate the whole idea
// template<typename T> void f(T);
// template<typename T> void f(T*);
// the functions are partial ordered and T* is more specialized then T
// compiler which is not supporting partial ordering will decide that f((int*)0)
// is ambiguous. We must resolve the ambiguity our self.
// There is more then one way of doing it but I like the following:
// struct A{};
// struct B : A{};
// template<typename T> void f(T, A);
// template<typename T> void f(T*, B);
// template<typename T> void f(T x) { f(x, B()); }
// for pointers f(T*, B) is better then f(T, A) when the call is f(ptr, B());
//
//
// This template will help us to "order" the function templates.
//
template<unsigned I>
struct Order : Order<I - 1> {};
template<>
struct Order<0> {};
template<unsigned I>
struct TypeTag
{
typedef char (&X)[I];
};
//
// This template class simulate the detection of the best specialization
//
template<class TList, class T>
class AppendPattern
{
// you can call me insane but VC7 fails without the following typedefs
typedef TypeTag<2>::X X2;
typedef TypeTag<3>::X X3;
typedef TypeTag<4>::X X4;
// Match Append<NullType, NullType>
static TypeTag<1>::X Match(Type2Type<NullType>, Type2Type<NullType>, Order<1>);
// Match Append<NullType, T>
template<typename T1>
static TypeTag<2>::X Match(Type2Type<NullType>, Type2Type<T1>, Order<0>);
// Match Append<NullType, Typelist<Head, Tail>>
template <class Head, class Tail>
static TypeTag<3>::X Match(Type2Type<NullType>, Type2Type<Typelist<Head, Tail> >, Order<1>);
// Match Append<Typelist<Head, Tail>, T>
template <class Head, class Tail, typename T1>
static TypeTag<4>::X Match(Type2Type<Typelist<Head, Tail> >, Type2Type<T1>, Order<0>);
static Type2Type<TList> Get1();
static Type2Type<T> Get2();
// VC will fail if the sizeof is written directly to the TypeTag
enum { value = sizeof(Match( Get1(), Get2(), Order<1>() )) };
public:
typedef TypeTag<value> Result;
};
template <class TList, class T> class Append2;
//
// This template class simulate the detection of the partial specialization
// The append helper simulate the partial specialized class templates with
// explicit specialization that represent the selected specialization and
// nested class template which implement the specialization
//
template<typename Tag> struct AppendHelper;
template<>
struct AppendHelper< TypeTag<1> >
{ // Append<NullType, NullType>
template <class, class>
struct In
{
typedef NullType Result;
};
};
template<>
struct AppendHelper< TypeTag<2> >
{ // Append<NullType, T>
template <class, class T>
struct In
{
typedef TYPELIST_1(T) Result;
};
};
template<>
struct AppendHelper< TypeTag<3> >
{ // Append<NullType, Typelist<Head, Tail> >
template <class, class TList>
struct In
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef Typelist<Head, Tail> Result;
//typedef TList Result;
};
};
template<>
struct AppendHelper< TypeTag<4> >
{ // Append<Typelist<Head, Tail>, T>
template <class TList, class T>
struct In
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
typedef Typelist<Head, typename Append2<Tail, T>::Result> Result;
};
};
template <class TList, class T>
class Append2
{
// First we detect the best specialization
typedef typename AppendPattern<TList, T>::Result Pattern;
public:
// Insatiate the best specialization
typedef typename AppendHelper<Pattern>::
template In<TList, T>::Result
Result;
};
//
// Lets toy with the simulated Append
//
typedef struct IncompType *IncompPtr;
struct A1 {};
struct B1 : A1 {};
struct A2 {};
struct B2 : A2 {};
struct C1 : B1 {};
struct C2 : B2 {};
struct D1 : C1, C2 {};
namespace
{
template<typename TList>
struct PrintTypelist
{
PrintTypelist()
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
printf("%s ,", typeid(Head).name());
PrintTypelist<Tail>();
}
};
template<>
struct PrintTypelist<NullType>
{
PrintTypelist()
{
printf("\n");
}
};
template<class TList, typename T>
void Test_Append2()
{
typedef typename TL::Append<TList, T>::Result typelist1_t;
typedef typename Append2<TList, T>::Result typelist2_t;
// Assert (compile time) that typelist1_t and typelist2_t are the same type
STATIC_CHECK((Conversion<typelist1_t, typelist2_t>::sameType), Append2_Failed);
PrintTypelist<typelist1_t>();
PrintTypelist<typelist2_t>();
}
void Test_Append()
{
typedef TL::MakeTypeList<int, A1, A2>::Result typelist1_t;
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**>::Result typelist2_t;
Test_Append2<NullType, NullType>();
Test_Append2<NullType, typelist2_t>();
Test_Append2<typelist1_t, NullType>();
Test_Append2<NullType, int>();
Test_Append2<typelist1_t, int[10]>();
Test_Append2<typelist1_t, typelist2_t>();
}
} // anonymous namespace
int main()
{
Test_Append();
system("pause");
}

View file

@ -0,0 +1,148 @@
#include <iostream>
#include <memory>
#include "AbstractFactory.h"
using namespace ::Loki;
struct Enemy
{
virtual Enemy* Clone() = 0;
virtual ~Enemy() {};
};
struct Soldier : Enemy
{
virtual Soldier* Clone() = 0;
virtual const char *SoldierName() const = 0;
};
struct Monster : Enemy
{
virtual Monster* Clone() = 0;
virtual const char *MonsterName() const = 0;
};
struct SuperMonster : Enemy
{
virtual SuperMonster* Clone() = 0;
virtual const char *SuperMonsterName() const = 0;
};
typedef AbstractFactory
<
TYPELIST_3(Soldier, Monster, SuperMonster)
>
AbstractEnemyFactory;
class SillySoldier
: public Soldier
{
public:
explicit SillySoldier(const char *name = "Anonymous Silly Soldier")
: name_(name)
{}
virtual SillySoldier* Clone()
{
return new SillySoldier("Cloned Silly Soldier");
}
virtual const char *SoldierName() const { return name_; }
private:
const char *name_;
};
class SillyMonster
: public Monster
{
public:
explicit SillyMonster(const char *name = "Anonymous Silly Monster")
: name_(name)
{}
virtual SillyMonster* Clone()
{
return new SillyMonster("Cloned Silly Moster");
}
virtual const char *MonsterName() const { return name_; }
private:
const char *name_;
};
class SillySuperMonster
: public SuperMonster
{
public:
explicit SillySuperMonster(const char *name = "Anonymous Silly SuperMonster")
: name_(name)
{}
virtual SillySuperMonster* Clone()
{
return new SillySuperMonster("Cloned Silly SuperMoster");
}
virtual const char *SuperMonsterName() const { return name_; }
private:
const char *name_;
};
typedef ConcreteFactory
<
AbstractEnemyFactory,
OpNewFactoryUnit,
TYPELIST_3(SillySoldier, SillyMonster, SillySuperMonster)
>
EasyLevelEnemyFactory;
typedef ConcreteFactory
<
AbstractEnemyFactory,
PrototypeFactoryUnit
>
EnemyFactory;
void print_names(AbstractEnemyFactory &abstEnemyFactory)
{
using std::auto_ptr;
auto_ptr<Soldier> apSoldier(abstEnemyFactory.Create<Soldier>());
std::cout << apSoldier->SoldierName() << std::endl;
auto_ptr<Monster> apMonster(abstEnemyFactory.Create<Monster>());
std::cout << apMonster->MonsterName() << std::endl;
auto_ptr<SuperMonster> apSuperMonster(abstEnemyFactory.Create<SuperMonster>());
std::cout << apSuperMonster->SuperMonsterName() << std::endl;
}
int main()
{
EasyLevelEnemyFactory testEasyLevelEnemyFactory;
print_names(testEasyLevelEnemyFactory);
EnemyFactory testEnemyFactory;
SillySoldier testSillySoldier;
testEnemyFactory.SetPrototype(&testSillySoldier);
SillyMonster testSillyMonster;
testEnemyFactory.SetPrototype(&testSillyMonster);
SillySuperMonster testSillySuperMonster;
testEnemyFactory.SetPrototype(&testSillySuperMonster);
print_names(testEnemyFactory);
}

View file

@ -0,0 +1,35 @@
#include <cstdio>
#include <typeinfo>
#include "Factory.h"
#include "AbstractFactory.h"
template<typename T>
void print_type()
{
printf("%s\n", typeid(T).name());
}
using namespace ::Loki;
struct A1 {}; struct A2 {}; struct A3 {}; struct A4 {};
struct A5 {}; struct A6 {}; struct A7 {}; struct A8 {};
typedef TL::MakeTypeList<A1, A2, A3, A4, A5, A6, A7, A8>::Result typelist1_t;
struct Abst : AbstractFactory<typelist1_t> {};
int main()
{
Factory<A1, int> a;
CloneFactory<A1> b;
typedef AbstractFactory<typelist1_t> abst_t;
struct AA1 : ConcreteFactory<abst_t, OpNewFactoryUnit> {};
AA1 a1;
struct AA2 : ConcreteFactory<Abst, OpNewFactoryUnit> {};
AA2 a2;
}

View file

@ -0,0 +1,44 @@
#include <cstdio>
#include "Functor.h"
using namespace Loki;
class A
{
public:
explicit A(int number)
: number_(number)
{}
int Get() const { return number_; }
private:
int number_;
};
int foo(int a1, A a2, const A &a3)
{
return a1 + a2.Get() + a3.Get();
}
int
main()
{
typedef Functor< int, TYPELIST_3(int, A, const A &) > func1_t;
func1_t fun1(foo);
func1_t fun2(fun1);
A num1(10);
printf("%d\n", fun1(1, num1, A(100)));
#if defined(_MSC_VER) && _MSC_VER == 1300
// will not compile with the original Loki although its fine
printf("%d\n", BindFirst(fun2, 15)(A(24), num1));
#else
A num2(24);
printf("%d\n", BindFirst(fun2, 15)(num2, num1)); // will not compile with the original loki
#endif
}

View file

@ -0,0 +1,69 @@
#include <cstdio>
#include <typeinfo>
#include "HierarchyGenerators.h"
using namespace ::Loki;
//
// Helper class for simulating (ranking) partial ordering
//
template<unsigned I>
struct Order : Order<I - 1> {};
template<>
struct Order<0> {};
template<template<typename> class Unit>
class PrintGenScatterHierarchy
{
template<typename Head, typename Tail>
PrintGenScatterHierarchy(GenScatterHierarchy<Typelist<Head, Tail>, Unit> *a, Order<1>)
{
printf("%s\n", typeid(*a).name());
GenScatterHierarchy<Head, Unit> *left = a;
PrintGenScatterHierarchy<Unit> X1(left);
GenScatterHierarchy<Tail, Unit> *right = a;
PrintGenScatterHierarchy<Unit> X2(right);
}
template<typename T>
PrintGenScatterHierarchy(GenScatterHierarchy<T, Unit> *a, Order<0>)
{
printf("%s\n", typeid(*a).name());
Unit<T> *left = a;
(void)left;
printf("%s\n", typeid(*left).name());
}
PrintGenScatterHierarchy(GenScatterHierarchy<NullType, Unit> *a, Order<1>)
{
(void)a;
printf("%s\n", typeid(*a).name());
}
public:
template<typename T>
explicit PrintGenScatterHierarchy(GenScatterHierarchy<T, Unit> *a)
{
PrintGenScatterHierarchy<Unit>(a, Order<1>());
}
};
template<typename> class TestUnit {};
template<int> struct A {};
int
main()
{
typedef TYPELIST_10(A<1>, A<2>, A<3>, A<4>, A<5>, A<6>, A<7>, A<8>, A<9>, A<10>) TestList_t;
GenScatterHierarchy<TestList_t, TestUnit> TestGenScatterHierarchy;
PrintGenScatterHierarchy<TestUnit> X(&TestGenScatterHierarchy);
}

View file

@ -0,0 +1,70 @@
#include <cstdio>
#include <typeinfo>
#include "HierarchyGenerators.h"
using namespace ::Loki;
//
// Helper class for simulating (ranking) partial ordering
//
template<unsigned I>
struct Order : Order<I - 1> {};
template<>
struct Order<0> {};
template<template<typename, typename> class Unit, class Root>
class PrintGenLinearHierarchy
{
template<typename Head>
PrintGenLinearHierarchy(GenLinearHierarchy<Typelist<Head, NullType>, Unit, Root> *a, Order<1>)
{
printf("%s\n", typeid(*a).name());
Unit<Head, Root> *base1 = a;
printf("%s\n", typeid(*base1).name());
Root *base2 = base1; (void)base2;
printf("%s\n", typeid(*base2).name());
}
template<typename Head, typename Tail>
PrintGenLinearHierarchy(GenLinearHierarchy<Typelist<Head, Tail>, Unit, Root> *a, Order<0>)
{
printf("%s\n", typeid(*a).name());
Unit<Head, GenLinearHierarchy<Tail, Unit, Root> > *base1 = a;
printf("%s\n", typeid(*base1).name());
GenLinearHierarchy<Tail, Unit, Root> *base2 = base1;
PrintGenLinearHierarchy<Unit, Root> X(base2);
}
public:
template<typename Head, typename Tail>
explicit PrintGenLinearHierarchy(GenLinearHierarchy<Typelist<Head, Tail>, Unit, Root> *a)
{
PrintGenLinearHierarchy<Unit, Root>(a, Order<1>());
}
};
template<typename, class Base>
class TestUnit : public Base {};
class TestRoot {};
template<int> struct A {};
int
main()
{
typedef TYPELIST_10(A<1>, A<2>, A<3>, A<4>, A<5>, A<6>, A<7>, A<8>, A<9>, A<10>) TestList_t;
GenLinearHierarchy<TestList_t, TestUnit, TestRoot> TestGenLinearHierarchy;
PrintGenLinearHierarchy<TestUnit, TestRoot> X(&TestGenLinearHierarchy);
}

View file

@ -0,0 +1,76 @@
#include <cstdio>
#include <typeinfo>
#include "HierarchyGenerators.h"
using namespace ::Loki;
//
// Helper class for simulating (ranking) partial ordering
//
template<unsigned I>
struct Order : Order<I - 1> {};
template<>
struct Order<0> {};
template<template<typename> class Unit>
class PrintGenScatterHierarchy
{
//
// The second parameter is not needed when using compilers that support partial ordering
// VC7 doesn't support that feature - this is an example of simulating that feature in VC7
//
template<typename Head, typename Tail>
static void Print(GenScatterHierarchy<Typelist<Head, Tail>, Unit> &a, Order<1>)
{
printf("%s\n", typeid(a).name());
GenScatterHierarchy<Head, Unit> &left = a;
Print(left);
GenScatterHierarchy<Tail, Unit> &right = a;
Print(right);
}
template<typename T>
static void Print(GenScatterHierarchy<T, Unit> &a, Order<0>)
{
printf("%s\n", typeid(a).name());
Unit<T> &left = a;
(void)left;
printf("%s\n", typeid(left).name());
}
static void Print(GenScatterHierarchy<NullType, Unit> &a, Order<1>)
{
(void)a;
printf("%s\n", typeid(a).name());
}
public:
template<typename T>
static void Print(GenScatterHierarchy<T, Unit> &a)
{
Print(a, Order<1>());
}
};
template<typename> class TestUnit {};
template<int> struct A {};
template<int> struct B {};
int
main()
{
typedef TYPELIST_20(A<1>, A<2>, A<3>, A<4>, A<5>, A<6>, A<7>, A<8>, A<9>, A<10>,
B<1>, B<2>, B<3>, B<4>, B<5>, B<6>, B<7>, B<8>, B<9>, B<10>) TestList_t;
GenScatterHierarchy<TestList_t, TestUnit> TestGenScatterHierarchy;
PrintGenScatterHierarchy<TestUnit>::Print(TestGenScatterHierarchy);
}

View file

@ -0,0 +1,72 @@
#include <cstdio>
#include <typeinfo>
#include "HierarchyGenerators.h"
using namespace ::Loki;
//
// Helper class for simulating (ranking) partial ordering
//
template<unsigned I>
struct Order : Order<I - 1> {};
template<>
struct Order<0> {};
template<template<typename, typename> class Unit, class Root>
class PrintGenLinearHierarchy
{
template<typename Head, typename Tail>
static void Print(GenLinearHierarchy<Typelist<Head, Tail>, Unit, Root> &a, Order<0>)
{
printf("%s\n", typeid(a).name());
Unit<Head, GenLinearHierarchy<Tail, Unit, Root> > &base1 = a;
printf("%s\n", typeid(base1).name());
GenLinearHierarchy<Tail, Unit, Root> &base2 = base1;
Print(base2);
}
template<typename Head>
static void Print(GenLinearHierarchy<Typelist<Head, NullType>, Unit, Root> &a, Order<1>)
{
printf("%s\n", typeid(a).name());
Unit<Head, Root> &base1 = a;
printf("%s\n", typeid(base1).name());
Root &base2 = base1; (void)base2;
printf("%s\n", typeid(base2).name());
}
public:
template<typename Head, typename Tail>
static void Print(GenLinearHierarchy<Typelist<Head, Tail>, Unit, Root> &a)
{
Print(a, Order<1>());
}
};
template<typename, class Base>
class TestUnit : public Base {};
class TestRoot {};
template<int> struct A {};
template<int> struct B {};
int
main()
{
typedef TYPELIST_20(A<1>, A<2>, A<3>, A<4>, A<5>, A<6>, A<7>, A<8>, A<9>, A<10>,
B<1>, B<2>, B<3>, B<4>, B<5>, B<6>, B<7>, B<8>, B<9>, B<10>) TestList_t;
GenLinearHierarchy<TestList_t, TestUnit, TestRoot> TestGenLinearHierarchy;
PrintGenLinearHierarchy<TestUnit, TestRoot>::Print(TestGenLinearHierarchy);
}

View file

@ -0,0 +1,220 @@
#include <iostream>
#include <typeinfo>
#include <memory>
#include <cassert>
#include "MultiMethods.h"
using ::std::cout;
struct Shape
{
virtual ~Shape() = 0;
};
Shape::~Shape() {}
class Rectangle : public Shape {};
class Poly : public Shape {};
class Ellipse : public Shape {};
class Cycloid : public Shape {};
class SymHachingExecutor
{
public:
typedef void ResultType;
ResultType Fire(Rectangle&, Rectangle&)
{ cout << "Fire(Rectangle&, Rectangle&)" << '\n'; }
ResultType Fire(Rectangle&, Poly&)
{ cout << "Fire(Rectangle&, Poly&)" << '\n'; }
ResultType Fire(Rectangle&, Ellipse&)
{ cout << "Fire(Rectangle&, Ellipse&)" << '\n'; }
ResultType Fire(Poly&, Poly&)
{ cout << "Fire(Poly&, Poly&)" << '\n'; }
ResultType Fire(Poly&, Ellipse&)
{ cout << "Fire(Poly&, Ellipse&)" << '\n'; }
ResultType Fire(Ellipse&, Ellipse&)
{ cout << "Fire(Ellipse&, Ellipse&)" << '\n'; }
void OnError(Shape& x, Shape& y)
{
cout << "OnError: "
<< typeid(x).name() << ", "
<< typeid(y).name() << '\n';
}
};
typedef ::Loki::StaticDispatcher
<
SymHachingExecutor,
Shape,
TYPELIST_3(Rectangle, Poly, Ellipse)
>
SymHachingDispatcher;
class HachingExecutor : SymHachingExecutor
{
public:
typedef SymHachingExecutor::ResultType ResultType;
using SymHachingExecutor::Fire;
ResultType Fire(Poly&, Rectangle&)
{ cout << "Fire(Poly&, Rectangle&)" << '\n'; }
ResultType Fire(Ellipse&, Rectangle&)
{ cout << "Fire(Ellipse&, Rectangle&)" << '\n'; }
ResultType Fire(Ellipse&, Poly&)
{ cout << "Fire(Ellipse&, Poly&)" << '\n'; }
using SymHachingExecutor::OnError;
};
typedef ::Loki::StaticDispatcher
<
HachingExecutor,
Shape,
TYPELIST_3(Rectangle, Poly, Ellipse),
false
>
HachingDispatcher;
template<class TestedHachingDispatcher, class TestedHachingExecutor>
void Test_HachingDispatcher(TestedHachingExecutor Exec)
{
using ::std::auto_ptr;
auto_ptr<Shape> shape1(new Rectangle);
auto_ptr<Shape> shape2(new Ellipse);
auto_ptr<Shape> shape3(new Poly);
auto_ptr<Shape> shape4(new Cycloid);
static const std::size_t number_of_shapes = 4;
Shape * const shapes[number_of_shapes] =
{
shape1.get(), shape2.get(),
shape3.get(), shape4.get(),
};
for (std::size_t i = 0 ; i < number_of_shapes ; ++i)
for (std::size_t j = 0 ; j < number_of_shapes ; ++j)
{
TestedHachingDispatcher::Go(*shapes[i], *shapes[j], Exec);
}
}
typedef ::Loki::BasicDispatcher<Shape> ShapeBasicDispatcher;
typedef ::Loki::FnDispatcher<Shape> ShapeFnDispatcher;
typedef ::Loki::FunctorDispatcher<Shape> ShapeFunctorDispatcher;
namespace // anonymous
{
template<class Shape1, class Shape2>
void HatchShapesDo(Shape1 &, Shape2 &)
{
cout << "HatchShapes: "
<< typeid(Shape1).name() << ", "
<< typeid(Shape2).name() << '\n';
}
template<class Shape1, class Shape2>
void HatchShapes(Shape &lhs, Shape &rhs)
{
assert(dynamic_cast<Shape1*>(&lhs) != 0);
assert(dynamic_cast<Shape2*>(&rhs) != 0);
HatchShapesDo(static_cast<Shape1&>(lhs),
static_cast<Shape2&>(rhs));
}
template<class Shape1, class Shape2>
struct HatchShapesFunctor
{
void operator()(Shape1 &lhs, Shape2 &rhs)
{
HatchShapesDo(lhs, rhs);
}
};
} // anonymous namespace
template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeBasicDispatcher &x)
{
x.Add<Shape1, Shape2>(HatchShapes<Shape1, Shape2>);
}
template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeFnDispatcher &x)
{
x.Add<Shape1, Shape2>(HatchShapes<Shape1, Shape2>);
}
template<class Shape1, class Shape2>
void ShapeDispatcherAdd(ShapeFunctorDispatcher &x)
{
x.Add<Shape1, Shape2>(HatchShapesFunctor<Shape1, Shape2>());
}
template<class Dispacher>
void Test_LogDispacher()
{
Dispacher testedBasicDispatcher;
ShapeDispatcherAdd<Rectangle, Poly>(testedBasicDispatcher);
ShapeDispatcherAdd<Poly, Rectangle>(testedBasicDispatcher);
ShapeDispatcherAdd<Rectangle, Ellipse>(testedBasicDispatcher);
ShapeDispatcherAdd<Ellipse, Poly>(testedBasicDispatcher);
ShapeDispatcherAdd<Poly, Poly>(testedBasicDispatcher);
using ::std::auto_ptr;
auto_ptr<Shape> shape1(new Rectangle);
auto_ptr<Shape> shape2(new Ellipse);
auto_ptr<Shape> shape3(new Poly);
static const std::size_t number_of_shapes = 3;
Shape * const shapes[number_of_shapes] =
{
shape1.get(), shape2.get(), shape3.get(),
};
for (std::size_t i = 0 ; i < number_of_shapes ; ++i)
for (std::size_t j = 0 ; j < number_of_shapes ; ++j)
{
try
{
testedBasicDispatcher.Go(*shapes[i], *shapes[j]);
}
catch(::std::runtime_error &exp)
{
cout << exp.what() << ": "
<< typeid(*shapes[i]).name() << ", "
<< typeid(*shapes[j]).name() << '\n';
}
}
}
int main()
{
SymHachingExecutor SymExec;
Test_HachingDispatcher<SymHachingDispatcher>(SymExec);
HachingExecutor Exec;
Test_HachingDispatcher<HachingDispatcher>(Exec);
Test_LogDispacher<ShapeBasicDispatcher>();
Test_LogDispacher<ShapeFnDispatcher>();
Test_LogDispacher<ShapeFunctorDispatcher>();
}

View file

@ -0,0 +1,34 @@
#include <Loki\Singleton.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace ::Loki;
namespace
{
struct A { ~A(){} };
struct B { ~B(){} };
struct C { ~C(){} };
unsigned int GetLongevity(C*)
{
return 1;
}
}//ns anon
extern void Test_Singleton()
{
cout << "Testing Loki\\Singleton" << endl;
typedef SingletonHolder<A> SingletonHolder1_t;
typedef SingletonHolder<B, CreateStatic> SingletonHolder2_t;
typedef SingletonHolder<C, CreateUsingNew, SingletonWithLongevity> SingletonHolder3_t;
A& p = SingletonHolder1_t::Instance();
SingletonHolder2_t::Instance();
SingletonHolder3_t::Instance();
cout << endl << endl;
}

View file

@ -0,0 +1,22 @@
//
//Test the Small Object Allocator
// MKH
//
#include <Loki\SmallObj.h>
namespace
{
struct Test : Loki::SmallObj
{
};
void Test_SmallObject()
{
Test;
}
}//ns anon
extern void Test_SmallObj()
{
Test_SmallObject();
}

View file

@ -0,0 +1,286 @@
#include <vector>
#include <algorithm>
#include <cassert>
#include <Loki\SmartPtr.h>
#include <iostream>
using std::cout;
using std::endl;
#if defined(TEST_LOKI_ORIG)
namespace Loki
{
template
<
typename T,
template <class> class OwnershipPolicy = RefCounted,
class ConversionPolicy = DisallowConversion,
template <class> class CheckingPolicy = AssertCheck,
template <class> class StoragePolicy = DefaultSPStorage
>
struct SmartPtrDef
{
typedef SmartPtr
<
T,
OwnershipPolicy,
ConversionPolicy,
CheckingPolicy,
StoragePolicy
>
type;
};
} // namespace Loki
#endif // defined(TEST_LOKI_ORIG)
using namespace ::Loki;
namespace
{
struct A
{
A() { ++s_instCount; }
A(const A &) { ++s_instCount; }
virtual ~A() { --s_instCount; }
virtual const char *name() const = 0;
static void AssertInstCount()
{
assert(s_instCount == 0);
}
private:
static int s_instCount;
};
int A::s_instCount = 0;
struct B : A
{
virtual const char *name() const
{
return "B";
}
};
struct C : A
{
virtual const char *name() const
{
return "C";
}
};
template<class SmartPtr_A>
struct PrintA
{
void operator()(const SmartPtr_A &spA) const
{
std::cout << spA->name() << ", ";
}
};
void Test_SmartPointer()
{
typedef SmartPtrDef<A, RefCounted>::type SmartPtr_A;
typedef SmartPtrDef<B, RefCounted>::type SmartPtr_B;
typedef SmartPtrDef<C, RefCounted>::type SmartPtr_C;
SmartPtr_B spB(new B);
SmartPtr_C spC(new C);
SmartPtr_A spA1(spB);
SmartPtr_A spA2(spC);
std::cout << spA1->name() << std::endl;
std::cout << spA2->name() << std::endl;
spA1 = spA2;
spA2 = spB;
std::cout << spA1->name() << std::endl;
if (spA2 == spA1)
{
std::cout << spA2->name() << std::endl;
}
Reset(spA2, new C);
if (spA2)
{
std::cout << spA2->name() << std::endl;
}
std::vector<SmartPtr_A> vectorA;
for (unsigned i = 0 ; i < 10 ; ++i)
{
if ((i % 3) == 0)
{
vectorA.push_back(new B);
}
else
{
vectorA.push_back(new C);
}
}
for (unsigned i = 0 ; i < 10 ; ++i)
{
vectorA.push_back(vectorA[i]);
}
std::for_each(vectorA.begin(), vectorA.end(), PrintA<SmartPtr_A>());
std::cout << std::endl;
}
// I know it's ugly code duplication but the template version kills VC7
void Test_SmartPtrRL()
{
typedef SmartPtrDef<A, RefLinked>::type SmartPtr_A;
typedef SmartPtrDef<B, RefLinked>::type SmartPtr_B;
typedef SmartPtrDef<C, RefLinked>::type SmartPtr_C;
SmartPtr_B spB(new B);
SmartPtr_C spC(new C);
SmartPtr_A spA1(spB);
SmartPtr_A spA2(spC);
std::cout << spA1->name() << std::endl;
std::cout << spA2->name() << std::endl;
spA1 = spA2;
spA2 = spB;
std::cout << spA1->name() << std::endl;
if (spA2 == spA1)
{
std::cout << spA2->name() << std::endl;
}
Reset(spA2, new C);
if (spA2)
{
std::cout << spA2->name() << std::endl;
}
std::vector<SmartPtr_A> vectorA;
for (unsigned i = 0 ; i < 10 ; ++i)
{
if ((i % 3) == 0)
{
vectorA.push_back(new B);
}
else
{
vectorA.push_back(new C);
}
}
for (unsigned i = 0 ; i < 10 ; ++i)
{
vectorA.push_back(vectorA[i]);
}
std::for_each(vectorA.begin(), vectorA.end(), PrintA<SmartPtr_A>());
std::cout << std::endl;
}
void Test_SmartPtrMT()
{
#define MyRefCountedMT RefCountedMTAdj<SingleThreaded>::RefCountedMT
typedef SmartPtrDef<A, MyRefCountedMT>::type SmartPtr_A;
typedef SmartPtrDef<B, MyRefCountedMT>::type SmartPtr_B;
typedef SmartPtrDef<C, MyRefCountedMT>::type SmartPtr_C;
#undef MyRefCountedMT
SmartPtr_B spB(new B);
SmartPtr_C spC(new C);
SmartPtr_A spA1(spB);
SmartPtr_A spA2(spC);
std::cout << spA1->name() << std::endl;
std::cout << spA2->name() << std::endl;
spA1 = spA2;
spA2 = spB;
std::cout << spA1->name() << std::endl;
if (spA2 == spA1)
{
std::cout << spA2->name() << std::endl;
}
Reset(spA2, new C);
if (spA2)
{
std::cout << spA2->name() << std::endl;
}
std::vector<SmartPtr_A> vectorA;
for (unsigned i = 0 ; i < 10 ; ++i)
{
if ((i % 3) == 0)
{
vectorA.push_back(new B);
}
else
{
vectorA.push_back(new C);
}
}
for (unsigned i = 0 ; i < 10 ; ++i)
{
vectorA.push_back(vectorA[i]);
}
std::for_each(vectorA.begin(), vectorA.end(), PrintA<SmartPtr_A>());
std::cout << std::endl;
}
void Test_RejectNull()
{
typedef SmartPtrDef<A, RefCounted, DisallowConversion, RejectNull>::type SmartPtr_A;
try {
SmartPtr_A spA;
} catch (std::exception &ex) {
std::cout << "Reject Default: " << ex.what() << std::endl;
}
try {
SmartPtr_A spA(0);
} catch (std::exception &ex) {
std::cout << "Reject Null: " << ex.what() << std::endl;
}
}
}// anonymous namespace
extern void Test_SmartPtr()
{
cout << "Testing Loki\\SmartPtr" << endl;
Test_SmartPointer();
Test_SmartPtrRL();
Test_SmartPtrMT();
Test_RejectNull();
A::AssertInstCount();
cout << endl << endl;
}

View file

@ -0,0 +1,145 @@
#include <windows.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include "SmartPtr.h"
#if defined(TEST_LOKI_ORIG)
namespace Loki
{
template
<
typename T,
template <class> class OwnershipPolicy = RefCounted,
class ConversionPolicy = DisallowConversion,
template <class> class CheckingPolicy = AssertCheck,
template <class> class StoragePolicy = DefaultSPStorage
>
struct SmartPtrDef
{
typedef SmartPtr
<
T,
OwnershipPolicy,
ConversionPolicy,
CheckingPolicy,
StoragePolicy
>
type;
};
} // namespace Loki
#endif // defined(TEST_LOKI_ORIG)
using namespace ::Loki;
struct A
{
A() { ++s_instCount; }
A(const A &) { ++s_instCount; }
virtual ~A() { --s_instCount; }
virtual const char *name() const = 0;
static void AssertInstCount()
{
assert(s_instCount == 0);
}
private:
static int s_instCount;
};
int A::s_instCount = 0;
struct B : A
{
virtual const char *name() const
{
return "B";
}
};
struct C : A
{
virtual const char *name() const
{
return "C";
}
};
template<class SmartPtr_A>
struct PrintA
{
void operator()(const SmartPtr_A &spA) const
{
std::cout << spA->name() << ", ";
}
};
void Test_SmartPtr()
{
#define MyRefCountedMT RefCountedMTAdj<ObjectLevelLockable>::RefCountedMT
//#define MyRefCountedMT RefCountedMTAdj<ClassLevelLockable>::RefCountedMT
typedef SmartPtrDef<A, MyRefCountedMT>::type SmartPtr_A;
typedef SmartPtrDef<B, MyRefCountedMT>::type SmartPtr_B;
typedef SmartPtrDef<C, MyRefCountedMT>::type SmartPtr_C;
#undef MyRefCountedMT
SmartPtr_B spB(new B);
SmartPtr_C spC(new C);
SmartPtr_A spA1(spB);
SmartPtr_A spA2(spC);
std::cout << spA1->name() << std::endl;
std::cout << spA2->name() << std::endl;
spA1 = spA2;
spA2 = spB;
std::cout << spA1->name() << std::endl;
if (spA2 == spA1)
{
std::cout << spA2->name() << std::endl;
}
Reset(spA2, new C);
if (spA2)
{
std::cout << spA2->name() << std::endl;
}
std::vector<SmartPtr_A> vectorA;
for (unsigned i = 0 ; i < 10 ; ++i)
{
if ((i % 3) == 0)
{
vectorA.push_back(new B);
}
else
{
vectorA.push_back(new C);
}
}
for (unsigned i = 0 ; i < 10 ; ++i)
{
vectorA.push_back(vectorA[i]);
}
std::for_each(vectorA.begin(), vectorA.end(), PrintA<SmartPtr_A>());
std::cout << std::endl;
}
int main()
{
Test_SmartPtr();
A::AssertInstCount();
}

View file

@ -0,0 +1,21 @@
//
//Test the Thread components
// MKH
#include <Loki\Threads.h>
using namespace ::Loki;
#include <iostream>
using std::cout;
using std::endl;
namespace
{
}
extern void Test_Threads()
{
cout << "Testing Loki\\Threads" << endl;
SingleThreaded<void>();
cout << endl << endl;
}

View file

@ -0,0 +1,70 @@
#include <cstdio>
#include <typeinfo>
#include "HierarchyGenerators.h"
using namespace Loki;
template<typename T>
void PrintType(T &)
{
printf("%s\n", typeid(T).name());
}
template<unsigned I>
class PrintTuple
{
public:
template<typename T>
explicit PrintTuple(const T &x)
{
PrintTuple<I - 1> X(x);
PrintType(Field<I>(x));
}
};
template<>
class PrintTuple<0>
{
public:
template<typename T>
explicit PrintTuple(const T &x)
{
PrintType(Field<0>(x));
}
};
template<typename T>
void PrintTupleFunc()
{
T x;
PrintTuple<TL::Length<typename T::TList>::value - 1> X(x);
}
template<int> struct A {};
int
main()
{
typedef TYPELIST_11(A<1>, A<1>, int, int, A<1>, A<2>, int[10], int, int *, A<2>, A<3>) typelist_t;
typedef Tuple<typelist_t> tuple_t;
PrintTupleFunc<tuple_t>();
tuple_t X;
A<3> Y = Field< A<3> >(X);
// without -Za warning C4239: nonstandard extension used
// this is because VC sometimes binds temporary to non-const reference
// which leads to selecting the wrong Field function (non-const version)
// fixed in VC7.1
Y = Field< A<3> >(tuple_t());
A<3> &Y1 = Field< A<3> >(X);
Y1 = Y;
}

View file

@ -0,0 +1,223 @@
#include <cstdio>
#include <typeinfo>
#include <Loki\Typelist.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace ::Loki;
namespace
{
typedef struct IncompType *IncompPtr;
struct A1 {};
struct B1 : A1 {};
struct A2 {};
struct B2 : A2 {};
struct C1 : B1 {};
struct C2 : B2 {};
struct D1 : C1, C2 {};
template<typename TList>
struct PrintTypelist
{
PrintTypelist()
{
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
printf("%s ,", typeid(Head).name());
PrintTypelist<Tail>();
}
};
template<>
struct PrintTypelist<NullType>
{
PrintTypelist()
{
printf("\n");
}
};
void Test_Length()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, int, B2*, B2 const *, B1>::Result typelist_t;
printf("%u\n", TL::Length<typelist_t>::value);
}
void Test_TypeAt()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, int>::Result typelist_t;
printf("%s, ", typeid(TL::TypeAt<typelist_t, 0>::Result).name());
printf("%s, ", typeid(TL::TypeAt<typelist_t, 1>::Result).name());
printf("%s, ", typeid(TL::TypeAt<typelist_t, 2>::Result).name());
printf("%s, ", typeid(TL::TypeAt<typelist_t, 3>::Result).name());
printf("%s, ", typeid(TL::TypeAt<typelist_t, 4>::Result).name());
printf("\n");
}
void Test_IndexOf()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, int, B2*, B2 const *, B1>::Result typelist_t;
printf("%u, ", TL::IndexOf<typelist_t, IncompPtr>::value);
printf("%u, ", TL::IndexOf<typelist_t, B1>::value);
printf("%u, ", TL::IndexOf<typelist_t, B2*>::value);
printf("%u, ", TL::IndexOf<typelist_t, A2**>::value);
printf("%u, ", TL::IndexOf<typelist_t, int>::value);
printf("%u, ", TL::IndexOf<typelist_t, B2 const *>::value);
printf("%u, ", TL::IndexOf<typelist_t, const B1>::value);
printf("%u, ", TL::IndexOf<typelist_t, B1&>::value);
printf("%u, ", TL::IndexOf<typelist_t, int const &>::value);
printf("\n");
}
void Test_TypeAtNonStrict()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, int>::Result typelist_t;
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 0>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 1>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 2, double>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 3>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 4>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 5>::Result).name());
printf("%s, ", typeid(TL::TypeAtNonStrict<typelist_t, 9, void>::Result).name());
printf("\n");
}
void Test_Append()
{
typedef TL::MakeTypeList<int, A1, A2>::Result typelist1_t;
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**>::Result typelist2_t;
PrintTypelist<TL::Append<NullType, NullType>::Result>();
PrintTypelist<TL::Append<NullType, typelist2_t>::Result>();
PrintTypelist<TL::Append<typelist1_t, NullType>::Result>();
PrintTypelist<TL::Append<NullType, int>::Result>();
PrintTypelist<TL::Append<typelist1_t, int[10]>::Result>();
PrintTypelist<TL::Append<typelist1_t, typelist2_t>::Result>();
}
void Test_Erase()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1>::Result typelist_t;
PrintTypelist<TL::Erase<typelist_t, int>::Result>();
PrintTypelist<TL::Erase<typelist_t, B1>::Result>();
PrintTypelist<TL::Erase<typelist_t, B2>::Result>();
PrintTypelist<TL::Erase<typelist_t, const B1>::Result>();
PrintTypelist<TL::Erase<typelist_t, B2 const *>::Result>();
PrintTypelist<TL::Erase<typelist_t, A2**>::Result>();
PrintTypelist<TL::Erase<typelist_t, NullType>::Result>();
}
void Test_EraseAll()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1, B2*, B2 const *, B1>::Result typelist_t;
PrintTypelist<TL::EraseAll<typelist_t, int>::Result>();
PrintTypelist<TL::EraseAll<typelist_t, B1>::Result>();
PrintTypelist<TL::EraseAll<typelist_t, B2*>::Result>();
PrintTypelist<TL::EraseAll<typelist_t, B2 const *>::Result>();
PrintTypelist<TL::EraseAll<typelist_t, NullType>::Result>();
}
void Test_NoDuplicates()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1, B2*, B2 const *, B1>::Result typelist1_t;
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B2 const *>::Result typelist2_t;
PrintTypelist<TL::NoDuplicates<typelist1_t>::Result>();
PrintTypelist<TL::NoDuplicates<typelist2_t>::Result>();
}
void Test_Replace()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1, B2*, B2 const *, B1>::Result typelist1_t;
PrintTypelist<TL::Replace<typelist1_t, int, A1>::Result>();
PrintTypelist<TL::Replace<typelist1_t, B1, int>::Result>();
PrintTypelist<TL::Replace<typelist1_t, B2*, B2[1]>::Result>();
}
void Test_ReplaceAll()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1, B2*, B2 const *, B1>::Result typelist1_t;
PrintTypelist<TL::ReplaceAll<typelist1_t, int, A1>::Result>();
PrintTypelist<TL::ReplaceAll<typelist1_t, B1, int>::Result>();
PrintTypelist<TL::ReplaceAll<typelist1_t, B2*, B2[1]>::Result>();
}
void Test_Reverse()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2**, B1, B2*, B2 const *, B1>::Result typelist1_t;
PrintTypelist<TL::Reverse<typelist1_t>::Result>();
}
void Test_MostDerived()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2*, A2, C1, B1, B2*, B2 const *, B1>::Result typelist1_t;
printf("%s, ", typeid(TL::MostDerived<typelist1_t, A2>::Result).name());
printf("%s, ", typeid(TL::MostDerived<typelist1_t, A1>::Result).name());
printf("%s, ", typeid(TL::MostDerived<typelist1_t, B1>::Result).name());
printf("\n");
}
void Test_DerivedToFront()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2, A2, C1, B1, C2, D1, B2, A1, B1, A1>::Result typelist1_t;
typedef TL::MakeTypeList<B1, A1, C1>::Result typelist2_t;
PrintTypelist<TL::DerivedToFront<typelist1_t>::Result>();
PrintTypelist<TL::DerivedToFront<typelist2_t>::Result>();
}
void Test_DerivedToFrontAll()
{
typedef TL::MakeTypeList<IncompPtr, B1, B2, A2, C1, B1, C2, D1, B2, A1, B1, A1>::Result typelist1_t;
typedef TL::MakeTypeList<B1, A1, C1>::Result typelist2_t;
PrintTypelist<TL::DerivedToFrontAll<typelist1_t>::Result>();
PrintTypelist<TL::DerivedToFrontAll<typelist2_t>::Result>();
}
}// anon namespace
extern void Test_TypeList()
{
cout << "Testing Loki::TypeList" << endl;
Test_Length();
Test_TypeAt();
Test_TypeAtNonStrict();
Test_IndexOf();
Test_Append();
Test_Erase();
Test_EraseAll();
Test_NoDuplicates();
Test_Replace();
Test_ReplaceAll();
Test_Reverse();
Test_MostDerived();
Test_DerivedToFront();
Test_DerivedToFrontAll();
cout << endl << endl;
}

View file

@ -0,0 +1,95 @@
#if defined(_MSC_VER) && _MSC_VER >= 1300
#pragma warning (disable : 4503 4244)
#endif
// 4503: decorated name length exceeded, name was truncated
// 4244: 'argument' : conversion from '<tyep1>' to '<type2>', possible loss of data
#include <string>
#include <cassert>
#include <iostream>
#include "Variant.h"
using namespace std;
int main()
{
try
{
typedef Variant<TYPELIST_3(string, int, double)> DBField;
DBField fld1(string("Hello, world"));
DBField fld2(25);
DBField fld3(3.14);
assert(fld1.TypeId() == typeid(string));
assert(fld2.TypeId() == typeid(int));
string* p = fld1.GetPtr<string>();
assert(p != 0);
*p += '!';
assert(fld1.Get<std::string>() == "Hello, world!");
fld3 = fld1;
assert(fld1.Get<std::string>() == "Hello, world!");
assert(fld3.Get<std::string>() == "Hello, world!");
fld3 = std::string("Assignment");
assert(fld3.Get<std::string>() == "Assignment");
DBField fld5;
assert(fld5.TypeId() == typeid(string));
assert(fld5.GetPtr<string>()->empty());
DBField fld4 = fld1;
assert(fld4.TypeId() == typeid(string));
assert(fld4.Get<std::string>() == "Hello, world!");
DBField fld(45);
float f = fld.ConvertTo<float>();
assert(f == 45);
(void)f;
fld2.ChangeType<double>();
assert(fld2.Get<double>() == 25);
typedef Variant<TYPELIST_3(string, int, float)> AlternateDBField;
AlternateDBField fld6(fld1);
assert(fld6.Get<std::string>() == "Hello, world!");
fld6 = fld3;
assert(fld6.Get<std::string>() == "Assignment");
#if defined(_MSC_VER) && _MSC_VER >= 1300
//
// Variant with VC non-standard alignment support
//
typedef TYPELIST_3(string, double, int) DBField2Typelist;
typedef Variant<DBField2Typelist, VC_AlignedPOD<DBField2Typelist> > AlternateDBField2;
AlternateDBField2 fld7(fld6);
assert(fld7.Get<std::string>() == "Assignment");
fld7 = fld2;
assert(fld7.Get<double>() == 25.0);
enum {
OrigAlign = __alignof(fld1),
VCExAlign = __alignof(fld7)
};
STATIC_CHECK(OrigAlign == VCExAlign, WrongAlignment);
#endif // def _MSC_VER
}
catch (const std::exception& e)
{
cout << "Something weird happened: " << e.what();
}
catch (...)
{
cout << "Something really weird happened.";
}
}

View file

@ -0,0 +1,158 @@
#include <iostream>
#include "Visitor.h"
using namespace ::Loki;
class RasterBitmap
: public BaseVisitable<>
{
public:
DEFINE_VISITABLE()
};
class Paragraph
: public BaseVisitable<>
{
public:
DEFINE_VISITABLE()
};
class ParagraphEx
: public Paragraph
{
public:
DEFINE_VISITABLE()
};
class DummyParagraph
: public Paragraph
{
public:
DEFINE_VISITABLE()
};
class DummyRasterBitmap
: public RasterBitmap
{
public:
DEFINE_VISITABLE()
};
class SomeVisitor
: public BaseVisitor
, public Visitor<TYPELIST_3(RasterBitmap, Paragraph, ParagraphEx)>
, public BaseVisitorImpl<TYPELIST_2(DummyParagraph, DummyRasterBitmap)>
{
public:
void Visit(RasterBitmap&)
{
std::cout << "SomeVisitor::Visit(RasterBitmap&)" << '\n';
}
void Visit(Paragraph &)
{
std::cout << "SomeVisitor::Visit(Paragraph&)" << '\n';
}
void Visit(ParagraphEx &)
{
std::cout << "SomeVisitor::Visit(ParagraphEx&)" << '\n';
}
};
void Test_Visitor()
{
SomeVisitor someVisit;
BaseVisitor &baseVisit = someVisit;
RasterBitmap rast;
rast.Accept(baseVisit);
Paragraph par;
par.Accept(baseVisit);
ParagraphEx parEx;
parEx.Accept(baseVisit);
DummyRasterBitmap dummyRast;
dummyRast.Accept(baseVisit);
DummyParagraph dummyPar;
dummyPar.Accept(baseVisit);
}
typedef CyclicVisitor
<
void,
TYPELIST_3(class DocElement, class RasterBitmap2, class Paragraph2)
>
MyCyclicVisitor;
class DocElement
{
public:
virtual void Accept(MyCyclicVisitor &) = 0;
virtual ~DocElement() {}
};
class RasterBitmap2
: public DocElement
{
public:
DEFINE_CYCLIC_VISITABLE(MyCyclicVisitor)
};
class Paragraph2
: public DocElement
{
public:
DEFINE_CYCLIC_VISITABLE(MyCyclicVisitor)
};
class SomeVisitor2
: public MyCyclicVisitor
{
public:
void Visit(DocElement &)
{
std::cout << "SomeVisitor::Visit(DocElement&)" << '\n';
}
void Visit(Paragraph2 &)
{
std::cout << "SomeVisitor::Visit(Paragraph2&)" << '\n';
}
void Visit(RasterBitmap2 &)
{
std::cout << "SomeVisitor::Visit(RasterBitmap2&)" << '\n';
}
};
void Test_CyclicVisitor()
{
SomeVisitor2 someVisit;
MyCyclicVisitor &baseVisit = someVisit;
RasterBitmap2 rast;
rast.Accept(baseVisit);
Paragraph2 par;
par.Accept(baseVisit);
DocElement &docElem1 = par;
docElem1.Accept(baseVisit);
DocElement &docElem2 = rast;
docElem2.Accept(baseVisit);
}
int main()
{
Test_Visitor();
Test_CyclicVisitor();
}