From bf00a06e245aa50b09b69da0e24344782a38ace5 Mon Sep 17 00:00:00 2001 From: sauron Date: Thu, 25 Feb 2021 16:23:13 +0900 Subject: [PATCH] add ZCppMain/ZMainHead.H --- ZCppMain/ZMainHead.H | 4502 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4502 insertions(+) create mode 100644 ZCppMain/ZMainHead.H diff --git a/ZCppMain/ZMainHead.H b/ZCppMain/ZMainHead.H new file mode 100644 index 0000000..0a3422c --- /dev/null +++ b/ZCppMain/ZMainHead.H @@ -0,0 +1,4502 @@ + + +/*////////////////////////////////////////////////////////////////////////////////////// + +■ unsigned 정수형은 가급적이면 쓰지 말자. 일반적으로 많이 쓰는 signed 정수와의 호환이 + '약간' 거슬리고 있는데, 이 '약간' 이라도 왠지 찝찝하다. 2008-09-14 03:24:00 +■ 해당 namespace 에서 필요한 상수는 그 namespace 안에서 상수전용 namespace ZNsConst 를 + 만들고 그 안에 둔다. + + 해당 namespace 에서 필요한 enum 는 그 namespace 안에서 enum 전용 namespace ZNsEnum 를 + 만들고 그 안에 둔다. 해당 enum 형을 문자열로 돌려주는 함수는, 동일한 네임스페이스 안 + 에 + + const char* GetMSG_enum_data_type(int AI_Enum); + const char* GetMSG_enum_data_type(enum_data_type AE_Enum); + + 의 형태로 설계한다. + + -- + + 필요하면 ZNsEnum, ZNsConst 를 접두어로 하는 namespace 를 만들고 그 안에서 필요한 enum + 자료형이나 상수형을 정의할 수 있다. + + -- 2010-06-13 22:37:00 + +■ 해당 namespace 에서 특정 클래스에 필요한 단순히 인터페이스를 알리주는 클래스나 함수는 + 그 namespace 안에서 interface 전용 namespace ZNsInterface 를 만들고 그 안에 둔다. 멤버 + 변수가 없이 순수 interface 로만 사용되는 클래스는 'C' 가 아닌 'I' 로 시작한다. + +■ 복잡한 템플릿 인수 타입 관계를 정리하기 위해 사용하는 class 에는 ZtCType 이라는 접두어 + 를 붙이고 모두 namespace ZNsType 에 둔다. + +■ 주로 예제 용도로 작성하는 클래스는 namespace ZNsExam 에 둔다. 주로 복잡한 템플릿 인수 + 를 가지는 클래스에 대한 예제일 것이다. + +■ 복잡한 템플릿 인수 타입 관계를 정리하기 위해 Proxy 로 사용하는 class 에는 CProxy 이라 + 는 접두어를 붙이고 모두 namespace ZNsIProxy 에 둔다.(Interface Proxy) 실제 Proxy 를 구 + 현하는 클래스는 CProxy 라는 접두어를 붙이고 namespace ZNsProxy 안에 둔다. + + ZNsIProxy 와 ZNsProxy 를 다른 용도로 쓰고 있는 것이다. + +■ 특정 클래스 안에서만 사용되어 사용자가 그 존재를 알 필요가 없는 클래스는 + + namespace ZNsHide + + 에 둔다. + +■ 같은 이름의 일반 함수와 템플릿 함수가 있어면 좋은 상황에서 하는데, 함수를 일반 함수와 + 템플릿 함수로 중첩시키기가 힘들 때, 템플릿 함수를 일반함수가 속한 namespace 안에 또 + 다른 namespace ZNsTmpl 에 둔다. + + cf) std::ZNsTmpl::FindPos(); + +■ 어떤 클래스(템플릿)이 거의 같은 기능을 하지만, Decoration 패턴을 사용하는 클래스와, + 그렇지 않은 클래스가 쌍으로 존재할 때, Decoration 패턴을 사용하는 클래스는 주로 + + namespace ZNsDeco + + 에 둔다. Decoration 패턴은 Logic 과 View 구조에서, View 에 해당하는 클래스를, Logic + 클래스 의 생성자에서 (주로) 참조로 전달받는 경우를 말한다. + +■ 클래스 템플릿 설계할 때 핵심 기능만 구현하고 나머지 부분은 기초클래스나 상속클래스, + 혹은 멤버가 되는 클래스로 설계할 수 있는데, 이 클래스들의 이름에 적절한 이름을 붙이기 + 어려운 경우에는 CHelp~ 로 시작하는 이름으로 하자. 이외에도 Business Logic 과 View 의 + 분리라는 뜻에서 CView~ 도 생각할 수 있다. + + cf) class CHelpIOCP + +■ template 으로 어떤 main class 를 디자인할 때 다른 class template 을 인수로 받는 경우 + 가 있겠고 이때 클래스 템플릿 인수의 instance 의 멤버를 셋팅하려면 그 template 의 모든 + 멤버에 대하여 public 권한을 갖게 되는 경우가 많을 것이다. 이때는 셋팅 권한을 갖는 멤 + 버를 외부 기초 클래스 template 으로 만들고(따라서 main class 는 이 기초클래스를 상속 + 한다.) 이 class 에서 friend 지정을 하면 될 것이다. 그런데 main class 도 템플릿일 것으 + 므로 기초 클래스가 정의되기 전에는 정의될 수 없다는 문제가 있다. 이 문제를 피하기 위 + 해 main class 를 상속하는 비템플릿 클래스를 선언하고 (정의는 나중으로 미루고 전방선언 + 만 한다.) 기초 클래스에서 이 클래스에 friend 지정을 하면 될 것이다. + + 아니면 public 이 아니어야 할 멤버 함수가 템플릿 설계로 인해 어쩔 수 없이 public 으로 + 해야 할때 No Public 을 의미하는 macro _NP_ 를 그 함수 선언과 정의 앞에 붙여주자 + +■ 함수가 어떤 조건에서 실행을 중지할 때, bool 값으로 표시해도 되지만 가독성을 위해서 + + enum std::ZNsEnum::ERun + + 을 사용하자. + +■ 함수가 굳이 어떤 값을 리턴할 필요는 없는데, 함수의 역할이 특정 조건인지 체크해서 그 + 조건에 맞으면 어떤 작업을 실행한다고 할 때, 이 실행여부를 굳이 리턴하고자 한다면 bool + 형 대신에, 가독성을 위해서 enum std::ZNsEnum::EAct 을 사용하자. + +■ call back 함수나 이떤 이벤트마다 실행하는 함수는 접두어 'On' 을 붙이자. 어떤 컨테이너 + 의 각 원소마다 특정한 처리를 하는 함수에는 'Iter' 를 붙이자. + + cf) CDoubleList::IterElement(); + + 'Iter' 대신에 'OnEach' 를 붙여도 좋을 것 같다. + +■ 클래스의 초기와, 종료함수를 별도로 지정할 때에는 각각 접두어 Init, Fini 뒤에 적절한 + 이름을 붙여주자. 클래스의 초기와, 종료함수를 Init, Fini 로만 지정했더니, 나중에는 비 + 슷비슷한 이름이 많아서 상속할 때 상당히 햇깔렸다. + + 클래스의 멤버중에 단순히 멤버를 0 과 같은 초기값으로 셋팅하는 함수는 InitVar 라는 함 + 수명을 사용하자. + +■ containter class template 는 TypeData 라는 type 을 가져야 한다. 예를 들어 + + CObjList::TypeData + + 라는 접근이 가능해야 한다. 이 표기에서 int 가 TypeData 라는 것은 분명히 알 수 있으나 + containter 형을 인수로 받는 템플릿에서, 그 템플릿이 어떤 자료형 (예에서는 int)에 대한 + containter 인지 모르게 된다. 이것을 해결하기 위한 (템플릿을 편리하게 하기 위한)규칙이 + 다. + + 이외에도 컨테이너의 컨테이너와 같은 복잡한 컨테이너 type 을 템플릿 인수로 여러 개 갖 + 는 컨테이너에서 TypeData 외에 추가적인 정의를 할 수 있겠다. 이런 type 이 이름은 Type + 으로 시작하는 것으로 하자. + + cf) IN ZNsCPP::CStringSerial_T<> + + typedef TTypeCh TypeData ; + typedef TStringType TypeCStringData ; + typedef TStringList TypeCStringList ; + + ※ 그런데 꼭 container class template 가 아니라 할지라도 class template 은 내부적으 + 로 대표 자료형 TypeData 형을 갖도록 하는 것이 좋을 것 같다. 2008-11-05 13:22:00 + + ※ TString 에 외부 접근 형 정의를 한다면 TypeCString 이 아니라 TypeString 으로 하는 + 것이 좀 예쁜(?) 것 같다. + + typedef TString TypeCString; + typedef TString TypeString ; + + 2 번 줄 코드가 좋 낳아 보이지 않을까. 2008-11-05 13:42:00 + +■ template 함수나 클래스에서 functor 인수는 참조로 선언하지 않는다. 아래 참고, + + InputIterator& first, InputIterator& last + + 이라고 하지 않았다. 단순 함수나 크기가 작은 object 일 경우 느려질 수 있기 때문이다. + 단 아래 for_each 예에서 InputIterator 가 클래스일 경우 복사 생성자를 꼭 가져야 한다. + + template + Function for_each(InputIterator first, InputIterator last, Function f) + { + while ( first!=last ) f(*first++); + return f; + } + +■ WINDOW 에서 UNICODE 로 컴파일할 경우 아래 3 개의 매크로를 추가할 것. + + #define _MBCS + #define _UNICODE + #define UNICODE + +■ 구 버전의 컴파일러에서 RTTI 옵션이 꺼져 있으면 헤더파일 typeinfo 을 사용할 수 없다. + + +■ breakpoint assembly + + _asm + { + int 3; + } + +■ 리눅스 core file 무제한 명령 + + ulimit -c unlimited + system("ulimit -c unlimited"); + +■ Visual C++ 2008 에 추가된 함수를 사용할려면 아래 매크로를 정의한다. + + #define _WIN32_WINNT 0x0600 + + -- 2010-04-22 19:55:00 + +■ _REENTRANT_EX 매크로를 정의하면 _REENTRANT 보다 좀더 최적화된 thread-safe 함수를 + 사용하거나, 약간 실험적인 thread-safe 함수를 사용한다. + + -- 2011-03-13 01:04:00 + +//////////////////////////////////////////////////////////////////////////////////////*/ + + +#ifndef __MAINHEADER_H__ +#define __MAINHEADER_H__ + + +#include +#include +#include +#include +#include +#include +#include + + +#define _CODE_OLD_ 0 +#define _CODE_BAD_ 0 +#define _CODE_NEW_ 1 + +/*///////////////////////////////////////////////////////////////// + +■ 위 매크로 _CODE_OLD_ 와 _CODE_NEW_ 등은 #if(0) 이나 #if(1) 등으 + 로 폐기되거나 추가된 코드를 나타냈던 것을 좀 더 직관적으로 표현 + 한다. + + -- 2013-07-28 16:21:00 + +/////////////////////////////////////////////////////////////////*/ + + +#define _COMMENT_ 0 // 주석으로 사용하는 부분. + + +#if defined(_WIN32) || defined(_WIN64) || defined(_WIN128) || \ + defined( WIN32) || defined( WIN64) || defined( WIN128) + + #ifndef _WIN + #define _WIN + #endif + +#endif/* + defined(_WIN32) || defined(_WIN64) || defined(_WIN128) || \ + defined( WIN32) || defined( WIN64) || defined( WIN128) */ + + +#if defined(_WIN64) || defined( WIN64) + #ifndef __CPU_BIT_CNT__ + #define __CPU_BIT_CNT__ 64 + #endif +#endif /*defined(_WIN64) || defined( WIN64) */ + +#if defined(_WIN128) || defined( WIN128) + #ifndef __CPU_BIT_CNT__ + #define __CPU_BIT_CNT__ 128 + #endif +#endif /*defined(_WIN128) || defined(WIN128) */ + + +#if defined(_WIN) + + typedef signed char int8_t ; + typedef unsigned char uint8_t ; + + typedef signed short int16_t; + typedef unsigned short uint16_t; + + typedef signed int int32_t; + typedef unsigned int uint32_t; + + typedef signed __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #ifndef __VISUAL_CPP_VER__ + #define __VISUAL_CPP_VER__ 200800 // 끝 2 자리는 소수점 버전 + #endif//__VISUAL_CPP_VER__ + +#elif defined(__mips__) + + typedef signed char int8_t ; + typedef unsigned char uint8_t ; + + typedef signed short int16_t; + typedef unsigned short uint16_t; + + typedef signed int int32_t; + typedef unsigned int uint32_t; + + typedef signed long long int64_t; + typedef unsigned long long uint64_t; + +#else + #include +#endif + + +#if defined(_WIN) + #define _STRUCT_PACK_ + #ifndef __STD_CALL__ + #define __STD_CALL__ __stdcall + #endif +#elif defined(__unix__) + #define _STRUCT_PACK_ __attribute__((packed)) + #ifndef __STD_CALL__ + #define __STD_CALL__ + #endif +#elif defined(__linux__) + #define _STRUCT_PACK_ __attribute__((packed)) + #ifndef __STD_CALL__ + #define __STD_CALL__ + #endif +#else + #define _STRUCT_PACK_ __attribute__((packed)) + #ifndef __STD_CALL__ + #define __STD_CALL__ + #endif +#endif + +#ifdef _REENTRANT_EX + #ifndef _REENTRANT + #define _REENTRANT + #endif +#endif + +#if defined(_REENTRANT) + #ifndef _REENTRANT_MUTEX + #define _REENTRANT_MUTEX + #endif //_REENTRANT_MUTEX + #define _REENTRANT_BOOL_ 1 +#else + #define _REENTRANT_BOOL_ 0 +#endif //_REENTRANT + + +#ifdef _WIN + + #pragma warning(disable:4503) + #pragma warning(disable:4786) + #pragma warning(disable:4996) + #pragma warning(disable:4244) + #pragma warning(disable:4267) + #pragma warning(disable:4018) + #pragma warning(disable:4312) + #pragma warning(disable:4290) + #pragma warning(disable:4076) + + /*///////////////////////////////////////////////////////////////////////////// + + ■ 4290 경고 : 함수 선언에 throw 가 있다. + + warning C4290: 함수가 __declspec(nothrow)가 아님을 나타내려는 경우를 제외하고 C++ 예외 사양은 무시됩니다. + warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow) + + -- 2013-07-08 02:39:00 + + ■ 4076 경고 : wchar_t 에 unsigned 를 지정했다. 리눅스에서는 어떤 경고도 없다. + + warning C4076: 'unsigned' : can not be used with type 'wchar_t' + + -- 2013-07-08 02:45:00 + + /////////////////////////////////////////////////////////////////////////////*/ + + + /*///////////////////////////////////////////////////////////////////////////// + + ■ WinSock2.h 파일이 include 되기 전에, windows.h 파일이 include 돼서는 안된다. + WinSock2.h 이 필요하면, 이 파일 MainHeader 보다 먼저 include 해야 한다. + + ■ TCHAR.H 파일을 include 하고 _MBCS 와 _UNICODE 가 정의되어 있으면 + TCHAR 이 wchar_t 으로 정의되어야 하나, VC++ 6.0 에서는 자꾸 char 로 정의된다. + + -- 2006-10-12 09:53:00 + + /////////////////////////////////////////////////////////////////////////////*/ + + #include + #include + #include + + // 아래 pragma 코드가 이미 CNet_Win.H 에 있는데, 필요하면 아래 주석을 제거한다. + // + // #pragma comment(lib, "ws2_32") + + + #ifndef _T + #define _T(X) X + #endif + + + #if defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__<200000 + + // VC++ 6.0 에서는 아래 선언이 필요. + // VC++ 7.0 부터는 주석처리 할 것. + + typedef unsigned long ULONG_PTR ; + typedef unsigned long* PULONG_PTR; + + #endif //defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__<200000 + +#else // !defined(_WIN) + + #include + + #if defined(UNICODE) || defined(_UNICODE) + #define LPCTSTR const wchar_t* + #else + #define LPCTSTR const char* + #endif + + #ifndef _T + #define _T(X) X + #endif + + #define LONG long + +#endif // !defined(_WIN) + + +#if defined(_REENTRANT) + + #if defined(__linux__) + + // 리눅스 Multi Thread Programming 에서 + // CDoubleList 라든가 여러 자료구조에서 쓰는 + // 동기화 뮤텍스를 위해 pthread.h 를 포함한다. + + #include + + #elif defined(__unix__) + #include + #elif defined(__sun__) // In Solaris + #include + #elif defined(_WIN) + //Don't inclucde + #else + #include + #endif + +#endif //defined(_REENTRANT) + + +#ifdef _DEBUG + #include + #include + #include +#endif + + +using namespace std; + + +#define RR(RefReceive) RefReceive + + // RR 메크로는 인수가 참조를 전달하고 다시 어떤 값으로 설정받는다는 것을 뜻함 + + +#define _NP_ + + /* 템플릿의 멤버함수가 원래는 public 가 아니어야 하지만, + 템플릿 설계상 어쩔 수 없이 public 으로 했음을 의미. No Public */ + + +#define _VT_ + + // _VT_ 메크로는 주로 상속해서 사용하는 멤버함수를 의미 + + +#define _SY_ + + /* 동기화(Sync) 영역에서 호출되는 함수를 의미. 따라서 이 함수안에서 + 같은 동기화 object 를 사용하는 함수를 호출하지 않도록 주의한다. */ + +#define _BETA_ + + /* beta 테스트 중이거나, 실제로 사용하기에는 기술적인 문제가 + 잠재해 있는 함수를 의미. (2011-04-03 21:37:00) */ + + +#ifdef __CYGWIN__ + #define atoll atol /*for Cygwin*/ +#endif + + +#define __for0(IntType, i, LoopCount) for(IntType i=0; i< LoopCount; ++i) +#define __for1(IntType, i, LoopCount) for(IntType i=1; i<=LoopCount; ++i) + +#define __forD0(i, LoopCount) for(i=0; i< LoopCount; ++i) // 정수형 선언이 미리 있는 경우. D 는 Declare. +#define __forD1(i, LoopCount) for(i=1; i<=LoopCount; ++i) + + +namespace ZNsMain +{ + + typedef int ZTypInt ; + typedef int ZTypIntE ; // int enum : 다른 enum 형끼리 비교할 일이 있을 때, 이 자료로 형변환한다. + typedef IntE ZTypIntEnum ; + typedef long ZTypIntLong ; + typedef short ZTypIntShort; + + typedef int ZTypIntI ; // 정수를 가장 잘 대표할 수 있는 자료형. 필요에 따라 long 이나 short 으로 typedef 할 수도 있다. + typedef long ZTypIntL ; + typedef short ZTypIntS ; + + typedef int8_t ZTypInt8 ; + typedef int16_t ZTypInt16 ; + typedef int32_t ZTypInt32 ; + typedef int64_t ZTypInt64 ; + + typedef uint8_t ZTypUInt8 ; + typedef uint16_t ZTypUInt16 ; + typedef uint32_t ZTypUInt32 ; + typedef uint64_t ZTypUInt64 ; + + typedef uint8_t ZTypIntU8 ; + typedef uint16_t ZTypIntU16 ; + typedef uint32_t ZTypIntU32 ; + typedef uint64_t ZTypIntU64 ; + + #if defined(UNICODE) || defined(_UNICODE) + + typedef wchar_t ZTypXCHAR ; + typedef wchar_t ZTypXChar ; + + typedef wchar_t* ZTypXPChar ; + typedef const wchar_t* ZTypXCPChar ; + #else + + typedef char ZTypXCHAR ; + typedef char ZTypXChar ; + + typedef char* ZTypXPChar ; + typedef const char* ZTypXCPChar ; + #endif + + + typedef char ZTypChar ; + typedef wchar_t ZTypCharW ; + + typedef const char ZTypCChar ; + typedef const wchar_t ZTypCCharW ; + + typedef char* ZTypPChar ; + typedef const char* ZTypCPChar ; + typedef char* const ZTypPCChar ; + typedef const char* const ZTypCPCChar ; + + typedef char* ZTypPCh ; + typedef const char* ZTypCPCh ; + typedef char* const ZTypPCCh ; + typedef const char* const ZTypCPCCh ; + + typedef wchar_t* ZTypPWChar ; + typedef const wchar_t* ZTypCPWChar ; + typedef wchar_t* const ZTypPWCChar ; + typedef const wchar_t* const ZTypCPCWChar; + + typedef wchar_t* ZTypPWCh ; + typedef const wchar_t* ZTypCPWCh ; + typedef wchar_t* const ZTypPWCCh ; + typedef const wchar_t* const ZTypCPCWCh ; + + typedef unsigned char ZTypUChar ; + + #if(0) + + typedef unsigned wchar_t ZTypUWChar ; + /* VC++ 2012 에서는 여기서 4076 번 경고가 발생한다. + + warning C4076: 'unsigned' : can not be used with type 'wchar_t' + + Linux g++ 4.4.7 에서는 unsigned wchar_t 를 잘 인식하고 있다. + + */ + #endif + + typedef unsigned int ZTypUInt ; + typedef unsigned short ZTypUShort ; + typedef unsigned long ZTypULong ; + + typedef unsigned char ZTypIntUChar ; + typedef unsigned int ZTypIntUInt ; + typedef unsigned short ZTypIntUShort ; + typedef unsigned long ZTypIntULong ; + + typedef unsigned char ZTypIntUC ; + typedef unsigned int ZTypIntUI ; + typedef unsigned short ZTypIntUS ; + typedef unsigned long ZTypIntUL ; + +#if(defined(__CPU_BIT_CNT__) && __CPU_BIT_CNT__>=64) + #ifdef _WIN + typedef __int64 ZTypLLength ; // 문자열의 길이를 나타내는 자료형. + // 송수신 버퍼의 크기 자료형으로도 쓰인다. + #else + typedef long ZTypLLength ; + #endif +#else // !defined(__CPU_BIT_CNT__) || __CPU_BIT_CNT__<64 + + typedef long ZTypLLength ; + +#endif // !defined(__CPU_BIT_CNT__) || __CPU_BIT_CNT__<64 + +#ifdef _WIN + typedef __int64 ZTypLLengthFile ; // 파일의 크기를 나타내는 자료형. +#else + typedef long ZTypLLengthFile ; // 파일의 크기를 나타내는 자료형. +#endif + + typedef ZTypLLengthFile ZTypLLengthF; + + + #ifdef _WIN + typedef __int64 ZTypLongLong ; + typedef unsigned __int64 ZTypULongLong; + + typedef __int64 ZTypIntLLong ; + typedef unsigned __int64 ZTypIntULLong; + #else + typedef long long ZTypLongLong ; + typedef unsigned long long ZTypULongLong; + + typedef long long ZTypIntLLong ; + typedef unsigned long long ZTypIntULLong; + #endif + + + typedef ZTypLongLong ZTypLLong ; + typedef ZTypULongLong ZTypULLong; + + typedef ZTypLongLong ZTypIntLL ; + typedef ZTypULongLong ZTypIntULL; + + + #ifdef _WIN64 + typedef __int64 ZTypIntPtr ; // 포인터를 표현하는 정수 크기다. + typedef unsigned __int64 ZTypIntUPtr; // 포인터를 표현하는 양의 정수 크기다. + #else + typedef long ZTypIntPtr ; + typedef unsigned long ZTypIntUPtr; + #endif + + + #ifdef _WIN32 + typedef HANDLE ZTypeID; + #else + typedef int ZTypeID; + #endif + + + typedef class ZCIterEasy{} ZTyIterEasy, *ZTyIterEasyID ; + typedef const ZTyIterEasyID* ZTyIterEasyIDc; + + /*/////////////////////////////////////////////////////////////////////////////// + + ■ typedef class CIterEasy{} *IterEasyID + + CObjList<> 등에서 사용하는 반복자로 사용하는 자료형이다. 반복자를 사용할 때마 + 다, typedef typename std::CObjList<>::IterEasy IterEasy 등으로 길게 선언해야 + 하는 것이 성가셨다. + + -- 2013-06-02 08:44:00 + + CObjList.H 등에서 관련 멤버 함수를 추가하고, CHttp.H 와 CHttp2.H 의 기존 ZCLink + 를 사용하는 코드를 IterEasyID 을 사용하는 코드로 적절히 반영한 결과, 숨어 있던 + 버그를 발견하고 조치한 듯한, 맑은 기분을 느낄 수 있었다. + + -- 2013-06-02 12:13:00 + + CStringEx.H 파일에도 반영했다. -- 2013-06-02 09:59:00 + + ■ IterEasyIDc 선언을 + + typedef const IterEasyID IterEasyIDc; + + 라 하면, 천만 뜻밖에도 IterEasyIDc 의 type 이름(type().nmae() 으로 구한 값)이 + IterEasyID 의 type 이름 값과 같다. + + -- 2015-11-07 21:34:00 + + ///////////////////////////////////////////////////////////////////////////////*/ + + + class ZCEmpty + { + /*/////////////////////////////////////////////////////////////////////////// + + ■ 템플릿 정의에서 비어있는 클래스를 요구하는 경우가 있다. + + ■ 또한 여러 개의 템플릿 인자를 가진 클래스 템플릿의 특정 인자에 대하여 부분 + 특수화를 하는 경우, 부분 특수화 되는 인수의 type 을, 특수화되지 않는 최초 + 의 템플릿 정의 부분에서 무엇으로 할 지 고민되는 경우가 있다면, 이때 고민 + 하지 말고 ZCEmpty 를 써버리자. + + -- 2010-05-04 02:29:00 + + 어, 근데 템플릿 인자에 void 를 사용할 수도 있다. 이것을 다소 늦게 알았는데, + 그래도 비어 있는 클래스를 상속할 경우, 커파일러가 크기를 0 으로 해놓는 장점 + 이 있으니까 일단 그냥 둔다. 만약 void 를 사용하게 되면, void 를 템플릿 인자 + 로 사용하는 버전과 사용하지 않는 버전으로 항상 정의를 해주어야 하는 성가신 + 점이 있다. + + -- 2012-09-01 17:26:00 + + ///////////////////////////////////////////////////////////////////////////*/ + };/* + class ZCEmpty*/ + + + namespace ZNsInterface + { + // 이 이름공간안에 interface 가 되는 class (템플릿) 가 온다. + }/* + namespace ZNsInterface*/ + + namespace ZNsIFace + { + // 이름공간 ZNsInterface 을 짧게 ZNsIFace 으로도 표기 가능하게 한다. + + using namespace ZNsInterface; + }/* + namespace ZNsIFace*/ + + namespace ZNsEnum + { + + // ECompareResult 는 어떤 두 개의 값을 비교한 결과를 표시한다. + // GetCompareCode() 나 class ZZtCCompare<> 에서 사용할 것이다. + + enum ECompareResult + { + ECompareResult_Equal= 0, // 서로 같다. + ECompareResult_More = 1, // 왼쪽이 크다. + ECompareResult_Less =-1 // 오른쪽이 크다. + };/* + enum ECompareResult*/ + + }/* + namespace ZNsEnum*/ + + + template int GetCompareCode( + const TTypeChar* ApcLeft , TTypeLength AI_LeftLength , + const TTypeChar* ApcRight, TTypeLength AI_RightLength + ) /*################################################################*/ + { + if(AI_LeftLength<1 && AI_RightLength<1) return ZNsEnum::ECompareResult_Equal; + + TTypeLength ViLoopCnt= (AI_LeftLength<=AI_RightLength ? AI_LeftLength : AI_RightLength); + + __for0(TTypeLength, i, ViLoopCnt) + { + if(ApcLeft[i] > ApcRight[i]) return ZNsEnum::ECompareResult_More; + if(ApcLeft[i] < ApcRight[i]) return ZNsEnum::ECompareResult_Less; + }/* + __for0(TTypeLength, i, ViLoopCnt)*/ + + if(AI_LeftLength==AI_RightLength) return ZNsEnum::ECompareResult_Equal; + if(AI_LeftLength> AI_RightLength) return ZNsEnum::ECompareResult_More ; + if(AI_LeftLength< AI_RightLength) return ZNsEnum::ECompareResult_Less ; + + return ZNsEnum::ECompareResult_Equal; + }/* + template int GetCompareCode( + const TTypeChar* ApcLeft , TTypeLength AI_LeftLength, + const TTypeChar* ApcRight, TTypeLength AI_RightLength + ) ##################################################################*/ + + + namespace ZNsType + { + + /*///////////////////////////////////////////////////////////////////////////////////////// + + ■ (주로 클래스) 템플릿에는 typename 인수를 10 개 이상 요구하는 복잡한 템플릿이 있는데 이런 + 템플릿의 typename 을 미리 예를 들어 명시함으로서 그 템플릿의 typename 을 지정하기 쉽도록 + 가이드라인을 제시하는 역할의 어떤 클래스나 데이타 타입이 올 수 있는데 이런 자료형이 이 + 이름공간에 온다. 어떤 데이타타입을 주로 typedef 하는 클래스라면 접두어 ZtCType 를 붙인다. + + ■ ZtCTypeCRTP_T<> 는 어떤 클래스 템플릿이 CRTP(CURIOUSLY RECURRING TEMPLATE PATTERN) 를 사용 + 하는지 아닌지를 알려준다. ZtCTypeCRTP_T<> 을 설계하지 않는다면, 같은 기능을 하기 위해, 클 + 래스를 2 개(CRTP 를 사용하는 클래스와, 그렇지 않은 클래스)를 만들어야 했을 것이다. + + -- 2010-03-12 20:00:00 + + ■ 또한 이 이름공간에 있는 클래스는 TypeData 라는 자료형을 갖는 것으로 하자. + + -- 2011-10-18 21:51:00 + + /////////////////////////////////////////////////////////////////////////////////////////*/ + + + template< typename TTypeChild=ZCEmpty, bool TTypebUseCRTP =false + > + class ZtCTypeCRTP_T ////////////////////////////////////////////// + { + public: + typedef TTypeChild TypeData; + public: + enum{EUseCRTP=(int)TTypebUseCRTP}; + public: + };/* + template< typename TTypeChild=ZCEmpty, bool TTypebUseCRTP =false + > + class ZtCTypeCRTP_T ////////////////////////////////////////////*/ + + + template< typename TTypeChild =ZCEmpty + , typename TTypeBase =ZCEmpty + , bool TTypebUseCRTP=false + > + class ZtCTypeCRTP2_T ///////////////////// + { + public: + typedef TTypeChild TypeData; + typedef TTypeBase TypeBase; + public: + enum{EUseCRTP=(int)TTypebUseCRTP}; + public: + }; /* + template< typename TTypeChild =ZCEmpty + , typename TTypeBase =ZCEmpty + , bool TTypebUseCRTP=false + > + class ZtCTypeCRTP_T2 ///////////////////*/ + + /*////////////////////////////////////////////////////////////////////////////////////////// + + ■ class ZtCTypeCRTP_T2<> 이 왜 필요한지, 그리고 사용례는 CWorkPool.H 의 + '주석-CCtrlAllocWork::CRTP2'를 참고한다. + + -- 2012-09-20 09:46:00 + + //////////////////////////////////////////////////////////////////////////////////////////*/ + + + /*///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + ■ class ZtCTypeCRTP_T<> 이 단점은 상속하지 않은 class 형은 알 수 없는데, 이것을 알아내기 위해 + + class ZtCTypeNowCRTP<> + + 을 설계한다. 이 클래스의 사용예는 CCtrlAsyncSock.H 에 있다. + + typedef typename TAsyncServ::ZtCTypeCRTP ZtCTypeCRTP ; + typedef typename ZtCTypeCRTP ::TypeData CMainServ0; + + typedef std::ZNsType::ZtCTypeNowCRTP< + TAsyncServ, CMainServ0>::TypeData CMainServ ; + + CMainServ& VR_CMainServ= + static_cast(ArCAsyncServ); + + ZtCTypeNowCRTP<> 이 없었을 때에는 TAsyncServ 이 상속 클래스를 갖지 않은 경우, CMainServ0 이 ZCEmpty 가 되어서, + 컴파일 에러를 피하기가 매우 복잡한 경우가 있었다. 지금은 상속 클래스가 없다면 그냥 자기 자신의 인터페이스를 + 사용하니까 컴파일 에러가 전혀 없다. + + 정말 멋진 기교가 아닌가. C++ 의 향기에 잠시 취해 보자. -- 2013-06-10 00:33:00 + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template class ZtCTypeNowCRTP + { public: typedef TTypeChild TypeData; public: enum{EUseCRTP=1}; }; + template class ZtCTypeNowCRTP + { public: typedef TTypeNow TypeData; public: enum{EUseCRTP=0}; }; + template class ZtCTypeNowCRTP + { public: typedef TTypeNow TypeData; public: enum{EUseCRTP=0}; }; + + + namespace ZNsTmplParam + { + /*////////////////////////////////////////////////////////////////////////// + + ■ 이 이름 공간에는 어떤 템플릿의 인수가 많고, 이 인수가 몇 개의 인수가 기본 + 값을 갖는 경우, 끝 부분에 있는 기본값 정의 인수에 명시적인 자료형을 지정 + 해야 할 때, 그 이전의 기본 인수에 대해서도 일일이 지정을 해야 하는데, 이 + 런 불편을 일부 덜기 위해서 기본값 정의 순서가 다른 template 을 설계한다. + 여기에 놓이는 클래스는 CParam~ 으로 시작하자. + + ■ ZNsTmplParam 이름공간은 꼭 ZNsType 에만 있을 필요는 없다. 그보다 더 적절한 + 장소가 있다면 그 곳에 선언하자. + + //////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsTmplParam*/ + + + /*////////////////////////////////////////////////////////////////////////////// + + ■ class ZtCTypeArguBind 은 class ZtCArguBind 에서 사용된다. + + class ZtCTypeArguBind 와 class ZtCArguBind 의 사용예는 CArguBind_test.cpp 에 + 있다. + + ZtCArguBind 은 boost 의 bind 를 흉내낸 것인데, 용법은 좀 다르다. + + -- 2014-07-05 18:49:00 + + //////////////////////////////////////////////////////////////////////////////*/ + + + template< typename TTypeArgu1 , typename TTypeArgu2 + , typename TTypeArgu3=ZCEmpty, typename TTypeArgu4 =ZCEmpty + , typename TTypeArgu5=ZCEmpty, typename TTypeArgu6 =ZCEmpty + , typename TTypeArgu7=ZCEmpty, typename TTypeArgu8 =ZCEmpty + , typename TTypeArgu9=ZCEmpty, typename TTypeArgu10=ZCEmpty + > + class ZtCTypeArguBind /////////////////////////////////////////////// + { + public: + + typedef TTypeArgu1 TypeArgu1 ; typedef TTypeArgu2 TypeArgu2 ; + typedef TTypeArgu3 TypeArgu3 ; typedef TTypeArgu4 TypeArgu4 ; + typedef TTypeArgu5 TypeArgu5 ; typedef TTypeArgu6 TypeArgu6 ; + typedef TTypeArgu7 TypeArgu7 ; typedef TTypeArgu8 TypeArgu8 ; + typedef TTypeArgu9 TypeArgu9 ; typedef TTypeArgu10 TypeArgu10; + + struct ZStArguments2{ ZStArguments2( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2): + _1(AR_TypeArgu1), _2(AR_TypeArgu2){} + + TypeArgu1& _1; TypeArgu2& _2; + };/* + struct ZStArguments2*/ + struct ZStArguments3{ZStArguments3( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; + };/* + struct ZStArguments3*/ + struct ZStArguments4{ZStArguments4( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; + };/* + struct ZStArguments4*/ + struct ZStArguments5{ZStArguments5( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; + };/* + struct ZStArguments5*/ + struct ZStArguments6{ZStArguments6( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5, TypeArgu6& AR_TypeArgu6): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5), _6(AR_TypeArgu6){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; TypeArgu6& _6; + };/* + struct ZStArguments6*/ + struct ZStArguments7{ZStArguments7( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5, TypeArgu6& AR_TypeArgu6, TypeArgu7& AR_TypeArgu7): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5), _6(AR_TypeArgu6), _7(AR_TypeArgu7){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; TypeArgu6& _6; TypeArgu7& _7; + };/* + struct ZStArguments7*/ + struct ZStArguments8{ZStArguments8( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5, TypeArgu6& AR_TypeArgu6, TypeArgu7& AR_TypeArgu7, TypeArgu8& AR_TypeArgu8): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5), _6(AR_TypeArgu6), _7(AR_TypeArgu7), _8(AR_TypeArgu8){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; TypeArgu6& _6; TypeArgu7& _7; TypeArgu8& _8; + };/* + struct ZStArguments8*/ + struct ZStArguments9{ZStArguments9( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5, TypeArgu6& AR_TypeArgu6, TypeArgu7& AR_TypeArgu7, TypeArgu8& AR_TypeArgu8, TypeArgu9& AR_TypeArgu9): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5), _6(AR_TypeArgu6), _7(AR_TypeArgu7), _8(AR_TypeArgu8), _9(AR_TypeArgu9){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; TypeArgu6& _6; TypeArgu7& _7; TypeArgu8& _8; TypeArgu9& _9; + };/* + struct ZStArguments9*/ + struct ZStArguments10{ZStArguments10( + TypeArgu1& AR_TypeArgu1, TypeArgu2& AR_TypeArgu2, TypeArgu3& AR_TypeArgu3, TypeArgu4& AR_TypeArgu4, TypeArgu5& AR_TypeArgu5, TypeArgu6& AR_TypeArgu6, TypeArgu7& AR_TypeArgu7, TypeArgu8& AR_TypeArgu8, TypeArgu9& AR_TypeArgu9, TypeArgu10& AR_TypeArgu10): + _1(AR_TypeArgu1), _2(AR_TypeArgu2), _3(AR_TypeArgu3), _4(AR_TypeArgu4), _5(AR_TypeArgu5), _6(AR_TypeArgu6), _7(AR_TypeArgu7), _8(AR_TypeArgu8), _9(AR_TypeArgu9), _10(AR_TypeArgu10){} + + TypeArgu1& _1; TypeArgu2& _2; TypeArgu3& _3; TypeArgu4& _4; TypeArgu5& _5; TypeArgu6& _6; TypeArgu7& _7; TypeArgu8& _8; TypeArgu9& _9; TypeArgu10& _10; + };/* + struct ZStArguments10*/ + + public: + };/* + template< typename TTypeArgu1 , typename TTypeArgu2 + , typename TTypeArgu3=ZCEmpty, typename TTypeArgu4 =ZCEmpty + , typename TTypeArgu5=ZCEmpty, typename TTypeArgu6 =ZCEmpty + , typename TTypeArgu7=ZCEmpty, typename TTypeArgu8 =ZCEmpty + , typename TTypeArgu9=ZCEmpty, typename TTypeArgu10=ZCEmpty + > + class ZtCTypeArguBind /////////////////////////////////////////////*/ + + }/* + namespace ZNsType*/ + + + template class ZtCArguBind + { + public: + + template + static void Exec2(Type1& AR_Type1, Type2& AR_Type2) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments2 VO_ZtCTypeArguBind(AR_Type1, AR_Type2); + + TClassExec::Exec2(VO_ZtCTypeArguBind); + }/* + template + static void Exec2(Type1& AR_Type1, Type2& AR_Type2)*/ + + template + static void Exec2(Type1& AR_Type1, Type2& AR_Type2, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments2 VO_ZtCTypeArguBind(AR_Type1, AR_Type2); + + TClassExec::Exec2(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec2(Type1& AR_Type1, Type2& AR_Type2, THelpType& ArHelpType)*/ + + + template + static void Exec3(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments3 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3); + + TClassExec::Exec3(VO_ZtCTypeArguBind); + }/* + template + static void Exec3(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3)*/ + + template + static void Exec3(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments3 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3); + + TClassExec::Exec4(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec3(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, THelpType& ArHelpType)*/ + + + template + static void Exec4(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments4 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4); + + TClassExec::Exec4(VO_ZtCTypeArguBind); + }/* + template + static void Exec4(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4)*/ + + template + static void Exec4(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments4 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4); + + TClassExec::Exec4(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec4(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, THelpType& ArHelpType)*/ + + + template + static void Exec5(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments5 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5); + + TClassExec::Exec5(VO_ZtCTypeArguBind); + }/* + template + static void Exec5(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5)*/ + + template + static void Exec5(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments5 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5); + + TClassExec::Exec5(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec5(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, THelpType& ArHelpType)*/ + + + template + static void Exec6(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments6 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6); + + TClassExec::Exec6(VO_ZtCTypeArguBind); + }/* + template + static void Exec6(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6)*/ + + template + static void Exec6(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments6 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6); + + TClassExec::Exec6(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec6(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, THelpType& ArHelpType)*/ + + + template + static void Exec7(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments7 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type6, AR_Type7); + + TClassExec::Exec7(VO_ZtCTypeArguBind); + }/* + template + static void Exec7(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7)*/ + + template + static void Exec7(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments7 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type7); + + TClassExec::Exec7(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec7(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7 THelpType& ArHelpType)*/ + + + template + static void Exec8(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments8 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type6, AR_Type7, AR_Type8); + + TClassExec::Exec8(VO_ZtCTypeArguBind); + }/* + template + static void Exec8(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8)*/ + + template + static void Exec8(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments8 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type7, AR_Type8); + + TClassExec::Exec8(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec8(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, THelpType& ArHelpType)*/ + + + template + static void Exec9(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments9 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type6, AR_Type7, AR_Type8, AR_Type9); + + TClassExec::Exec9(VO_ZtCTypeArguBind); + }/* + template + static void Exec9(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9)*/ + + template + static void Exec9(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments9 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type7, AR_Type8, AR_Type9); + + TClassExec::Exec9(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec9(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, THelpType& ArHelpType)*/ + + + template + static void Exec10(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, Type10& AR_Type10) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments10 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type6, AR_Type7, AR_Type8, AR_Type9, AR_Type10); + + TClassExec::Exec10(VO_ZtCTypeArguBind); + }/* + template + static void Exec10(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, Type10& AR_Type10)*/ + + template + static void Exec10(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, Type10& AR_Type10, THelpType& ArHelpType) + { + typename ZNsType::ZtCTypeArguBind:: + ZStArguments10 VO_ZtCTypeArguBind(AR_Type1, AR_Type2, AR_Type3, AR_Type4, AR_Type5, AR_Type6, AR_Type7, AR_Type8, AR_Type9, AR_Type10); + + TClassExec::Exec10(VO_ZtCTypeArguBind, ArHelpType); + }/* + template + static void Exec10(Type1& AR_Type1, Type2& AR_Type2, Type3& AR_Type3, Type4& AR_Type4, Type5& AR_Type5, Type6& AR_Type6, Type7& AR_Type7, Type8& AR_Type8, Type9& AR_Type9, Type10& AR_Type10, THelpType& ArHelpType)*/ + + public: + };/* + template class ZtCArguBind*/ + + + /*////////////////////////////////////////////////////////////////////////////////////////// + + ■ 위 ZtCArguBind<> 보다는 아래 struct ZtStTuple<> 이 더 유용할 것이다. -- 2015-02-15 20:52:00 + + ■ template 인수가 Type11 까지 있음에 주의한다. 그러면 Type10 까지 전문화할 수 있는 것이다. + + -- 2015-02-16 21:20:00 + + //////////////////////////////////////////////////////////////////////////////////////////*/ + + + template< typename Type1 , typename Type2=void, + typename Type3=void, typename Type4=void, typename Type5=void, typename Type6=void, typename Type7=void, typename Type8=void, typename Type9=void, typename Type10=void, typename Type11=void + > + struct ZtStTuple ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; + + ZtStTuple(){} + ZtStTuple(Type1 _T1):_1(_T1){} + };/* + template< typename Type1 , typename Type2=void, + typename Type3=void, typename Type4=void, typename Type5=void, typename Type6=void, typename Type7=void, typename Type8=void, typename Type9=void, typename Type10=void, typename Type11 + > + struct ZtStTuple ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2):_1(_T1), _2(_T2){} + };/* + template< typename Type1, typename Type2 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3):_1(_T1), _2(_T2), _3(_T3){} + };/* + template< typename Type1, typename Type2, typename Type3 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4 //////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4):_1(_T1), _2(_T2), _3(_T3), _4(_T4){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4 //////////////////////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5 //////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5):_1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5 //////////////////////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6 //////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; Type6 _6; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6):_1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5), _6(_T6){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6 //////////////////////////////////////////////////////////////////////// + > + struct ZtStTuple //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7 //////////////////////////////////////////////////////// + > + struct ZtStTuple ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; Type6 _6; Type7 _7; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6, Type7 _T7):_1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5), _6(_T6), _7(_T7){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7 //////////////////////////////////////////////////////// + > + struct ZtStTuple ///////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8 //////////////////////////////////////// + > + struct ZtStTuple ////////////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; Type6 _6; Type7 _7; Type8 _8; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8):_1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5), _6(_T6), _7(_T7), _8(_T8){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8 //////////////////////////////////////// + > + struct ZtStTuple ////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9 //////////////////////// + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; Type6 _6; Type7 _7; Type8 _8; Type9 _9; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8, Type9 _T9) : _1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5), _6(_T6), _7(_T7), _8(_T8), _9(_T9){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9 + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////////////*/ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9, typename Type10 + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////// + { + Type1 _1; Type2 _2; Type3 _3; Type4 _4; Type5 _5; Type6 _6; Type7 _7; Type8 _8; Type9 _9; Type9 _10; + + ZtStTuple(){} + + ZtStTuple( + Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8, Type9 _T9, Type10 _T10) : + _1(_T1), _2(_T2), _3(_T3), _4(_T4), _5(_T5), _6(_T6), _7(_T7), _8(_T8), _9(_T9), _10(_T10){} + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9, typename Type10 + > + struct ZtStTuple /////////////////////////////////////////////////////////////////////////////////////////*/ + + + template< typename Type1, typename Type2 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2) + { + ZtStTuple VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; + VO_ZtStTuple._2=AO_Type2; return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2) */ + + template< typename Type1, typename Type2, typename Type3 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3) + { + ZtStTuple VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; + VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type2 AO_Type3) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4) + { + ZtStTuple VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + + return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5) + { + ZtStTuple VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + VO_ZtStTuple._5=AO_Type5; + + return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6) + { + ZtStTuple< + Type1, Type2, Type3, Type4, Type5, Type6> VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + VO_ZtStTuple._5=AO_Type5; VO_ZtStTuple._6=AO_Type6; return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6AO_Type6) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7) + { + ZtStTuple< + Type1, Type2, Type3, Type4, Type5, Type6, Type7> VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + VO_ZtStTuple._5=AO_Type5; VO_ZtStTuple._6=AO_Type6; + VO_ZtStTuple._7=AO_Type7; + + return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7 + > + ZtStTuple MakeArguTuple(Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8) + { + ZtStTuple< + Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8> VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + VO_ZtStTuple._5=AO_Type5; VO_ZtStTuple._6=AO_Type6; + VO_ZtStTuple._7=AO_Type7; VO_ZtStTuple._8=AO_Type8; return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8, Type8 AO_Type9) + { + ZtStTuple< + Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9> VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2=AO_Type2; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4=AO_Type4; + VO_ZtStTuple._5=AO_Type5; VO_ZtStTuple._6=AO_Type6; + VO_ZtStTuple._7=AO_Type7; VO_ZtStTuple._8=AO_Type8; VO_ZtStTuple._9=AO_Type9; + + return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8, Type8 AO_Type9) */ + + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9, typename Type10 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8, Type9 AO_Type9, Type1 AO_Type10) + { + ZtStTuple< + Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10> VO_ZtStTuple; + + VO_ZtStTuple._1=AO_Type1; VO_ZtStTuple._2 =AO_Type2 ; + VO_ZtStTuple._3=AO_Type3; VO_ZtStTuple._4 =AO_Type4 ; + VO_ZtStTuple._5=AO_Type5; VO_ZtStTuple._6 =AO_Type6 ; + VO_ZtStTuple._7=AO_Type7; VO_ZtStTuple._8 =AO_Type8 ; + VO_ZtStTuple._9=AO_Type9; VO_ZtStTuple._10=AO_Type10; return VO_ZtStTuple; + };/* + template< typename Type1, typename Type2, typename Type3, typename Type4, typename Type5, typename Type6, typename Type7, typename Type8, typename Type9, typename Type10 + > + ZtStTuple MakeArguTuple( + Type1 AO_Type1, Type2 AO_Type2, Type3 AO_Type3, Type4 AO_Type4, Type5 AO_Type5, Type6 AO_Type6, Type7 AO_Type7, Type8 AO_Type8, Type9 AO_Type9, Type1 AO_Type10) */ + + + namespace ZNsHide + { + /* 특정 클래스 안에서만 사용되어, 사용자가 그 존재를 알 필요가 없는 클래스를 둔다. */ + }/* + namespace ZNsHide*/ + + namespace ZNsIn + { + /*/////////////////////////////////////////////////////////////////////////////// + + ■ 특정 메인 클래스에 종속되어 사용되는 클래스가 있고, 메인 클래스가 생성될 때 등, + 아주 잠시만 필요한 클래스가 있다면 ZNsIn~ 접두어로 시작하는 namespace 에 둔다. + ZNsHide 에 두자니 한 번은 명시적으로 사용을 하니까 Hidden 되지는 않기 때문에, + 이렇게 하자. 이를테면 CIocp 클래스가 있는데, 이 클래스의 생성자에서 CHelpIocp + 클래스를 인수로 받고, 그 후 CHelpIocp 는 사용자가 직접 사용할 일이 없다면 이 클 + 래스는 namespace ZNsInIOCP 에 둘 수 있겠다. + + -- 2009-12-21 12:56:00 + + ///////////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsIn*/ + + namespace ZNsTmplParam + { + }/* + namespace ZNsTmplParam*/ + + namespace ZNsBase + { + // 가상클래스도 아니고 인터페이스 전용의 함수도 아니면서 + // 주로 기반 클래스로 사용되는 클래스는 여기에 둔다. + }/* + namespace ZNsBase*/ + + namespace ZNsSngt + { + /*//////////////////////////////////////////////////////////////////////////////////////////// + + ■ singleton 으로 사용되는 object 들을 가져오는 함수나 object 들은 여기에 둔다. + singleton 으로 사용되는 object 들은 여기에 두지말고, CSngt 라는 접두어를 사용할 수도 있다. + + ////////////////////////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsSngt*/ + + namespace ZNsSttc + { + /*///////////////////////////////////////////////////////////////////////////// + + ■ static 멤버만을 갖는 object 들은 여기에 두거나 CSttc 라는 접두어를 사용한다. + + -- 2010-03-10 19:58:00 + + /////////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsSttc*/ + + namespace ZNsReent + { + /*//////////////////////////////////////////////////////////// + + ■ ZNsReent : namespace Reentrant + + 어떤 자료 구조가 thread safe 한 경우와, 그렇지 않은 경우를 + 따로 구현한다면 thread safe 한 구조를 여기에 둔다. + + ////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsReent*/ + + namespace ZNsArg + { + /*//////////////////////////////////////////////////////////////// + + ■ 쓰레드의 Call Back 함수와 같이 어떤 함수가 특정한 자료를 포인터 + 로 받고 있는데, 이 포인터가 특수한 사정으로 여러 자료형의 object + 의 포인터를 받아야 할 때, 해당 object 들의 포인터를 class 로 묶 + 고 이 클래스 object 의 포인터로 사용하면 되는데, 이와 같은 용도 + 로 사용하는 클래스는 여기에 둔다. + + 쓰레드의 Call Back 함수라면 아예 그 함수 내부에서 내포 클래스로 + 정의해버리는 것이 더 좋을 것 같다. + + -- 2010-01-02 22:11:00 + + ////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsArg*/ + + namespace ZNsDeco + { + /*//////////////////////////////////////////////////////////////// + + ■ 어떤 클래스(템플릿)이 거의 같은 기능을 하지만, Decoration 패턴 + 을 사용하는 클래스와, 그렇지 않은 클래스가 쌍으로 존재할 때, + Decoration 패턴을 사용하는 클래스는 주로 namespace ZNsDeco 에 둔 + 다. 즉, Logic 과 View 구조에서, View 에 해당하는 클래스를 생성 + 자에서 (주로 참조로) 전달받는 클래스 템플릿이 주요 대상이다. + + -- 2010-03-10 22:04:00 + + ////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsDeco*/ + + namespace ZNsView + { + /*////////////////////////////////////////////////////////////////////////////////// + + ■ 'Logic-View 구조'(일반적으로는 Document-View 구조라고 얘기를 하는데, 그보다는 + 'Logic-View 구조'라고 하는 것이 더 적절한 것 같다)에서 View 에 해당하는 클래스는 + 여기에 놓는다. 여기에 있는 클래스는 접두어 CView 붙여도 좋을 것 같다. + + 접두어 CView 를 붙이지 않아도, namespace ZNsView 에 있다면 그 클래스는 View 라는 + 것을 알 수 있는데, 그렇다면 접두어 CView 을 붙일 것인지 말 것인지는, 그때그때 상 + 황에 맡기기로 하자. + + -- 2011-09-11 13:50:00 + + //////////////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsView*/ + + namespace ZNsViewIFace + { + /*////////////////////////////////////////////////////////////////////////////////// + + ■ 'Logic-View 구조'에서 View 에 해당하는 어떤 클래스의 interface 를 알려주는 클래스는 + 여기에 놓는다. + + -- 2011-09-11 13:54:00 + + //////////////////////////////////////////////////////////////////////////////////*/ + }/* + namespace ZNsViewIFace*/ + + namespace ZNsCRTP + { + /*////////////////////////////////////////////////// + + ■ CRTP : CURIOUSLY RECURRING TEMPLATE PATTERN + + CRTP 를 사용하는 클래스 템플릿은 주로 여기에 둔다. + + -- 2010-03-12 13:51:00 + + //////////////////////////////////////////////////*/ + }/* + namespace ZNsCRTP*/ + + namespace ZNsFunc + { + + /*/////////////////////////////////////////////////////////////////////////// + + ■ 특수한 목적으로 쓰이는 전역 템플릿 함수는 여기에 놓는다. + + ■ __FastMoveObj<>(Type1& AR_Type1,Type2& AR_Type2) + + 차기 표준에서 구현하는 RValue Reference 를 흉내낸 함수다. Move 생성자와 + Move 대입연산 중 대입연산만을 흉내내는 것이며, 일반적으로 이 함수 호출후에 + AR_Type2 의 크기는 0 이 되거나 줄어들 것이다. + + 해당 object 에 Move 대입연산이 필요하면 해당 object 를 인수로 갖는 + __FastMoveObj() 함수 템플릿을 전문화하면 된다. + + ■ 어느 함수 func()가 인수로 전달되는 object 의 초기/종료 멤버함수를 요구하는 + 경우, 그때마다 해당 object class 를 선언할 때, 특정한 이름의 초기/종료 멤버 + 함수를 선언/정의해야 하는데, 이런 불편함을 약간이라도 감소시키기 위해, func() + 에서 해당 object 를 인수로 갖는 전역함수 __Init<>(), __Fini<>() 를 호출하는 + 것으로 하면 다소 편해질 것이다. 그 후 필요에 따라, __Init, __Fini 템플릿을 + 전문화하면 된다. + + ■ -- 2009-08-15 19:57:00 + + ///////////////////////////////////////////////////////////////////////////*/ + + template + void __FastMoveObj(Type1& AR_Type1, Type2& AR_Type2) + { + #ifdef _DEBUG_FAST_MOVE_OBJ_ + cout<<" ※※ __FastMoveObj Start : Type1="<(Type&), Type="< void __Init(Type& AR_Type)*/ + + template void __Fini(Type& AR_Type) + { + #ifdef _DEBUG + cout<<"void ZNsFunc::__Fini(Type&), Type="< void __Fini(Type& AR_Type)*/ + + + /*/////////////////////////////////////////////////////////////////////////// + + ■ CObjAVL<> 등의 클래스에서 object 를 추가하거나 삭제할 때, 아래 중첩 함수를 + 각각 1 회 씩 최대 2 회 수행하게 되는데, + + bool operator> (~) + bool operator==(~) + + 이를 꼭 1 번만 수행하도록 줄이기 위해 (클래스이지만 실은 함수인) + + int ZtCCompare<>::Exec(TTypeArg1 AR_TypeArg1, TTypeArg2 AR_TypeArg2) + + 를 사용한다. + + -- 2012-09-01 20:13:00 + + AR_Type1==AR_Type2 이면 ZNsEnum::ECompareResult_Equal , + AR_Type1>=AR_Type2 이면 ZNsEnum::ECompareResult_Equal 이상의 값, + AR_Type1> AR_Type2 이면 ZNsEnum::ECompareResult_More 이상의 값, + AR_Type1<=AR_Type2 이면 ZNsEnum::ECompareResult_Equal 이하의 값, + AR_Type1< AR_Type2 이면 ZNsEnum::ECompareResult_Less 이하의 값, + + 을 리턴하거나 + + AR_Type1>=AR_Type2 이면 ZNsEnum::ECompareResult_Equal 이상의 값, + AR_Type1> AR_Type2 이면 ZNsEnum::ECompareResult_Equal 보다 큰 값, + AR_Type1<=AR_Type2 이면 ZNsEnum::ECompareResult_Equal 이하의 값, + AR_Type1< AR_Type2 이면 ZNsEnum::ECompareResult_Equal 보다 작은 값, + + 을 리턴한다. + + -- 2012-09-01 20:20:00 + + 최초에는 + + template __CompareObj(Type1, Type2) + + 라는 함수를 만들어 사용했는데, 템플릿 중첩 정의 시에 상당히 불편했었다. + 분명히 문법에 맞게 썼는 것 같은데, 컴파일 에러가 자꾸 나고... 단순히 문 + 법에 안맞게 써서 그렇다고 한 마디 말로 표현하기에는 어려운 상황이다. + + -- 2012-09-02 22:49:00 + + ZtCCompare<>::Exec(~) 가 template 함수로 선언되어 있는데, 이전에는 template + 함수가 아니었다. 이것을 template 함수로 바꾼 이유는 ZtCCompare<> 의 template + 인자에 TTypeArg1, TTypeArg2 에 구애받지 않기 위해서다. 따라서 확장성이 + 약간 상승한다. + + -- 2012-10-09 09:14:00 + + ///////////////////////////////////////////////////////////////////////////*/ + + template< typename TTypeArg1, + typename TTypeArg2, + bool TTypebCompareObj=true + > + class ZtCCompare ///////////////////////// + { + public: + enum {EUseCompareObj=(ZTypIntE)TTypebCompareObj}; + public: + + template + static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) + { + #ifdef _DEBUG_CCOMPARE_EXEC + cout<<" ※※ ZtCCompare is called."< + static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) */ + + public: + };/* + template< typename TTypeArg1, + typename TTypeArg2, + bool TTypebCompareObj=true + > + class ZtCCompare ///////////////////////*/ + + + template + class ZtCCompare + { + public: + enum {EUseCompareObj=0}; + public: + + template + static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) + { + return ZNsEnum::ECompareResult_Equal; + }/* + template + static ZTypInt Exec(TTypeArg1 AR_TypeArg1, TTypeArg2 AR_TypeArg2)*/ + + public: + };/* + template + class ZtCCompare */ + + + template<> class ZtCCompare + { + public: + enum {EUseCompareObj=1}; + public: + + static ZTypInt Exec(ZTypInt AI_Int1, ZTypInt AI_Int2) + { + #ifdef _DEBUG_CCOMPARE_EXEC + cout<<" ※※ ZtCCompare is called."< class ZtCCompare*/ + + + + /*///////////////////////////////////////////// + + ■ ZtCMoveObj<> 의 사용례는 CObjAVL.H 에 있다. + + -- 2013-08-26 19:18:00 + + /////////////////////////////////////////////*/ + + template< typename TTypeArg1, + typename TTypeArg2, + bool TTypebMoveObj=true + > + class ZtCMoveObj /////////////////////// + { + public: + enum {EUseMoveObj=(ZTypIntE)TTypebMoveObj}; + public: + + template + static void Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) + { + #ifdef _DEBUG_MOVEOBJ_EXEC + cout<<" ※※ ZtCMoveObj is called."< + static void Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) */ + + public: + };/* + template< typename TTypeArg1, + typename TTypeArg2, + bool TTypebMoveObj=true + > + class ZtCMoveObj ////////////////////*/ + + + template< typename TTypeArg1, typename TTypeArg2 + > + class ZtCMoveObj //// + { + public: + enum {EUseMoveObj=0}; + public: + + template + static void Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) + { + AR_TypeArg1 = AR_TypeArg2 ; + }/* + template + static void Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) */ + + public: + };/* + template< typename TTypeArg1, typename TTypeArg2 + > + class ZtCMoveObj //*/ + + }/* + namespace ZNsFunc*/ + + + namespace ZNsTmplChain + { + + /*//////////////////////////////////////////////////////////// + + ■ ZtCTmplChain<> 와 유사한 인터페이스를 이용하여, 마치 chain + 처럼 호출하는 구조를 갖는 클래스를 여기에 둔다. + + -- 2011-08-05 21:16:00 + + 사용례는 CMainChars.H 의 + + TTypeLength CSearchCursor_T<>::GetLengthByTmplChain(~) + + 함수를 참고한다. + + -- 2011-08-06 23:51:00 + + ////////////////////////////////////////////////////////////*/ + + template< typename TTypeNow, typename TTypeNext + > + class ZtCTmplChain //////////////////////////// + { + public : + typedef TTypeNow ZCObjNow ; + typedef TTypeNext ZCObjNext; + public : + enum{ENextObjNo =ZCObjNext::ENextObjNo+1}; + enum{EBoolNextObj=1 }; + private: + TTypeNow mo_ZCObjNow ; + TTypeNext mo_ZCObjNext; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow ;} + ZCObjNext& GetNextObj() {return mo_ZCObjNext;} + /*#####################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow ;} + const ZCObjNext& GetNextObj() const{return mo_ZCObjNext;} + public: + };/* + template< typename TTypeNow, typename TTypeNext + > + class ZtCTmplChain //////////////////////////*/ + + + template class ZtCTmplChain + { + public : + typedef TTypeNow ZCObjNow ; + typedef TTypeNow ZCObjNext; + public : + enum{ENextObjNo =1}; + enum{EBoolNextObj=0}; + private: + ZCObjNow mo_ZCObjNow; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow;} + ZCObjNext& GetNextObj() {return mo_ZCObjNow;} + /*####################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow;} + const ZCObjNext& GetNextObj() const{return mo_ZCObjNow;} + public: + };/* + template class ZtCTmplChain */ + + + /*////////////////////////////////////////////////////////////////////////////// + + ■ ZtCTmplTreeChain<> 와 유사한 인터페이스를 이용하여, 마치 chain 의 tree 처럼 + 호출하는 구조를 갖는 클래스를, ZtCTmplChain<> 와 같은 namespace 에 둔다. + + -- 2011-10-04 00:46:00 + + 일종의 2진 트리 형태인데, GetNextObj2() 멤버로 호출하는 노드를 따라서 먼저 + 처리를 끝내는지, 아니면 GetNextObj() 멤버로 호출하는 노드를 따라서 먼저 처리할 + 것인지는 경우에 따라 다르다. 일반적으로는 GetNextObj2() 멤버로 호출하는 노드를 + 따라서 먼저 처리를 하는 것으로 정한다. + + -- 2011-10-04 21:01:00 + + 사용례는 CMainChars.H 의 + + TTypeLength CSearchCursor_T<>::GetLengthByTmplTreeChain(~) + + 함수를 참고한다. + + -- 2011-10-04 00:53:00 + + //////////////////////////////////////////////////////////////////////////////*/ + + template< typename TTypeNow , + typename TTypeNext , + typename TTypeNext2 + > + class ZtCTmplTreeChain //////// + { + public : + enum{ENextObjNo =TTypeNext ::ENextObjNo +1}; + enum{ENextObjNo2 =TTypeNext2::ENextObjNo2+1}; + enum{EBoolNextObj =1}; + enum{EBoolNextObj2=1}; + enum{EObjChainCnt =TTypeNext::EObjChainCnt+TTypeNext2::EObjChainCnt+2}; + public : + typedef TTypeNow ZCObjNow ; + typedef TTypeNext ZCObjNext ; + typedef TTypeNext2 ZCObjNext2; + private: + ZCObjNow mo_ZCObjNow ; + ZCObjNext mo_ZCObjNext ; + ZCObjNext2 mo_ZCObjNext2; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow ;} + ZCObjNext& GetNextObj () {return mo_ZCObjNext ;} + ZCObjNext2& GetNextObj2() {return mo_ZCObjNext2;} + /*########################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow ;} + const ZCObjNext& GetNextObj () const{return mo_ZCObjNext ;} + const ZCObjNext2& GetNextObj2() const{return mo_ZCObjNext2;} + public : + };/* + template< typename TTypeNow , + typename TTypeNext , + typename TTypeNext2 + > + class ZtCTmplTreeChain //////*/ + + + template< typename TTypeNow, typename TTypeNext + > + class ZtCTmplTreeChain + { + public : + enum{ENextObjNo =TTypeNext::ENextObjNo +1}; + enum{ENextObjNo2 =0 }; + enum{EBoolNextObj =1 }; + enum{EBoolNextObj2=0 }; + enum{EObjChainCnt =TTypeNext::EObjChainCnt+1}; + public : + typedef TTypeNow ZCObjNow ; + typedef TTypeNext ZCObjNext ; + typedef TTypeNext ZCObjNext2; // interface 호환을 위해서만 존재. + private: + ZCObjNow mo_ZCObjNow ; + ZCObjNext mo_ZCObjNext; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow ;} + ZCObjNext& GetNextObj () {return mo_ZCObjNext;} + ZCObjNext2& GetNextObj2() {return mo_ZCObjNext;} // interface 호환을 위해서만 존재. + /*#######################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow ;} + const ZCObjNext& GetNextObj () const{return mo_ZCObjNext;} + const ZCObjNext2& GetNextObj2() const{return mo_ZCObjNext;} // interface 호환을 위해서만 존재. + public : + };/* + template< typename TTypeNow, typename TTypeNext + > + class ZtCTmplTreeChain */ + + template< typename TTypeNow, typename TTypeNext2 + > + class ZtCTmplTreeChain + { + public : + enum{ENextObjNo =0 }; + enum{ENextObjNo2 =TTypeNext2::ENextObjNo2 +1 }; + enum{EBoolNextObj =0 }; + enum{EBoolNextObj2=1 }; + enum{EObjChainCnt =TTypeNext2::EObjChainCnt+1 }; + public : + typedef TTypeNow ZCObjNow ; + typedef TTypeNext2 ZCObjNext ; // interface 호환을 위해서만 존재. + typedef TTypeNext2 ZCObjNext2; + private: + ZCObjNow mo_ZCObjNow ; + ZCObjNext2 mo_ZCObjNext2; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow ;} + ZCObjNext& GetNextObj () {return mo_ZCObjNext2;} // interface 호환을 위해서만 존재. + ZCObjNext2& GetNextObj2() {return mo_ZCObjNext2;} + /*########################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow ;} + const ZCObjNext& GetNextObj () const{return mo_ZCObjNext2;} // interface 호환을 위해서만 존재. + const ZCObjNext2& GetNextObj2() const{return mo_ZCObjNext2;} + public : + };/* + template< typename TTypeNow , typename TTypeNext2 + > + class ZtCTmplTreeChain */ + + template< typename TTypeNow //////////////////// + > + class ZtCTmplTreeChain + { + public : + enum{ENextObjNo =0}; + enum{ENextObjNo2 =0}; + enum{EBoolNextObj =0}; + enum{EBoolNextObj2=0}; + enum{EObjChainCnt =1}; + public : + typedef TTypeNow ZCObjNow ; + typedef ZCObjNow ZCObjNext ; // interface 호환을 위해서만 존재. + typedef ZCObjNow ZCObjNext2; // interface 호환을 위해서만 존재. + private: + ZCObjNow mo_ZCObjNow; + public : + ZCObjNow& GetNowObj () {return mo_ZCObjNow;} + ZCObjNext& GetNextObj () {return mo_ZCObjNow;} // interface 호환을 위해서만 존재. + ZCObjNext2& GetNextObj2() {return mo_ZCObjNow;} // interface 호환을 위해서만 존재. + /*######################################################*/ + const ZCObjNow& GetNowObj () const{return mo_ZCObjNow;} // interface 호환을 위해서만 존재. + const ZCObjNext& GetNextObj () const{return mo_ZCObjNow;} // interface 호환을 위해서만 존재. + const ZCObjNext2& GetNextObj2() const{return mo_ZCObjNow;} // interface 호환을 위해서만 존재. + public : + };/* + template< typename TTypeNow //////////////////// + > + class ZtCTmplTreeChain + */ + }/* + namespace ZNsTmplChain*/ + + + /*/////////////////////////////////////////////////////////////////// + + ■ 함수가 어떤 조건에서 실행을 중지할 때, + bool 값으로 표시해도 되지만 가독성을 위해서 enum ERun 을 사용하자. + + ■ enum ERun 의 값을 포함해서 에러 상태를 표현하고 싶을 때에는, + enum ERunEx 를 사용하자. + + -- 2011-09-27 05:37:00 + + ///////////////////////////////////////////////////////////////////*/ + + namespace ZNsEnum + { + + enum ERun + { + ERun_NO, // 실행 중지 + ERun_OK // 실행 계속 + };/* + enum ERun*/ + + enum ERunEx + { + ERunEx_NO, // 실행 중지 + ERunEx_OK, // 실행 계속 + ERunEx_Err // 실행 에러 + };/* + enum ERun*/ + + enum EAct + { + EAct_NO, // (함수 등이) 어떤 조건에 맞지 않아서 아무 짓도 하지 않았다. + EAct_OK // (함수 등이) 어떤 조건에 맞아서 지정된 처리를 하였다. + };/* + enum EAct*/ + + enum EActEx + { + EActEx_NO, // (함수 등이) 어떤 조건에 맞지 않아서 아무 짓도 하지 않았다. + EActEx_OK, // (함수 등이) 어떤 조건에 맞아서 지정된 처리를 하였다. + EActEx_Err // (함수 등이) 수행 중에 에러가 발생하였다. + };/* + enum EAct*/ + + enum EThrowFinally + { + EThrowFinally_NO, + EThrowFinally_OK + };/* + enum EThrowFinally*/ + + /*//////////////////////////////////////////////// + + ■ 타 언어의 throw ~ catch ~ finally 를 흉내낼 때 + EThrowFinally 예외를 던진다. + + ////////////////////////////////////////////////*/ + + }/* + namespace ZNsEnum*/ + + + namespace ZNsInterface + { + + /*//////////////////////////////////////////////////////////////////////////////////// + + ■ class ZIDelgtMSG 는 C# 의 delegate 삼아서 만든 클래스. + + 어느 object 가 하나 이상의 다른 object 에게 어떤 메시지를 전달하고 싶을 때, 메시지를 + 전송하는 object 는, 수신하는 object 의 기반클래스 ZIDelgtMSG 의 참조나 포인터를 멤버 + 로 가지고 있다가, ZIDelgtMSG::SendMSG() 나 ZIDelgtMSG::RecvMSG() 을 호출하면 된다. + + ■ COM 개념을 상당부분 포함하고 있다. 간단하게 COM 대용으로 써도 될 듯 하다. + + -- 2009-03-08 02:26:00 + + ■ class ZIDelgtMSG 를 상속하여 추가 멤버함수를 가진 인터페이스를 구현하는 클래스일 경우 + 에는 namespace ZNsInterface 에 두지 말고 namespace ZNsIDelgt 에 두자. + + -- 2009-03-08 19:17:00 + + ■ A, B, C 클래스가 서로의 존재를 알아야 한다고 할 때도 사용할 수 있겠다. 그런데 이런 경 + 우는 굳이 ZIDelgtMSG 를 사용하지 말고, 단순 가상 함수 클래스를 사용해도 된다. 그게 더 + 간단할 것이다. 그래도 ZIDelgtMSG 를 사용한다면, interface 의 일관성을 얻을 수 있다는 게 + 장점이 될 수 있다. + + -- 2010-03-13 22:28:00 + + ////////////////////////////////////////////////////////////////////////////////////*/ + + class ZIDelgtMSG + { + public: + enum EIMSG{EIMSG_NO=0, EIMSG_OK=1}; + public: + + virtual ~ZIDelgtMSG(){} + + virtual int GetTypeID() const + { + return 0; + }/* + virtual int GetTypeID() const*/ + + virtual const char* GetTypeName() const + { + return 0; + }/* + virtual const char* GetTypeID() const*/ + + virtual int GetIMSGPtrOfID(int AI_TypeID, ZIDelgtMSG*& APR_ZIDelgtMSG) + { + APR_ZIDelgtMSG=0; return EIMSG_OK; + }/* + virtual int GetIMSGPtrOfID(int AI_TypeID, ZIDelgtMSG*R APR_ZIDelgtMSG)*/ + + virtual IntPtr SendMSG(ZIDelgtMSG& ArZIDelgtMSG, int AI_MsgNo, const char* ApcMsgData, int AI_MsgLen, void* AP_Void=0, ...) + { + return EIMSG_OK; + }/* + virtual IntPtr SendMSG(ZIDelgtMSG& ArZIDelgtMSG, int AI_MsgNo, const char* ApcMsgData, int AI_MsgLen,void* AP_Void=0, ...)*/ + + virtual IntPtr RecvMSG(int AI_MsgNo, const char* ApcMsgData, int AI_MsgLen, void* AP_Void=0, ...) + { + return EIMSG_OK; + }/* + virtual IntPtr RecvMSG(int AI_MsgNo, const char* ApcMsgData, int AI_MsgLen, void* AP_Void=0, ...)*/ + + public: + };/* + class ZIDelgtMSG*/ + + }/* + namespace ZNsInterface*/ + + + namespace ZNsIDelgt + { + // class ZIDelgtMSG 를 상속하여 추가 멤버함수를 가진 + // 인터페이스를 구현하는 클래스일 경우에는 여기에 둔다. + }/* + namespace ZNsIDelgt*/ + + + class ZCAllocator + { + public: + static void* operator new (size_t AL_AllocSize ){return ::malloc(AL_AllocSize);} + static void* operator new[](size_t AL_AllocSize ){return ::malloc(AL_AllocSize);} + static void* operator new (size_t AL_AllocSize, void* AP_AllocBegin){return AP_AllocBegin ;} + static void* operator new[](size_t AL_AllocSize, void* AP_AllocBegin){return AP_AllocBegin ;} + + static void operator delete (void* AP_Void){if(AP_Void!=0) ::free(AP_Void);} + static void operator delete[](void* AP_Void){if(AP_Void!=0) ::free(AP_Void);} + public: + };/* + class ZCAllocator*/ + + + /*///////////////////////////////////////////////////////////////// + + ■ class ZCAllocator 는 정적 멤버를 사용하지만 + class ZtCAllocClass<> 는 비정적 멤버를 사용한다. + + ■ 기본메모리 할당자로 ZtCAllocClass<> 을 사용하는 클래스가 나중에 + 다른 할당 알고리즘을 사용하고 싶을 때는 ZtCAllocClass<> 템플릿을 + 해당 Type 으로 전문화시켜주면 된다. + + /////////////////////////////////////////////////////////////////*/ + + template + class ZtCAllocClass : public ZCAllocator + { + public: + TType* NewMem (size_t AL_AllocSize){return (TType*)::malloc(AL_AllocSize) ;} + TType* NewArrMem(size_t AL_AllocSize){return (TType*)::malloc(AL_AllocSize*sizeof(TType));} + public: + void DeleteMem(void* AP_Void){if(AP_Void!=0) ::free(AP_Void);} + public: + };/* + template class ZtCAllocClass*/ + + + class ZCAllocClass : public ZCAllocator + { + public: + void* NewMem (size_t AL_AllocSize){return ::malloc(AL_AllocSize) ;} + void DeleteMem(void* AP_Void ){if(AP_Void!=0) ::free(AP_Void);} + public: + };/* + class ZCAllocClass : public ZCAllocator*/ + + + /*////////////////////////////////////////////////////////////// + + ■ 가끔 템플릿으로 클래스 설계를 하다보면 템플릿의 parameter 가 + 포인터나 참조일 경우, 무엇의 포인터나 참조형인지 알고 싶을 때 + 가 있다. 이런 경우에 ZtCTypeData<> 를 사용한다. + + cf) + + cout<::TypeData).name()<::TypeData).name()<::TypeData).name()<::GetObjRef(~) 는 아래처럼 주로 포인터 자료형을 + (null 이 아닌 경우) 항상 참조형으로 다루고 싶을 때 사용한다. + 템플릿 Parameter 가 포인터형인데, 무엇의 포인터 형인지 알아 + 내어, 참조형으로 만들어 다른 함수의 인수로 사용하거나, 해당 + 멤버의 호출을 포인터 참조 표기 -> 말고 참조 표기(.)로 하면 편 + 할 것이다. + + typedef std::CStringBase_T CStringData ; + typedef CStringData* CStringDataPtr; + + CStringData VO_CStringData("My"); + CStringDataPtr VP_CStringData=&VO_CStringData; + + (*VP_CStringData)("Data"); + + cout<::GetObjRef(VP_CStringData)< class ZtCTypeData + { public: typedef TType TypeData; + static TType& GetObjRef(TType& AR_Type ){return \AR_Type ;}}; + template class ZtCTypeData + { public: typedef TType TypeData; + static TType& GetObjRef(TType* AP_Type){return *AP_Type;}}; + template class ZtCTypeData + { public: typedef TType TypeData; + static TType& GetObjRef(TType& AR_Type ){return AR_Type ;}}; + + + /*//////////////////////////////////////////////////////////////////////////////// + + ■ 문자열 클래스에서 새로 메모리를 증가시켜야 할 때, 필요한 메모리보다 약간 더 할 + 당하는 것이 좋을 경우가 있는데, 이 경우에 필요한 메모리보다 어느 정도 만큼의 메 + 모리를 할당한 것인지를 지정한다. + + ////////////////////////////////////////////////////////////////////////////////*/ + + template class ZtCAllocMemSize + { + public: + + template + TTypeSize GetNewAllocSize(TTypeSize AL_NowAllocSize, TTypeSize AL_AllAllocSize) + { + /* AL_AllAllocSize : 해당 문자열 object 가 할당받은 문자 총갯수. + AL_NowAllocSize : AL_AllAllocSize 에서 현재 유효한 문자 갯수. */ + + return AL_NowAllocSize<=AL_AllAllocSize ? AL_NowAllocSize : AL_NowAllocSize*2 ; + }/* + template + TTypeSize GetNewAllocSize(TTypeSize AL_NowAllocSize, TTypeSize AL_AllAllocSize) */ + + public: + };/* + template class ZtCAllocMemSize */ + + + /*////////////////////////////////////////////////////////////// + + ■ 아래 템플릿은 양방향 리스트에서 n 번째 원소에 접근할 때, 앞에 + 서부터 접근하는 것이 빠를지, 뒤에서부터 접근하는 것이 빠를지 + 판단할 때 사용한다. + + //////////////////////////////////////////////////////////////*/ + + template class ZtCShortCut + { + private: + + static inline TTypSize GetAbs(TTypSize AI_Param) // 인수의 절대값을 얻는다. + { + return (AI_Param<0 ? -AI_Param : AI_Param); + }/* + static inline TTypSize GetAbs(TTypSize AI_Param)*/ + + /*private:*/ + public : + + static int GetAbsMinOrder(TTypSize AI_One, TTypSize AI_Two, TTypSize AI_Three) + { + // 세 개의 인수 중에서 절대값이 최소가 되는 수는 + // 몇 번째 인지 그 순서를 반환한다. + // 맨 앞의 인수가 절대값이 최소면 1 을 반환한다. + // 두 번째 인수의 절대값이 최소면 2 를 반환한다. + // 세 번째 인수의 절대값이 최소면 3 을 반환한다. + + // 이 함수는 양방향 원형 연결리스트에서 n 번째 링크를 찾는데 쓰인다. + + return ( GetAbs(AI_One)<=GetAbs(AI_Two ) /******/ ? + (GetAbs(AI_One)<=GetAbs(AI_Three) ? 1 : 3) : + (GetAbs(AI_Two)<=GetAbs(AI_Three) ? 2 : 3) + /****/ ); + };/* + static int GetAbsMinOrder(TTypSize AI_One,TTypSize AI_Two, TTypSize AI_Three)*/ + + public: + };/* + template class ZtCShortCut*/ + + +#ifdef _WIN + + /*///////////////////////////////////////////////// + + inline int GetLastError(){return ::GetLastError();} + + /////////////////////////////////////////////////*/ + + using ::GetLastError; + + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) + { + LPVOID VP_MsgBuff; DWORD ViErrNo=(AI_ErrNo==0 ? ::GetLastError() : AI_ErrNo); + + const DWORD CI_RetCode = ::FormatMessage( /////////////// + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS , + NULL , + ViErrNo , + MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + (LPTSTR)&VP_MsgBuff,0,NULL + /*//////////*/ ); /////////////////////////////////////// + + if(CI_RetCode==0) return false; + + (ARR_BuffCStr= + ((LPCTSTR)VP_MsgBuff))(", ErrNo=")(ViErrNo); + + ::LocalFree(VP_MsgBuff); return true; + }/* + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) */ + + // defined(_WIN) +#elif defined(__unix__) + + inline int GetLastError() + { + return errno ; // ::error 로 하면 안된다. + }/* + inline int GetLastError()*/ + + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) + { + if(AI_ErrNo==0) + ARR_BuffCStr = ::strerror(errno ); + else ARR_BuffCStr = ::strerror(AI_ErrNo); + + return true; // for compatibility with window + }/* + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) */ + +//#elif defined(__unix__) + #else + + inline int GetLastError(){return errno ;} + + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) + { + if(AI_ErrNo==0) + ARR_BuffCStr = ::strerror(errno ); + else + ARR_BuffCStr = ::strerror(AI_ErrNo); + //else + + return true; // for compatibility with window + }/* + template + static bool GetLastErrMSG(TString& ARR_BuffCStr, int AI_ErrNo=0) */ + +#endif + + + // 절대값을 가져온다. + + template TLong ABS(TLong AL_Value) + { + if(AL_Value<0) return -AL_Value; return AL_Value; + }/* + template TLong ABS(TLong AL_Value) */ + + template + TypeInt AToInt(const char* ApcChar, int AI_Length) + { + if(AI_Length<1) return 0; + + while(AI_Length>0 && ApcChar[AI_Length-1]==' ') + --AI_Length; // 뒤에 있는 공백을 제외. + //while + + if(AI_Length<1) return 0; + + const char* VPC_Char =ApcChar+AI_Length-1; + TypeInt VL_Temp; + TypeInt VL_Result =(*VPC_Char--)-'0'; + TypeInt VL_Multiple=1; + + while(--AI_Length>0) + { + if((VL_Temp=*VPC_Char--)<'0' || VL_Temp>'9' ) return 0; + + VL_Result += (VL_Multiple*=10)*(VL_Temp-'0') ; //////// + }/* + while(--AI_Length>0)*/ + + return VL_Result; + }/* + template + TypeInt AToInt(const char* ApcChar, int AI_Length) */ + +#ifdef _WIN + + inline LongLong ATOLL(const char* ApcChar) + { + if(ApcChar==0) return 0; return ::_atoi64(ApcChar); + }/* + inline LongLong ATOLL(const char* ApcChar)*/ + +#else // !defined(_WIN) + + inline LongLong ATOLL(const char* ApcChar) + { + if(ApcChar==0) return 0; return ::atoll(ApcChar); + }/* + inline LongLong ATOLL(const char* ApcChar)*/ + +#endif // !defined(_WIN) + + + inline LongLong ATOLL(const char* ApcChar, int AI_Length) + { + return AToInt(ApcChar, AI_Length); + }/* + inline LongLong ATOL(const char* ApcChar, int AI_Length)*/ + + + inline long ATOL(const char* ApcChar) + { + if(ApcChar==0) return 0; return atol(ApcChar); + }/* + inline long ATOL(const char* ApcChar)*/ + + inline long ATOL(const char* ApcChar, int AI_Length) + { + return AToInt(ApcChar, AI_Length); + }/* + inline long ATOL(const char* ApcChar, int AI_Length)*/ + + + inline int ATOI(const char* ApcChar) + { + if(ApcChar==0) return 0; return atoi(ApcChar); + }/* + inline int ATOI(const char* ApcChar)*/ + + inline int ATOI(const char* ApcChar, int AI_Length) + { + return AToInt(ApcChar, AI_Length); + }/* + inline int ATOI(const char* ApcChar, int AI_Length)*/ + + inline double ATOD(const char* ApcChar) + { + return ApcChar==0 ? 0 : ::atof(ApcChar) ; + }/* + inline double ATOD(const char* ApcChar)*/ + + + template inline LLength GetLength(const TTypeCh* ApcChar) + { + if(ApcChar==0) return 0; long VL_Length=0; + + while(*(ApcChar+VL_Length)!=_T('\0')) ++VL_Length; return VL_Length; + }/* + template LLength GetLength(const TTypeCh* ApcChar) */ + + template + inline TTypeSize GetLengthType(const TTypeCh* ApcChar) + { + if(ApcChar==0) return 0; + + TTypeSize VL_Length=0; //////////////// + + while(*(ApcChar+VL_Length)!=_T('\0')) + { + ++VL_Length; + }/* + while(*(ApcChar+VL_Length)!=_T('\0'))*/ + + return VL_Length; //////////////////// + }/* + template + inline TTypeSize GetLengthType(const TTypeCh* ApcChar) */ + + + /*////////////////////////////////////////////////////////////////////////////////////// + + ■ CopyChars() 함수는 최대 AL_DestSize 만큼 복사하는데, ZNsWin.H 의 CRegistry 클래스에서 + Windows 의 Strsafe.h 에 정의된 StringCchCopy() 을 대신하려고 만들었다. mingw 에서는 + 헤더 파일 Strsafe.h 이 없는 경우가 있는 것이다. 원래 StringCchCopy() 선언은 이렇다. + + HRESULT StringCchCopy( + __out LPTSTR pszDest, + __in size_t cchDest, + __in LPCTSTR pszSrc + ); + + This function can return one of the following values. It is strongly recommended + that you use the SUCCEEDED and FAILED macros to test the return value of this function. + + Return code + + S_OK : Source data was present, fully copied without truncation, and the resultant + destination buffer is null-terminated. + + STRSAFE_E_INVALID_PARAMETER : The value in cchDest is either 0 or larger than STRSAFE_MAX_CCH. + + STRSAFE_E_INSUFFICIENT_BUFFER : The copy operation failed due to insufficient buffer + space. The destination buffer contains a truncated, null-terminated version of the + intended result. In situations where truncation is acceptable, this may not necessarily + be seen as a failure condition. + + -- 2012-08-15 07:40:00 + + //////////////////////////////////////////////////////////////////////////////////////*/ + + template + TTypeSize CopyChars(TTypeCh* ApcDest, TTypeSize AL_DestSize, const TTypeCh* ApcSource) + { + /* ApcSource must be null-terminated. AL_DestSize + must be equal to or more than strlen(ApcSource)+1. + + Null 문자를 포함하여 ApcDest 에 복사된 길이를 리턴한다. */ + + if(ApcSource==0) return 0; + + TTypeSize VL_SourceSize=0 ; + TTypeCh* VPC_Dest =ApcDest ; + const TTypeCh* VPC_Source =ApcSource; + + for(; VL_SourceSize + TTypeSize CopyChars(TTypeCh* ApcDest, TTypeSize AL_DestSize, const TTypeCh* ApcSource) */ + + + template class ZtCInit + { + public: + void operator()(TType& AR_TypeArg){} + public: + void OnInit(TType& AR_TypeArg){} + void OnFini(TType& AR_TypeArg){} + public: + };/* + template class ZtCInit*/ + + + class ZCInit + { + public: + template void operator()(TType& AR_TypeArg){} + template void OnInit (TType& AR_TypeArg){} + template void OnFini (TType& AR_TypeArg){} + + void OnInit(){} + void OnFini(){} + public: + };/* + class ZCInit*/ + + + class CExceptBase + { + public: void* operator()(){return 0;} + };/* + class CExceptBase*/ + + + // 예외 기반 클래스를 template 로 하면 여러 기법을 사용할 수 있다. + + template< typename TType, typename TypeArg=const TType& + > + class CExceptBase_T /*/////////////////////////////////*/ + { + protected: + TType mo_Type; + public : + + CExceptBase_T(){} + + CExceptBase_T(TypeArg TypeArgObj):mo_Type(TypeArgObj){} + + TType& operator()(){return mo_Type;} + + public : + };/* + template< typename TType, typename TypeArg=const TType& + > + class CExceptBase_T ///////////////////////////////////*/ + + + /*///////////////////////////////////////////////////////////////////////////////// + + ■ 이 클래스를 private 상속하는 클래스에서 복사생성자와 대입연산자의 사용을 막는다. + + ■ template class 나 class member template 을 사용할 때, 인수가 class object 이고 + 이 인수가 반드시 참조형으로 전달되어야하고, 복사 생성되어 전달될 수 없을때, 이를 + 보장하기 위해 해당 class 를 아래 class 로부터 상속할 필요가 있다. + + 이를 모르고 있다가, CAsyncServ_H 에 정의된 CAsyncServ_T<> 클래스를 사용할 때, 이 + 클래스가 작업쓰레드 풀 인수로 복사 생성되어 전달되는 것을 나중에 알고 깜짝 놀랬다. + + -- 2010-12-20 23:51:00 + + /////////////////////////////////////////////////////////////////////////////////*/ + + class CNonCopyable + { + private: + CNonCopyable(const CNonCopyable& rhs){} + CNonCopyable& operator=(const CNonCopyable& rhs){return *this;} + public : + CNonCopyable(){} + public : + };/* + class CNonCopyable*/ + + + /*/////////////////////////////////////////////////////////////////////////// + + ■ 리스트나 트리 구조에서 쓰는 링크의 힙-자유 기억 공간-을 구현하는 class 는 + class ZCFreeAllocBase 를 상속한다. 이 자유 기억 공간 클래스의 object 는 힙 + 에 할당한다. + + ///////////////////////////////////////////////////////////////////////////*/ + + class ZCFreeAllocBase + { + public: + + virtual ~ZCFreeAllocBase(){} + + virtual long GetHeapSize() const{return 0;} + virtual long GetMemSize () const{return 0;} + + const char* GetTypeName() const + { + return typeid(*this).name(); + }/* + const char* GetTypeName() const*/ + + virtual void DeleteAllInHeap(){} + + public: + };/* + class ZCFreeAllocBase*/ + + + // 자유 기억 공간을 총괄하는 단방향 연결 리스트 + + class ZCHeapAllocList + { + public: + + class ZCLink + { + public: + friend class ZCHeapAllocList; + public: + + ZCLink(ZCFreeAllocBase& ArCFreeAllocBase):mr_AllocBase(ArCFreeAllocBase), mp_NextLink(0) + { + }/* + ZCLink(ZCFreeAllocBase& ArCFreeAllocBase)*/ + + ZCLink* GetNextLink() + { + return mp_NextLink; + }/* + ZCLink* GetNextLink()*/ + + ZCLink* GetNextLink(long AL_Distance) + { + ZCLink* VP_NowLink=this; + + while(--AL_Distance>=0) + VP_NowLink=VP_NowLink->mp_NextLink; + + return VP_NowLink; + }/* + ZCLink* GetNextLink(long AL_Distance)*/ + + ZCFreeAllocBase& GetData() + { + return mr_AllocBase; + }/* + ZCFreeAllocBase& GetData()*/ + + /*public :*/ + + private: + ZCFreeAllocBase& mr_AllocBase; + ZCLink* mp_NextLink ; + private: + };/* + class ZCLink*/ + + + /*public :*/ + private: + ZTypIntL ml_Size ; + ZCLink* mp_HeadLink ; + ZCLink* mp_TailLink ; + private: + + void AddLink(ZCLink* AP_NewLink) + { + if(ml_Size++ == 0) + { + mp_HeadLink= mp_TailLink=AP_NewLink ; + mp_TailLink->mp_NextLink=mp_HeadLink; + } + else + { + mp_TailLink->mp_NextLink=AP_NewLink ; + AP_NewLink ->mp_NextLink=mp_HeadLink; + mp_TailLink=mp_TailLink->mp_NextLink; + }/* + else*/ + }/* + void AddLink(ZCLink* AP_NewLink)*/ + + /*private:*/ + public : + + ZCHeapAllocList() + { + ml_Size =0; + mp_HeadLink =0; + mp_TailLink =0; + }/* + ZCHeapAllocList()*/ + + template TypeFreeAlloc& AddFreeAlloc() + { + // TypeFreeAlloc 은 ZCFreeAllocBase 의 파생클래스여야 한다. + + TypeFreeAlloc* VP_TypeFreeAlloc=new TypeFreeAlloc; + + ZCLink* VP_NewLink=new ZCLink(*VP_TypeFreeAlloc); + + AddLink(VP_NewLink); return *VP_TypeFreeAlloc; + }/* + template TypeFreeAlloc& AddFreeAlloc() */ + + void AddFreeAllocBase(ZCFreeAllocBase& ArCFreeAllocBase) + { + AddLink( new ZCLink(ArCFreeAllocBase) ); + }/* + void AddFreeAllocBase(ZCFreeAllocBase& ArCFreeAllocBase)*/ + + + ZCFreeAllocBase& GetData(long AL_Index) + { + return mp_HeadLink->GetNextLink(AL_Index-1)->mr_AllocBase; + }/* + ZCFreeAllocBase& GetData(long AL_Index)*/ + + ZCLink* GetHeadLink() + { + return mp_HeadLink; + }/* + ZCLink* GetHeadLink()*/ + + template DeriveType& GetDataType(long AL_Index) + { + return static_cast( mp_HeadLink->GetNextLink(AL_Index-1)->mr_AllocBase ); + }/* + template DeriveType& GetDataType(long AL_Index) */ + + void FreeAll() + { + ZCLink* VP_Link=mp_HeadLink; + + for(long i=1; i<=ml_Size; ++i) + { + VP_Link->mr_AllocBase.DeleteAllInHeap(); + VP_Link=VP_Link->mp_NextLink; + }/* + for(long i=1; i<=ml_Size; ++i)*/ + }/* + void FreeAll()*/ + + void DeleteAll() + { + ZCLink* VP_CutLink=0; + + for(long i=1; i<=ml_Size; ++i) + { + VP_CutLink =mp_HeadLink; + mp_HeadLink=mp_HeadLink->mp_NextLink; + + delete VP_CutLink; + }/* + for(long i=1; i<=ml_Size; ++i)*/ + + ml_Size=0; + }/* + void DeleteAll()*/ + + void ClearAll() + { + ZCLink* VP_CutLink=0; + + for(long i=1; i<=ml_Size; ++i) + { + VP_CutLink =mp_HeadLink ; + mp_HeadLink=mp_HeadLink->mp_NextLink; + + VP_CutLink-> + mr_AllocBase.DeleteAllInHeap() ; + + delete VP_CutLink; + }/* + for(long i=1; i<=ml_Size; ++i)*/ + + ml_Size=0; + }/* + void ClearAll()*/ + + ZTypIntL GetSize() const + { + return ml_Size; + }/* + ZTypIntL GetSize() const*/ + + public: + };/* + class ZCHeapAllocList*/ + + + static ZCHeapAllocList& GetCHeapAllocList() + { + static ZCHeapAllocList SO_CHeapAllocList; return SO_CHeapAllocList; + }/* + static ZCHeapAllocList& GetCHeapAllocList()*/ + + + + /*////////////////////////////////////////////////////////////////// + + ■ 템플릿 인자를 정의할 때 참조로 하지 않은 경우에 object 의 크기가 + 크면 포인터로 넘겨야 하는데, 이러면 어느 object 의 포인터인지 알 + 수 있지만 그 object 에 속한 enum 형이나 typedef 선언 및 기타 자료 + 형은 알 수 없다. 그래서 object 의 포인터를 포장하는 클래스 템플릿 + ZtCObjectPtr<> 을 설계한다. + + ■ typedef std::CStringBase_T CStringBase; + typedef ZtCObjectPtr CObjectPtr ; + + 라는 선언이 있으면 CStringBase::TTypeChar 에 접근할 때에는 + + CObjectPtr::TypeData::TTypeChar 로 하면 된다. + + ■ 포인터 자료형에 대하여 ZtCObjectPtr<> 대신 더 간단하게 + ZtCTypeData<> 를 사용해도 된다. 이 편이 오히려 낳을 것 같다. + + -- 2010-01-24 22:25:00 + + //////////////////////////////////////////////////////////////////*/ + + template class ZtCObjectPtr + { + public : + typedef TType TypeData; + protected: + TType& mr_TypeData; + public : + + ZtCObjectPtr(TType& ArCData):mr_TypeData(ArCData){} + + TType* operator->(){return &mr_TypeData;} + TType& operator* (){return mr_TypeData;} + operator TType& (){return mr_TypeData;} + + public : + };/* + template class ZtCObjectPtr */ + + + /*///////////////////////////////////////////////////////// + + ■ object 를 heap 에 생성하고, 참조 카운트를 이용하여 관리. + + -- 2014-07-20 04:49:00 + + /////////////////////////////////////////////////////////*/ + + template< typename TType, typename TAllocClass=ZCAllocClass + > + class ZtCObjectNew : public TAllocClass //////////////////// + { + public : + typedef TType TypeData ; + typedef TAllocClass ZCAllocator; + private: + + struct StTypeRefCnt + { + TType MO_TypeData; + ZTypInt MI_RefCount; + + StTypeRefCnt(){MI_RefCount=0;} + };/* + struct StTypeRefCnt*/ + + private: + StTypeRefCnt* mp_StTypeRefCnt; + public : + + ZtCObjectNew() + { + mp_StTypeRefCnt = (StTypeRefCnt*) + this->ZCAllocator::NewMem( sizeof(StTypeRefCnt) ); + mp_StTypeRefCnt->MI_RefCount = 1 ; + + new(&mp_StTypeRefCnt->MO_TypeData) TypeData; + }/* + ZtCObjectNew()*/ + + ZtCObjectNew(const TypeData& AR_TypeData) + { + mp_StTypeRefCnt = (StTypeRefCnt*) + this->ZCAllocator::NewMem( sizeof(StTypeRefCnt) ); + mp_StTypeRefCnt->MI_RefCount = 1 ; + + new(&mp_StTypeRefCnt->MO_TypeData) TypeData(AR_TypeData); + }/* + ZtCObjectNew(const TypeData& AR_TypeData)*/ + + template + ZtCObjectNew(TTypeArg1& ArTTypeArg1, TTypeArg2& ArTTypeArg2) + { + mp_StTypeRefCnt = (StTypeRefCnt*) + this->ZCAllocator::NewMem(sizeof(StTypeRefCnt)); + mp_StTypeRefCnt->MI_RefCount = 1 ; + + new(&mp_StTypeRefCnt->MO_TypeData) + TypeData(ArTTypeArg1, ArTTypeArg2); + }/* + template + ZtCObjectNew(TTypeArg1& ArTTypeArg1, TTypeArg2& ArTTypeArg2))*/ + + ZtCObjectNew(const ZtCObjectNew& rhs) + { + mp_StTypeRefCnt=rhs.mp_StTypeRefCnt; ++mp_StTypeRefCnt->MI_RefCount; + }/* + ZtCObjectNew(const ZtCObjectNew& rhs)*/ + + ~ZtCObjectNew() + { + if(--mp_StTypeRefCnt->MI_RefCount<=0) this->ZCAllocator::DeleteMem(mp_StTypeRefCnt); + }/* + ~ZtCObjectNew()*/ + + ZtCObjectNew& operator=(const ZtCObjectNew& rhs) + { + if(this==&rhs || mp_StTypeRefCnt==rhs.mp_StTypeRefCnt) return *this; + + #if(0) + mp_StTypeRefCnt->MO_TypeData = rhs.mp_StTypeRefCnt->MO_TypeData; return *this; + #else + if(--mp_StTypeRefCnt->MI_RefCount<=0) this->ZCAllocator::DeleteMem(mp_StTypeRefCnt); + + mp_StTypeRefCnt = rhs.mp_StTypeRefCnt; ++mp_StTypeRefCnt->MI_RefCount; return *this; + #endif + }/* + ZtCObjectNew& operator=(const ZtCObjectNew& rhs)*/ + + ZtCObjectNew& operator=(const TypeData& AR_TypeData) + { + if(&mp_StTypeRefCnt->MO_TypeData==&AR_TypeData) return *this; + + mp_StTypeRefCnt->MO_TypeData = AR_TypeData; return *this; + }/* + ZtCObjectNew& operator=(const TypeData& AR_TypeData)*/ + + TypeData& operator* (){return mp_StTypeRefCnt->MO_TypeData;} + TypeData* operator->(){return &mp_StTypeRefCnt->MO_TypeData;} + + operator TypeData& (){return mp_StTypeRefCnt->MO_TypeData;} + + ZTypInt GetRefCnt() const{return mp_StTypeRefCnt->MI_RefCount;} + TypeData* GetObjPtr() const{return &mp_StTypeRefCnt->MO_TypeData;} + + public : + };/* + template< typename TType, typename TAllocClass=ZCAllocClass + > + class ZtCObjectNew : public TAllocClass //////////////////*/ + + +#ifdef _DEBUG + + /*///////////////////////////////////////////////////////////////////// + + ■ 멀티쓰레드 환경에서는 반드시 _REENTRANT 이 정의되어 있어야 한다. 이 + 것을 체크하기 위해 쓰레드를 만드는 클래스가 있다면 생성자에서 아래 + 함수를 호출해서 _REENTRANT 가 정의되어 있는지 확인한다. + + -- 2009-12-23 10:38:00 + + /////////////////////////////////////////////////////////////////////*/ + + inline void _DEBUG_REENTRANT_Check() + { + if(_REENTRANT_BOOL_<1) + { + std::fstream fileout("DEBUG.txt", std::ios::out | std::ios::app); + + fileout<<"◆◆ Error! : _REENTRANT is Not Defined In Multi-Thread"< + + using namespace ZNsMain; + + int main() + { + _FUNC_IN_FUNC_START_(My) + (IntI ArgiShowCnt) + { + for(int i=0; iSendPacket((HANDLE)100,"my",2); // 어느 함수가 호출될까. + + 위 코드는 CIOCP::SendPacket() 을 호출하게 된다. + + -- 2009-01-03 13:09:00 + +■ 여러 오브젝트 파일에서 사용되는 문자열 상수는 + + const char* CPC_MySQL_Host="localhost" 이 아니고 + const char* const CPC_MySQL_Host="localhost" 로 선언해야 한다. + +■ 템플릿으로 상속을 구현하면, 템플릿 parameter 에 따라 기반 클래스를 마음대로 바꿀 수가 있다. 이 기능이 상당히 편하 + 긴 한데 조심할 점이 한 가지 있다. + + template + class CMy : public TTypeBase + { + public: + void Init(); + void Fini(); + }; + + 위 클래스 템플릿을 상속해서 CMy2 를 만든다음 + clear() 멤버를 추가한다고 하자. 그러면 + + class CMy2 : public CMy + { + public: + void clear(); + }; + + 위외 같은 형태가 될텐데, 이때 clear() 멤버를 정의하면서 기반클래스인 CMy 의 멤버변수와 함수를 어떻게 + 사용하겠는지 한 번쯤 생각을 하게 된다. 그런데 CMy 의 기반클래스인 CBaseClass 에 대해서는 자칫 생각을 + 못하게 된다. clear() 함수가 어떤 자원을 해제하는 함수라면 CBaseClass 의 관련 자원을 해제하는 처리를 빠트릴 수 있는 + 것이다. 따라서 템플릿 기반의 상속 구현에서 기반클래스의 관련 멤버에 대해서도 어떤 처리가 필요한지 한 번 더 따져봐 + 야 한다. + + 상속클래스를 템플릿 parameter 로 받는 클래스 템플릿을 상속하는 경우에도 마찬가지로 주의해야 한다. + + CHttp.H 파일에서 std::ZNsCGI::ZNsThpe::ZtCTypeLoadDataQuery_T<> template 에서도 clear() 멤버를 Override 하고 있는데, + 위와 상황은 약간 다르지만 유사한 헛점이 생겼던 코드이다. clear() 멤버는 자원을 해제하는 함수인데 이 함수를 재정의 + 하지 않는 상태에서 + + ZtCTypeLoadDataQuery_T<> ::clear() 을 호출하니 + std::CLoadDataBlockOne_T<>::clear() 만을 호출하고 + + 또다른 기반 클래스인 TTypeBase 의 자원을 해제하지 못하고 있었다. 그래서 부랴부랴 TTypeBase 인자에 해당하는 클래스 + 에 clear() 멤버를 추가하고 ZtCTypeLoadDataQuery_T<>::clear() 을 재정의한 함수 정의에, 코드 + + std::CLoadDataBlockOne_T<>::clear() + this->TTypeBase ::clear() + + 을 추가시켰다. 그제야 결과가 정상이었다. 이전에는 이상하게 짝수번 실행시에 결과가 엉뚱하게 나왔었다. clear() 시에 + 기반클래스 TTypeBase 인 + + std::ZNsIFace::CDeriveLoadDataQuery_T + + 클래스에서 멤버 me_ESearch 을 ESearch_Name 으로 초기하지 못하고 있었던 것이다. 그러니까 처음 실행시에는 + + me_ESearch==ESearch_Name 이니까 정상이고 2 번째 실행시에 + me_ESearch!=ESearch_Name 이니까 엉뚱한 결과가 나오고, 이때 우연치 않게도 + me_ESearch==ESearch_Name 으로 다시 초기화되고, 3 번째 실행시에는 + me_ESearch==ESearch_Name 이니까 정상이고... + + 게다가 갑자기 breakpoint 가 먹질 않고... 휴 진땀뺏다. -- 2009-01-05 10:02:00 + +■ CHttp.H 에 가상 기초클래스가 필요한 상황에 어떻게 템플릿으로 구현하는지 그 예가 있다. 여러 개의 상속클래스에서 공 + 통이 되는 멤버를, 상속클래스에서 선언및 정의하는 방법을 사용하고 있다. + + 이 방법을 "가상 상속의 템플릿 구현(TIVI : Template Implementation Of Virtual Inheritance)" 이라고 하자. + + CHttp.H 에서 사용한 이런 기법이 다른 경우에도 적용될 수 있다. 프로그램이 커지면 여러 가지 클래스를 정의하게 되고, + 어떠 클래스를 정의하기 전에, 다른 클래스 정의를 요구하고 또 다른 클래스 object 를 요구할 수 있다. 다른 클래스 정의 + 를 요구하는 경우는 그 클래스 앞에 요구하는 클래스를 미리 정의하면 간단한데, 다른 클래스 object (참조, 포인터) 를 + 외부에서 요구하는 경우는 처리가 복잡해진다. 그때마다 전역 인스턴스를 만들자니 뭔가 찝찝하다. 예를 들어 A, B, C,D,E + 클래스가 있는데 + + B 는 외부의 A 의 object 참조를 요구하고 + C 는 외부의 B 의 object 참조를 요구하고 + D 는 외부의 C 의 object 참조를 요구하고 + E 는 외부의 D 의 object 참조를 요구하는 상황이라고 하자. 그러면 + + A 를 정의하고 A 전역 object 를 만들고 + B 를 정의하고 B 전역 object 를 만들고 + C 를 정의하고 C 전역 object 를 만들고 + D 를 정의하고 D 전역 object 를 만드는 과정을 반복해야 한다. + + 이렇게 하면 전역object 가 어지럽게 널려 있게 된다. 이런 상황에서도 "가상 상속의 템플릿 구현" 을 사용할 수 있겠다. + + -- 2009-01-18 17:48:00 + + 음, "가상 상속의 템플릿 구현" 을 좀 더 곰곰히 생각해 보면, 스트립트 언어에서는 이런 경우를 '어떻게 처리할까' 라는 + 궁금증이 생긴다. 근데 스트립트 언어에서는 데이타형에서 자유롭기 때문에 이런 상황을 풀어 내기가 훨씬 쉬워 보인다. + 데이타형에서 자유롭기 때문에 얻어지는 이 장점이 과연 좋은 것일까. 버그가 더 발생하기 쉽지 않을까. + + -- 2009-01-19 01:21:00 + + 위에서 예로 든 object A,B,C,D,E 의 관계를 이렇게 풀 수도 있겠다. + + A 를 정의하고 + A 의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 B 를 만들고 + B 의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 C 를 만들고 + C 의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 D 를 만든다. + + 이 개념을 가상함수로 풀면, + + A 를 정의하고 + A 의 기초클래스의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 B 를 만들고 + B 의 기초클래스의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 C 를 만들고 + C 의 기초클래스의 참조(나 포인터)를 생성자에서 인수로 받는 클래스 D 를 만든다. + + -- 2009-01-19 01:26:00 + + 이런 상황이 더 복잡해진다면 적절한 작업쓰레드를 모델링해서 해결하는 것도 좋을 것 같다. + + (WTM 은 Working Thread Model) + + A 의 역할을 하는 IOCP 형 작업쓰레드 모델 A-WTM 을 만들고 + B 의 역할을 하는 IOCP 형 작업쓰레드 모델 B-WTM 을 만들고 + C 의 역할을 하는 IOCP 형 작업쓰레드 모델 C-WTM 을 만들고 ... + + 만약 A,B 나 C,D 를 하나의 단위로 묶을 수 있다면, + + A,B 의 역할을 하는 IOCP 형 작업쓰레드 모델 AB-WTM 을 만들고 + C,D 의 역할을 하는 IOCP 형 작업쓰레드 모델 CD-WTM 을 만들고... + + -- + + 이 문제는 COM(Component Object Model) 방식으로 해결할 수도 있겠다. + + cf) std::ZNsIFace::ZIDelgtMSG + + -- 2009-03-09 20:18:00 + + "가상 상속의 템플릿 구현"은 꼭 가상 함수의 다중 상속이 필요한 상황 외에도 클래스 A, B, C, D 가 서로의 인터페이스에 + 접근하는 복잡한 상황에서도 사용할 수 있겠다. 클래스 A, B, C, D 를 상속클래스 템플릿인자를 받도록 선언하고, 클래스 + A, B, C, D 를 상속하는 클래스 E 를 만든 다음에, 이 E 를 통해 A, B, C, D 각 클래스에 접근할 수 있다. 즉 상속클래스 + 가 기반 클래스들의 중간 다리역할을 하고 있는 것이다. + + cf) MainHead_VirtualDeriveTmpl.cpp + + + "가상 상속의 템플릿 구현" 은 CURIOUSLY RECURRING TEMPLATE PATTERN 과 일맥상통한다. + + class template A 가 다수 개의 class B1,B2,B3 의 존재를 알아야 하고, 또 class B1, B2, B3 는 A 의 존재를 알아야 하는 + 순환 인식 구조에서도 적용하면 아주 좋을 것 같다. 또한 class B1, B2, B3 가 서로의 존재를 알아야 할 때도 유용하다. + class B1, B2, B3 의 멤버함수를 호출할 때, A 의 상속클래스 A2 를 넘기면, A2 에 B1, B2, B3 에 접근하는 interface 가 + 있기 때문에, B1 에서 B2 나 B3 의 interface 에 접근할 수가 있는 것이다. + + ex) + + 1) 먼저 상속 클래스를 템플릿 인자로 받는 class template A 를 정의한다. + 2) A 의 상속 클래스에 B1, B2, B3 클래스의 인터페이스가 있다는 가정하에 + B1, B2, B3 클래스의 인터페이스를 사용하는 멤버함수를 A 에 추가한다. + 3) A 의 상속 클래스에서, B1, B2, B3 클래스 object 에 접근할 수 있는, + 인터페이스를 정의한다. + + template + class A + { + public: + void UseB1(){static_cast(this)->GetObjB1().CallFunc();} + void UseB2(){static_cast(this)->GetObjB2().CallFunc();} + void UseB3(){static_cast(this)->GetObjB3().CallFunc();} + void UseExB1(TParent& ArCParent){static_cast(this)->GetObjB1().CallFunc(ArCParent);} + void UseExB2(TParent& ArCParent){static_cast(this)->GetObjB2().CallFunc(ArCParent);} + void UseExB3(TParent& ArCParent){static_cast(this)->GetObjB3().CallFunc(ArCParent);} + }; + + class A2 : public A + { + public: + class B1{public:void CallFunc() {cout<<"Call B1::CallFunc()"<::UseExB1(*this);} + void UseExB2(){A::UseExB2(*this);} + void UseExB3(){A::UseExB3(*this);} + }; + + + A2 myA2; + + myA2.UseB1(); + myA2.UseB2(); + myA2.UseB3(); + myA2.UseExB1(); + myA2.UseExB2(); + myA2.UseExB3(); + + -- 2010-03-12 11:56:00 + + 그런데 가상함수 클래스를 이용하면 더 간단할 수 있다. 예를 들어 클래스 A,B,C 에 접근할 수 있는 인터페이스를 제공하 + 는 가상함수 클래스 IA, IB, IC 를 만들고, 클래스 A, B, C 는 각각 IA, IB, IC 클래스를 상속한다. 그 다음 IA, IB, IC + 의 포인터를 관리하는 singleton object SngtA, SngtB, SngtC 를 정의하고, 클래스 A, B, C 는 생성후, 바로(혹은 빠른 시 + 간 안에), SngtA, SngtB, SngtC 가 관리하는 가상함수 클래스의 포인터를 자신의 포인터로 설정해 준다. + + 이러면 A, B, C 는 singleton object SngtA, SngtB, SngtC 를 통해 서로의 interface 를 호출할 수 있다. 가상함 수의 사 + 용이 부담되지 않는다면 이 방법이 더 편할 수 있다. + + -- 2010-03-13 22:43:00 + +■ 작업쓰레드 pool P1 에서 class A, B 를 사용하는데, A,B 는 P1 보다 먼저 선언해야 하지만, B 는 내부적으로 P1 을 사용 + 하고 있어서 P1 이후에 선언해야 한다고 생각해보자. 그러면 선언/정의 순서가 A => P1 => B 가 된다. 그런데 P1 은 B 라 + 는 자료형을 알아야 하는데, 이것은 P1 의 작업쓰레드의 수행 함수를 템플릿으로 만들어서 인자를 받게 하고, P1 의 Instance + 를 B 에서 만들면서 템플릿 인자로 B 를 넘겨주면 된다. + + 클래스 테플릿 CThreadEx_T<> 와 파일 CProxySockHttpXml.H 을 참고한다. + + -- 2009-08-09 20:23:00 + +■ 기초클래스의 생성자에서 파생클래스의 참조(나 포인터)를 인수로 받는 경우가 있는데, 이때 기초 클래스의 생성자에서는 + 파생클래스의 멤버가 초기화되기 전이므로, 파생 클래스의 멤버 변수에 접근하거나 파생 클래수의 멤버 변수를 사용하는 + 함수를 호출해서는 안된다. 단, 파생클래스의 각 멤버를 초기화하는, 파생클래스의 어떤 멤버 함수를 호출한 후라면 상관 + 없다. + + -- 2009-02-10 23:02:00 + +■ VC++ 2008 에서 "도구 => 옵션 => '프로젝트 밑 솔루션' => VC++ 디렉토리" 에서 해당 라이브러리의 헤더 파일과 라이브러 + 리 파일을 "포함파일" 과 "라이브러리 파일" 에 설정을 했어도 해당 경로에서 라이브러리를 못찾는 경우가 있다. 이때는 + "프로젝트 => 속성" 에서 헤더 파일과 라이브러리 파일의 경로를 또 적어주어야 한다. + + -- 2009-02-27 10:02:00 + +■ 멤버 함수 템플릿은 가상함수가 될 수 없다. -- 2009-02-28 04:21:00 + +■ C# 의 delegate 삼아서 std:ZNsIFace::ZIDelgtMSG 클래스를 설계하였다. 이 object 로부터 메시지를 수신하는 클래스는 이 + 클래스를 상속하거나, 이 클래스를 상속하여 관련 interface 를 재정의한 클래스를 멤버 변수로 가지고 있는 것이 좋다. + 특히 다수의 메시지를 수신받아야 하는 경우에는 다수의 멤버 변수로 설계하는 것이 좋다. + + 결국 ZIDelgtMSG 에서 정한 interface 만 사용할 수 있는 것인데, 이런 때는 COM(Component Object Model) 이 참 편리하게 + 느껴진다. 또한 C++ 표준에도 COM 이 들어가면 좋겠다는 생각을 하게 된다. + + -- 2009-03-01 12:04:00 + +■ 다중 쓰레드 프로그램에서 다소 긴 작업을 처리하는 작업쓰레드가 있고, 이 쓰레드에서 작업을 처리하는 동안 얼마만큼을 + 처리했는지 처리과정을 나타내는 진행 상황 정보 변수를 담은 object 에 자주 조회해야 한다고 해보자. + + (물론, 진행 상황 정보 변수들이 동적할당이 필요없는 데이타라면 동기화가 굳이 필요없으므로, 여기서는 동적 할당이 필 + 요한 변수들이 있다고 가정한다.) + + 1) 작업쓰레드 object 에 주기적으로 polling 하는 경우, + + 이때는 해당 작업쓰레드에서 진행 상황 정보 object 에 진행정보변수를 설정하거나, 다른 쓰레드에서 진행 상황 정보 object + 에 접근할 때에는 동기화를 해주어야 한다. + + 진행상황정보의 읽기 작업(즉 polling)이 갱신작업보다 상당히 많다면 읽기/쓰기 lock 을 사용하는 것도 한 방법이다. + + 2) 작업쓰레드 자체에서 실행 코드의 어떤 지점을 지날 때마다, 작업 진행 정보 object 를 인수로 하여, 어떤 지정된 + 함수를 호출하는 경우, + + 이처럼 작업 쓰레드 자체에서 주기적으로 어떤 함수를 호출하는 경우에는, 동기화가 필요없다. 단, 호출된 함수쪽 에서는 + 경우에 따라 동기화할 필요가 있을 것이다. + + ※ 진행 상황 정보 object 의 멤버 변수들이 불어나서 많아진다면 각각의 진행 상황 정보를 멤버 변수로 만드는 것 보다 + 는 key/value 의 map 으로 구성하는 것도 좋을 것 같다. 이런 목적으로 + + CKeyValueMap_T<> 이나 CKeyValMapPrgs(Sync)_T<> + + 을 설계하였다. + + -- 2009-03-03 07:36:00 + + ※ 진행 상황 정보 object 의 멤버변수에 동작할당이 필요한 문자열이 있다면, 이 문자메모리를 동적으로 할당하지 말고 + 문자 배열로 선언해서 사용할 수도 있겠다. + + -- 2009-03-05 06:20:00 + +■ 서로 다른 다수의 오브젝트가, 다른 다수의 오브젝트에게 서로 다른 메시지를 송신해야 한다고 생각해보자. 각 클래스 인 + 터페이스를 알아야 하고 그러기 위해서는 메시지를 수신하는 클래스의 헤더를, 송신하는 클래스에서 #include 해야 하고, + 또 수신하는 클래스에서 다시 송신하는 클래스에 메세지를 보낼때에는 양방향으로 #include 가 이루어져야 하는 등 포함 + 관계가 아주 복잡해진다. 이것을 해결하기 위해 + + class CKeyValueMap_T< int,std::ZNsIFace::ZIDelgtMSG*, + int,std::ZNsIFace::ZIDelgtMSG*, + /////////////////// > + + 클래스를 설계한다. 이 클래스를 정적object 로 갖는 클래스를 만들고, 이 클래스 헤더를 각각의 메시지 송/수신이 필요한 + 클래스에서 #include 하면 된다. 이 다음 각 메시지 별로 std::ZNsIFace::ZIDelgtMSG 을 상속하는 클래스를 정의하여 사용하자. + + -- 2009-03-06 08:59:00 + +■ Modeless 대화상자에서 Modeless 대화상자를 호출한 부모 윈도우에서 쓰레드가 동작하고 있는 경우, 부모창이 닫히면 Modeless + 대화상자가 자동으로 안닫히는 경우가 있다. 이때는 부모창의 종료이벤트에서 명시적으로 해당 Modeless 를 종료해 주는 + 것이 좋다. + + -- 2009-03-08 21:28:00 + +■ 함수 템플릿의 템플릿 인수가 템플릿인 경우에는 어떻게 전문화하는지, CStringEx.H 의 std::__FastMoveObj() 의 CStringBase_T<> + 템플릿 전문화에 그 예가 있다. + + -- 2009-09-06 07:26:00 + +■ OS 별로 별도의 코딩이 필요한 파일들 + + MainHead.H + MainHeadEx.H + + CFileEx.H + CProcess.H + CNet.H + +■ 도전과 응전을 통한 발전 + + 인간은 누구든 현실에 안주하려는 속성을 지니고 있다. 어느 정도의 단계에 이르면 거기에 만족하고 그만 멈추려 고 한다. + 그런데 인간이 처한 운명은 자꾸만 변하기 때문에 그럴 수가 없다. 운명은 인간에게 다음 단계로 올라가라고 도전장을 던 + 진다. 그 단계에 이르면 다른 도전이 와서 또 다음 단계로 올라가게 한다. 그렇게 죽는 순간까지 인간은 도전을 받고 살아 + 간다. + + - 아놀드 토인비 + + 토인비는 가혹한 자연환경이나 외적의 침입 등 어느 문명권의 존속에 대한 위험을 도전으로 정의하고, 이러한 도전에 대하 + 여 이들 문명권이 응전에 성공하면 그 문명권은 계속 존속 발전할 수 있고 응전에 실패하면 역사 속으로 사라진다고 주장 + 합니다. 재미있는 사실은 도전을 받지 못한 문명 역시 멸망의 길을 걷는다는 것입니다. 문명은 아주 살기 어려운 환경에서 + 발생하는 것이고, 살기 좋은 환경에서는 문명이 발생하지 않음을 알 수 있습니다. + + http://phpschool.com/gnuboard4/bbs/board.php?bo_table=talkbox&wr_id=1473843&page=1 + + -- 2009-04-28 09:16:00 + +■ 템플릿 멤버 함수를 클래스 밖에서 정의하는 코드 예시. + + template struct CShow + { + static void Show(){cout<<"## show : T="< static void Show2(T2); + }; + + template template + void CShow::Show2(T2){cout<<"## show : T2="< 나 CArray_T<> 등의 클래스 를 사용해야 한다. + + -- 2013-07-11 01:26:00 + + □ 네트워크 관련 처리에서, 데이타를 수신 버퍼로 수신하는 상황에서, 수신 버퍼의 최대 크기로 수신한 경우, 더 수신할 + 데이타가 있는지 검사하였는가. + + 이 사항은 MainSSL.H 의 2015-03-06 22:17:00 일자 기록을 참고. https://www.openssl.org 의 데이타를 가져올 때, 응 + 답 본문을 BIO object 에서 읽어 왔는데, 최대 수신 버퍼 크기로 읽어 왔을 때의 처리가 빠져 있었다. 그래서 이상하게 + 본문을 끝까지 받지 못했었다. + + -- 2015-03-08 21:32:00 + + □ 쓰레드풀 같이 object 의 풀을 사용하는 경우, object 을 풀에 반납하고 가져올 때, 종료및 초기화 처리가 되었는가. + + CCtrlAsyncSock.H 파일의 "'코드C2'에 대한 주석" 참고. -- 2015-03-22 17:01:00 + +■ 참조 카운팅 종료 + + object 의 참조 카운팅이 -1 인 경우에만, 어떤 object 를 소멸시키거나, 특정 flow 를 종료하는 것이다. 어떤 object 의 + 참조를 다른 작업 쓰레드에서 사용하는 경우, 그 쓰레드에서 해당 object 에 접근하는 동안에는 다른 쓰레드에서 그 object + 를 소멸시키면 안된다. 이런 때 사용하는 기법이다. + + -- 2013-06-23 19:25:00 + + '참조 카운팅 종료'시에 어떤 종료 행위를 효과적으로 수행하기 위해, 참조 카운팅을 증가/감소시키는 함수는 외부 object + 를 인수로 받아, 그 object 에서 일정한 행위를 수행하게 하면 좋다. + + -- 2013-06-23 19:34:00 + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + + + +#endif //__MAINHEADER_H__