Files
RepoMain/ZCppMain/ZMainHead.H

10581 lines
394 KiB
C++

/*//////////////////////////////////////////////////////////////////////////////////////
■ 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 ZNsIFace 를 만들고 그 안에 둔다. 멤버
변수가 없이 순수 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::ZERun
을 사용하자.
■ 함수가 굳이 어떤 값을 리턴할 필요는 없는데, 함수의 역할이 특정 조건인지 체크해서 그
조건에 맞으면 어떤 작업을 실행한다고 할 때, 이 실행 여부를 굳이 리턴하고자 한다면 bool
형 대신에, 가독성을 위해서 enum std::ZNsEnum::EAct 을 사용하자.
■ call back 함수나 이떤 이벤트마다 실행하는 함수는 접두어 'On' 을 붙이자. 어떤 컨테이너
의 각 원소마다 특정한 처리를 하는 함수에는 'Iter' 를 붙이자.
cf) CDoubleList<int>::IterElement();
'Iter' 대신에 'OnEach' 를 붙여도 좋을 것 같다.
■ 클래스의 초기와, 종료함수를 별도로 지정할 때에는 각각 접두어 Init, Fini 뒤에 적절한
이름을 붙여주자. 클래스의 초기와, 종료함수를 Init, Fini 로만 지정했더니, 나중에는 비
슷비슷한 이름이 많아서 상속할 때 상당히 햇깔렸다.
클래스의 멤버중에 단순히 멤버를 0 과 같은 초기값으로 셋팅하는 함수는 InitVar 라는 함
수명을 사용하자.
■ containter class template 는 TypeData 라는 type 을 가져야 한다. 예를 들어
CObjList<int>::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<class InputIterator, class Function>
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 __ZCPPMAIIN_ZMAINHEAD_H__
#define __ZCPPMAIIN_ZMAINHEAD_H__
#include <cstdio>
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#include <string>
#include <climits>
#include <typeinfo>
#include <wchar.h>
#include <iostream>
#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 <stdint.h>
#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 <TCHAR.H>
#include <WinSock2.h>
#include <windows.h>
// 아래 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<errno.h>
#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 에서 ZCObjList 라든가 여러
// 자료구조에서 쓰는 동기화 뮤텍스를 위해 pthread.h 를 포함한다.
#include <pthread.h>
#elif defined(__unix__)
#include <pthread.h>
#elif defined(__sun__) // In Solaris
#include <pthread.h>
#elif defined(_WIN)
//Don't inclucde
#else
#include <pthread.h>
#endif
#endif //defined(_REENTRANT)
#ifdef _DEBUG
#include<iostream>
#include<fstream>
#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)
#define __for_it( MainType, MainObj, IterVar) \
for ( \
typename MainType:: iterator \
IterVar=MainObj.begin(); \
IterVar<=MainObj.size(); ++IterVar \
)
#define __for_itc(MainType, MainObj, IterVar) \
for ( \
typename MainType::const_iterator \
IterVar=MainObj.cbegin(); \
IterVar<=MainObj.size(); ++IterVar \
)
#define __for_it_r( MainType, MainObj, IterVar) \
for ( \
typename MainType:: iterator \
IterVar=MainObj.end(); \
IterVar>0; --IterVar \
)
#define __for_it_rc(MainType, MainObj, IterVar) \
for ( \
typename MainType::const_iterator \
IterVar=MainObj.cend(); \
IterVar>0; --IterVar \
)
#define _FOR_ITER_EASY_START0(MainType, MainObj, IterVar, SizeVar) \
{ \
typedef typename MainType::TypeSize IterTypeSize ; \
ZNsMain::IterEasyID IterVar = MainObj.ItHID(); \
\
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
#define _FOR_ITER_EASY_CLOSE0(MainType, MainObj, IterVar, SizeVar) \
MainObj.ItNext(IterVar); } \
}
#define _FOR_ITER_EASY_START0_C(MainType, MainObj, IterVar, SizeVar) \
{ \
typedef typename MainType::TypeSize IterTypeSize ; \
ZNsMain::IterEasyIDc IterVar = MainObj.ItHIDc(); \
\
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
#define _FOR_ITER_EASY_CLOSE0_C(MainType, MainObj, IterVar, SizeVar) \
MainObj.ItNext(IterVar); } \
}
#define _FOR_ITER_EASY_START0_R(MainType, MainObj, IterVar, SizeVar) \
{ \
typedef typename MainType::TypeSize IterTypeSize ; \
ZNsMain::IterEasyID IterVar = MainObj.ItTID(); \
\
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
#define _FOR_ITER_EASY_CLOSE0_R(MainType, MainObj, IterVar, SizeVar) \
MainObj.ItPrev(IterVar); } \
}
#define _FOR_ITER_EASY_START0_RC(MainType, MainObj, IterVar, SizeVar) \
{ \
typedef typename MainType::TypeSize IterTypeSize ; \
ZNsMain::IterEasyIDc IterVar = MainObj.ItTIDc(); \
\
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
#define _FOR_ITER_EASY_CLOSE0_RC(MainType, MainObj, IterVar, SizeVar) \
MainObj.ItPrev(IterVar); } \
}
/*######################################################################
■ _FOR_ITER_EASY_START0 와 _FOR_ITER_EASY_CLOSE0 예제.
typedef ZtCObjList<int> CObjList;
CObjList myList;
myList.AddTail(1);
myList.AddTail(2);
myList.AddTail(3);
_FOR_ITER_EASY_START0 (CObjList, myList, VH_NowIter, i)
{
cout<<"# list : "<<myList.ItD(VH_NowIter)<<endl;
}
_FOR_ITER_EASY_CLOSE0 (CObjList, myList, VH_NowIter, i)
_FOR_ITER_EASY_START0_RC(CObjList, myList, VH_NowIter, i)
{
cout<<"# list rev const: "<<myList.ItD(VH_NowIter)<<endl;
}
_FOR_ITER_EASY_CLOSE0_RC(CObjList, myList, VH_NowIter, i)
-- 2025-10-14 16:34
######################################################################*/
namespace ZNsMain
{
typedef int ZTypInt ;
typedef int ZTypIntE ; // int enum : 다른 enum 형끼리 비교할 일이 있을 때, 이 자료로 형변환한다.
typedef int ZTypIntEnum ;
typedef long ZTypIntLong ;
typedef short ZTypIntShort;
typedef int ZTypIntI ; // 정수를 가장 잘 대표할 수 있는 자료형. 필요에 따라 long 이나 short 으로 typedef 할 수도 있다.
typedef long ZTypIntL ;
typedef short ZTypIntS ;
typedef long ZTypLong ;
typedef short ZTypShort ;
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 ZTypUWCha ;
/* 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 ZTypLength ; // 문자열의 길이를 나타내는 자료형.
// 송수신 버퍼의 크기 자료형으로도 쓰인다.
typedef unsigned __int64 ZTypULen ;
typedef unsigned __int64 ZTypULength ;
#else
typedef long ZTypLength ;
typedef unsigned long ZTypULen ;
typedef unsigned long ZTypULength ;
#endif
#else // !defined(__CPU_BIT_CNT__) || __CPU_BIT_CNT__<64
typedef long ZTypLength ;
typedef unsigned long ZTypULen ;
typedef unsigned long ZTypULength ;
#endif // !defined(__CPU_BIT_CNT__) || __CPU_BIT_CNT__<64
#ifdef _WIN
typedef __int64 ZTypLengthFile ; // 파일의 크기를 나타내는 자료형.
#else
typedef long ZTypLengthFile ; // 파일의 크기를 나타내는 자료형.
#endif
typedef ZTypLengthFile ZTypLengthF ;
#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
typedef const int ZTycInt ;
typedef const int ZTycIntI ;
typedef const long ZTycLong ;
typedef const long ZTycIntL ;
typedef const short ZTycShort ;
typedef const short ZTycIntS ;
typedef const char ZTycChar ;
typedef const wchar_t ZTycCharW ;
typedef const ZTypLLong ZTycLLong ;
typedef const ZTypULLong ZTycULLong ;
typedef const ZTypIntLL ZTycIntLL ;
typedef const ZTypIntULL ZTycIntULL ;
typedef const ZTypIntPtr ZTycIntPtr ;
typedef const ZTypIntUPtr ZTycIntUPtr;
typedef const char ZTycChar ;
typedef const wchar_t ZTycWChar ;
typedef const char* ZTycPChar ;
typedef const wchar_t* ZTycPWChar ;
#ifdef _WIN32
typedef HANDLE ZTypeID;
#else
typedef int ZTypeID;
#endif
typedef class ZCIterEasy{} IterEasy, *IterEasyID ;
typedef const IterEasy* IterEasyIDc;
/*///////////////////////////////////////////////////////////////////////////////
■ typedef const IterEasyID IterEasyIDc;
라고 하면, IterEasy * const 이지, IterEasy const * 가 아니다! -- 2025-10-14 19:50
■ cf) _FOR_ITER_EASY_START0 , _FOR_ITER_EASY_CLOSE0 -- 2025-10-14 16:36
■ 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 이름
typeid(IterEasyIDc).name() 으로 구한 값
이 IterEasyID 의 name() 값과 같다.
-- 2015-11-07 21:34:00
typedef class ZCIterEasy{} IterEasy, *IterEasyID ;
typedef const IterEasyID IterEasyIDc;
라고 하면, IterEasyIDc 는
IterEasy const * 가 아니고 IterEasy * const
이다.
///////////////////////////////////////////////////////////////////////////////*/
class ZCEndian
{
private:
static const unsigned int SUI_Int ;
static const unsigned char* const SPC_Char;
public :
static const bool SB_IsBig ;
static const bool SB_IsLittle ;
public :
};/*
class ZCEndian*/
const unsigned int ZCEndian::SUI_Int = 1 ;
const unsigned char* const ZCEndian::SPC_Char =
reinterpret_cast<const unsigned char*>(&ZCEndian::SUI_Int) ;
const bool ZCEndian::SB_IsBig = (int(ZCEndian::SPC_Char[0]) ==1 ) ;
const bool ZCEndian::SB_IsLittle = (int(ZCEndian::SPC_Char[0]) !=1 ) ;
class ZCEmpty
{
/*///////////////////////////////////////////////////////////////////////////
■ 템플릿 정의에서 비어있는 클래스를 요구하는 경우가 있다.
■ 또한 여러 개의 템플릿 인자를 가진 클래스 템플릿의 특정 인자에 대하여 부분
특수화를 하는 경우, 부분 특수화 되는 인수의 type 을, 특수화되지 않는 최초
의 템플릿 정의 부분에서 무엇으로 할 지 고민되는 경우가 있다면, 이때 고민
하지 말고 ZCEmpty 를 써버리자.
-- 2010-05-04 02:29:00
어, 근데 템플릿 인자에 void 를 사용할 수도 있다. 이것을 다소 늦게 알았는데,
그래도 비어 있는 클래스를 상속할 경우, 커파일러가 크기를 0 으로 해놓는 장점
이 있으니까 일단 그냥 둔다. 만약 void 를 사용하게 되면, void 를 템플릿 인자
로 사용하는 버전과 사용하지 않는 버전으로 항상 정의를 해주어야 하는 성가신
점이 있다.
-- 2012-09-01 17:26:00
///////////////////////////////////////////////////////////////////////////*/
};/*
class ZCEmpty*/
namespace ZNsIFace
{
// 이 이름 공간안에 interface 가 되는 class (템플릿) 가 온다.
}/*
namespace ZNsIFace*/
namespace ZNsIFaceEx
{
// ZNsIFace 에는 주로 interface 가 있다면,
// ZNsIFaceEx 에는 실제로 동작하는 코드가 온다.
// 따라서 여기에 오는 클래스는 주로 ZNsIFace 에 이미 있는 것이다.
// 다만, ZNsIFace 의 클래스는 주로 ZI 로 시작한다면
// ZNsIFaceEx 의 클래스는 주로 ZC 로 시작한다.
// -- 2025-09-13 01:06
}/*
namespace ZNsIFaceEx*/
namespace ZNsEnum
{
// ECompareResult 는 어떤 두 개의 값을 비교한 결과를 표시한다.
// ZftGetCompareCode() 나 class ZtCCompare<> 에서 사용할 것이다.
enum ZECompareResult
{
ZECompareResult_Equal= 0, // 서로 같다.
ZECompareResult_More = 1, // 왼쪽이 크다.
ZECompareResult_Less =-1 // 오른쪽이 크다.
};/*
enum ZECompareResult*/
}/*
namespace ZNsEnum*/
/*//////////////////////////////////////////////////////////////////////
■ ZtCCharInt 는 문자형 TTypChar 을 충분히 표현할 수 있는 정수형을 정의
cf) 'char 의 int 확장에 따른 문제의 코드'
cf) ZtCCharInt<char>::TypeInt, ZtCCharInt<wchar_t>::TypeInt
-- 2025-10-08 09:37
//////////////////////////////////////////////////////////////////////*/
namespace ZNsIn
{
const int CI_Char1Byte = 1;
const int CI_Char2Byte = 2;
const int CI_Char4Byte = 4;
}/*
namespace ZNsIn*/
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
template<int TTyiByteSize> class ZtCCharIntBySize
{ public: typedef ZTypLong TypeInt; };
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
template<> class ZtCCharIntBySize<ZNsIn::CI_Char1Byte>
{ public: typedef ZTypInt TypeInt; };
template<> class ZtCCharIntBySize<ZNsIn::CI_Char2Byte>
{ public: typedef ZTypInt TypeInt; };
template<> class ZtCCharIntBySize<ZNsIn::CI_Char4Byte>
{ public: typedef ZTypLong TypeInt; };
template<typename TTypChar> class ZtCCharInt
{ public: typedef typename ZtCCharIntBySize<sizeof(TTypChar)>::TypeInt TypeInt; };
template<> class ZtCCharInt<char >
{ public: typedef typename ZtCCharIntBySize<sizeof(char) >::TypeInt TypeInt; };
template<> class ZtCCharInt<wchar_t>
{ public: typedef typename ZtCCharIntBySize<sizeof(wchar_t) >::TypeInt TypeInt; };
template<typename TTyChar, typename TTyiLength> ZTypIntE ZftGetCompareCode
(
const TTyChar* ZApcLeft , TTyiLength ZAiLenLeft ,
const TTyChar* ZApcRight, TTyiLength zAiLenRight
)
/*######################################################################*/
{
if(ZAiLenLeft<1 && zAiLenRight<1)
return ZNsEnum::ZECompareResult_Equal;
typedef typename ZtCCharInt<TTyChar>::TypeInt TypeInt;
TTyiLength ViLoopCnt =
(ZAiLenLeft<=zAiLenRight ? ZAiLenLeft : zAiLenRight);
__for0(TTyiLength, i, ViLoopCnt)
{
if(TypeInt(ZApcLeft[i]) > TypeInt(ZApcRight[i])) return ZNsEnum::ZECompareResult_More;
if(TypeInt(ZApcLeft[i]) < TypeInt(ZApcRight[i])) return ZNsEnum::ZECompareResult_Less;
}/*
__for0(TTyiLength, i, ViLoopCnt)*/
if(ZAiLenLeft==zAiLenRight) return ZNsEnum::ZECompareResult_Equal;
if(ZAiLenLeft> zAiLenRight) return ZNsEnum::ZECompareResult_More ;
if(ZAiLenLeft< zAiLenRight) return ZNsEnum::ZECompareResult_Less ;
return ZNsEnum::ZECompareResult_Equal;
}/*
template<typename TTyChar, typename TTyiLength> ZTypIntE ZftGetCompareCode
(
const TTyChar* ZApcLeft , TTyiLength ZAiLenLeft ,
const TTyChar* ZApcRight, TTyiLength zAiLenRight
)
########################################################################*/
/* 어떤 변수를 강제적으로 참조로 인식하게 하는 클래스. 인수를 참조로
넘어가게 하고 싶을 때 사용한다. class ZtCCheckRef 에서 사용하고 있다.
-- 2021-04-10 16:15
*/
template<typename TTypType> class ZtCRef
{
public :
typedef TTypType& TypeData ;
typedef TTypType& TypeRef ;
typedef TTypType TypeRaw ;
typedef TTypType TypeConst;
private:
TypeData mr_Data;
public :
ZtCRef(TypeData AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeData GetData(){return mr_Data;}
public :
};/*
template<typename TTypType> class ZtCRef*/
template<typename TTypType> class ZtCRef<TTypType&>
{
public :
typedef TTypType& TypeData ;
typedef TTypType& TypeRef ;
typedef TTypType TypeRaw ;
typedef const TTypType& TypeConst;
private:
TypeRaw& mr_Data;
public :
ZtCRef(TypeRef AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeRef GetData(){return mr_Data;}
public :
};/*
template<typename TTypType> class ZtCRef<TTypType&>*/
template<typename TTypType> class ZtCRef<const TTypType&>
{
public :
typedef const TTypType& TypeData ;
typedef const TTypType& TypeRef ;
typedef const TTypType TypeRaw ;
typedef const TTypType& TypeConst;
private:
TypeRaw& mr_Data;
public :
ZtCRef(TypeRef AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeRef GetData(){return mr_Data;}
public :
};/*
template<typename TTypType> class ZtCRef<const TTypType&>*/
template<typename TTypType> inline ZtCRef<TTypType>
ZftMakeCRef(TTypType& AR_TypeData){ return ZtCRef<TTypType> (AR_TypeData );}
template<typename TTypType> inline ZtCRef<TTypType>*
ZftMakeCPtr(TTypType& AR_TypeData){ return (ZtCRef<TTypType>*)(&AR_TypeData);}
/*////////////////////////////////////////////////////////////////////////////////
■ ZftMakeCPtr() 은 인수 AR_TypeData 이 ZtCRef<TTypType>* 인 것처럼 반환한다.
그래서 template<typename TType> class ZtCCheckRef< ZtCRef<TType>* > 에서 사용할
것이다.
-- 2025-08-07 17:16
■ 사용례는 ZCppMain/ZtCArray.H 의 IterElement() 의 주석에 있다.
■ 아래 ZftMCR() 와 ZftMCP() 는 위 함수명을 더 축약한 것이다. -- 2025-08-07 17:41
////////////////////////////////////////////////////////////////////////////////*/
template<typename TTypType> inline ZtCRef<TTypType>
ZftMCR(TTypType& AR_TypeData){ return ZtCRef<TTypType> (AR_TypeData );}
template<typename TTypType> inline ZtCRef<TTypType>*
ZftMCP(TTypType& AR_TypeData){ return (ZtCRef<TTypType>*)(&AR_TypeData);}
/* template 인수에 ZtCRef 가 있으면, 해당 값을 참조로 인식하고
그렇지 않으면, 일반적인 복사해서 전달되는 값으로 인식한다.
ZtCArray.H 같은 자료 구조에서 사용하고 있다.
-- 2021-04-10 16:15
*/
template<typename TType>
class ZtCCheckRef /*###############################################*/
{
public :
typedef TType TypeData;
typedef TType TypeRaw ;
private:
TypeData mr_Data;
public :
ZtCCheckRef(TypeData AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeData GetData(){return mr_Data;}
public :
static TypeData PassData(TypeData AO_Data){return AO_Data;}
};/*
template<typename TType>
class ZtCCheckRef #################################################*/
/* ZtCRef 전문화 */
template<typename TType>
class ZtCCheckRef< ZtCRef<TType> > /*##############################*/
{
public :
typedef TType& TypeData;
typedef TType TypeRaw ;
typedef ZtCRef<TType> ZCRef ;
private:
TypeData mr_Data;
public :
ZtCCheckRef(TypeData AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeData GetData(){return mr_Data;}
public :
static TypeData PassData(TypeData AO_Data){return AO_Data;}
static TypeData PassData(ZCRef& AO_Data){return AO_Data.GetData();}
};/*
template<typename TType>
class ZtCCheckRef< ZtCRef<TType> > ################################*/
/*///////////////////////////////////////////////////////////////////////
■ ZtCRef* 전문화
아래 함수
template<typename TTypType> inline
ZtCRef<TTypType>* ZftMakeCPtr(TTypType& AR_TypeData)
{ return (ZtCRef<TTypType>*)(&AR_TypeData); }
를 통해, 생성된 포인터에 대해서, 정적 멤버 PassData() 로
TypeRaw* 로 강제변환하고 있다. 그래서 ZtCRef<TTypType> 객
체의 생성없이 TypeRaw 를 참조로 다룰려고 하는 것이다.
-- 2025-08-07 17:19
///////////////////////////////////////////////////////////////////////*/
template<typename TType>
class ZtCCheckRef< ZtCRef<TType>* > /*#############################*/
{
public :
typedef TType& TypeData;
typedef TType TypeRaw ;
typedef ZtCRef<TType> ZCRef ;
private:
TypeData mr_Data;
public :
ZtCCheckRef(TypeData AR_TypeData) : mr_Data(AR_TypeData){}
public :
TypeData GetData(){return mr_Data;}
public :
static TypeData PassData(TypeData AO_Data){return AO_Data;}
static TypeData PassData(ZCRef& AO_Data){return AO_Data.GetData();}
static TypeData PassData(ZCRef* AP_CRef)
{ return *reinterpret_cast<TypeRaw*>(AP_CRef); }
};/*
template<typename TType>
class ZtCCheckRef< ZtCRef<TType>* > ###############################*/
template<typename TType> class ZtCCheckConstRef
{
public: enum {ZEConstRef = 0};
};/*
template<typename TType> class ZtCCheckConstRef*/
template<typename TType> class ZtCCheckConstRef<const TType&>
{
public: enum {ZEConstRef = 1};
};/*
template<typename TType> class ZtCCheckConstRef<const TType&>*/
namespace ZNsType
{
/*/////////////////////////////////////////////////////////////////////////////////////////
■ (주로 클래스) 템플릿에는 typename 인수를 10 개 이상 요구하는 복잡한 템플릿이 있는데 이런
템플릿의 typename 을 미리 예를 들어 명시함으로서 그 템플릿의 typename 을 지정하기 쉽도록
가이드라인을 제시하는 역할의 어떤 클래스나 데이타 타입이 올 수 있는데 이런 자료형이 이
이름공간에 온다. 어떤 데이타타입을 주로 typedef 하는 클래스라면 접두어 ZtCType 를 붙인다.
■ ZtCTypeCRTP<> 는 어떤 클래스 템플릿이 CRTP(CURIOUSLY RECURRING TEMPLATE PATTERN) 를 사용
하는지 아닌지를 알려준다. ZtCTypeCRTP<> 을 설계하지 않는다면, 같은 기능을 하기 위해, 클
래스를 2 개(CRTP 를 사용하는 클래스와, 그렇지 않은 클래스)를 만들어야 했을 것이다.
-- 2010-03-12 20:00:00
class ZtCTypeCRTP 는 상속 클래스만을 표시하고,
class ZtCTypeCRTP2 는 상속 클래스와 기반 클래스 모두를 표시한다.
어쩌면 모든 상속 클래스는 내부적으로, ZtCTypeCRTP 클래스를 갖는 원칙을 세우는 것도 좋겠
다. 그래서 상속 클래스가 CDerive0 라면, 기반 클래스에 접근하고 싶을 때,
CDerive0::ZtCTypeCRTP::TypeData
형식으로 일관성있게 접근하도록 하는 것이다. 그러자면 다중 상속의 경우에 문제가 있겠네.
-- 2021-03-25 16:01
■ 또한 이 이름 공간에 있는 클래스는 TypeData 라는 자료형을 갖는 것으로 하자.
-- 2011-10-18 21:51:00
/////////////////////////////////////////////////////////////////////////////////////////*/
/*#########################################################################################
■ 2번 template parameter 가 bool TTypebUseCRTP 인데, 만약 TTypeChild 가 유효한 자료형이라
면, TTypebUseCRTP 이 true 인 것이 맞겠으나, DEBUG 등의 특수한 용도로 TTypebUseCRTP 을
false 로 설정할 수 있게 한 것이다.
-- 2025-09-28 08:41
#########################################################################################*/
template< typename TTypeChild=ZCEmpty, bool TTypebUseCRTP =false
>
class ZtCTypeCRTP ////////////////////////////////////////////////
{
public:
typedef TTypeChild TypeData;
public:
enum{ZEUseCRTP=(ZTypIntE)TTypebUseCRTP};
public:
};/*
template< typename TTypeChild=ZCEmpty, bool TTypebUseCRTP =false
>
class ZtCTypeCRTP //////////////////////////////////////////////*/
#if(_CODE_OLD_)
/*#########################################################################################
■ ZtCTypeCRTP2 이 필요한 곳에 ZtCTypeNowCRTP 을 사용하자. -- 2025-09-28 09:25
ZtCBaseList 에서 ZtCTypeCRTP 와 ZtCTypeNowCRTP 을 사용하고 있다.
#########################################################################################*/
template< typename TTypeChild = ZCEmpty , ////////////////////
typename TTypeBase = ZCEmpty ,
bool TTypebUseCRTP= false
>
class ZtCTypeCRTP2 ///////////////////////////////////////////////
{
public:
typedef TTypeChild TypeData;
typedef TTypeBase TypeBase;
public:
enum{ZEUseCRTP=(ZTypIntE)TTypebUseCRTP};
public:
}; /*
template< typename TTypeChild = ZCEmpty , ////////////////////
typename TTypeBase = ZCEmpty ,
bool TTypebUseCRTP= false
>
class ZtCTypeCRTP2 /////////////////////////////////////////////*/
#endif //_CODE_OLD_
/*//////////////////////////////////////////////////////////////////////////////////////////
■ class ZtCTypeCRTP2<> 이 왜 필요한지, 그리고 사용례는 예전 파일 CWorkPool.H 의
'주석-CCtrlAllocWork::CRTP2'를 참고한다.
-- 2012-09-20 09:46:00
■ 해당 코드는 대충 이렇다. -- 2025-09-28 02:41
template< typename TWork ,
typename TWorkExec , // 작업(TWork)에 대하여 어떤 처리를 하는 클래스
typename TWorkArg =const TWork& ,
typename TBarrier =std::CBarrier_T<> , // 작업 쓰레드의 시작 및 종료 대기 barrier
typename TSyncWait =std::CThreadSemaphore,
typename TSyncExec =std::CDefLockEasy ,
typename TWorkList =NsCPP::CObjList<TWork,TWorkArg> , // 작업 큐 컨테이너
typename TTypeBase =NsIFace::CAllocWork_BASE_T<TWork>,
typename TFetchWork=TWorkList , // 작업 큐에서 작업을 가져오는 컨테이너.
typename TTypeCRTP =std::NsType::CTypeCRTP2_T< NsIFace::ICtrlAllocWork, NsIFace::ICtrlAllocWork >
>
class CTypeCtrlAllocWork_T //////////////////////////////////////////////////////////////////////////////////
{
public:
class CThread ;
class CBaseClass;
typedef TWork CWork ;
typedef TWorkArg CWorkArg ;
typedef TWorkExec CWorkExec ;
typedef TBarrier CBarrier ;
typedef TSyncWait CSyncWait ;
typedef TSyncExec CSyncExec ;
typedef TWorkList CWorkList ;
typedef TFetchWork CFetchWork;
typedef TTypeCRTP CTypeCRTP ;
typedef typename TWorkList::TypeAlloc CAlloc ;
typedef std::CAutoKey_T<CSyncExec> CAutoKey ;
typedef NsCPP::CObjList
<
CThread ,
const CThread&,
CAlloc
> CThreadList;
typedef typename CThreadList::CLink CThreadLink;
#define _CAllocWork_BASE_ std::CAllocWork_T< \
CWork , \
CWorkArg , \
CSyncWait , \
CSyncExec , \
CWorkList , \
CThread , \
CBaseClass , \
std::NsType::CTypeCRTP_T<CAllocWork, true> >
class CAllocWork : public _CAllocWork_BASE_
{
// some code
}
};
template<typename TTypeCtrlAllocWork>
class CCtrlAllocWork_T : protected TTypeCtrlAllocWork::CSyncKey ,
protected TTypeCtrlAllocWork::CAllocWork,
protected TTypeCtrlAllocWork::CTypeCRTP::TypeBase
{
public :
enum{EMaxThreadCnt=1}; typedef NsEnum::EThreadPoolStep EPoolStep;
public :
typedef typename TTypeCtrlAllocWork::CWork CWork ;
typedef typename TTypeCtrlAllocWork::CWorkArg CWorkArg ;
typedef typename TTypeCtrlAllocWork::CWorkExec CWorkExec ;
typedef typename TTypeCtrlAllocWork::CThread CThread ;
typedef typename TTypeCtrlAllocWork::CSyncKey CSyncKey ;
typedef typename TTypeCtrlAllocWork::CSyncExec CSyncExec ;
typedef typename TTypeCtrlAllocWork::CAutoKey CAutoKey ;
typedef typename TTypeCtrlAllocWork::CAllocWork CAllocWork ;
typedef typename TTypeCtrlAllocWork::CBaseClass CBaseClass ;
typedef typename TTypeCtrlAllocWork::CWorkList CWorkList ;
typedef typename TTypeCtrlAllocWork::CFetchWork CFetchWork ;
typedef typename TTypeCtrlAllocWork::CThreadList CThreadList;
typedef typename TTypeCtrlAllocWork::CThreadLink CThreadLink;
typedef typename TTypeCtrlAllocWork::CTypeCRTP CTypeCRTP ;
// some code
void SetCloseMark(CWork& ARR_CWork)
{
if(CTypeCRTP::EUseCRTP>0)
{
typedef typename CTypeCRTP::TypeData CCtrlAllocWorkEx;
#if(_CODE_NEW_)
static_cast<CCtrlAllocWorkEx&>(*this). // 코드-CCtrlAllocWork::CRTP2
SetCloseMarkInChild(RR(ARR_CWork)); return;
#else
((CCtrlAllocWorkEx&)(*this)). // 코드-CCtrlAllocWork::CRTP
SetCloseMarkInChild(RR(ARR_CWork)); return;
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////
■ 주석-CCtrlAllocWork::CRTP2
이전에는 상속 클래스의 SetCloseMarkInChild() 을 사용하기 위해 위의 '코드-CCtrlAllocWork::CRTP'
를 사용하였으나 약간의 안전성 상승을 위해, std::NsType::CTypeCRTP2_T<> 을 긴급히 정의하고, NsT
ype::CTypeCtrlAllocWork_T<> 의 템플릿 인수에 typename TTypeCRTP 를 추가한 다음, '코드-CCtrlAll
ocWork::CRTP2' 를 사용하게 되었다. 그래서 class CCtrlAllocWork_T<> 이
TTypeCtrlAllocWork::CTypeCRTP::TypeBase
을 상속하고 있다. 이 TypeBase 는 SetCloseMarkInChild(CWork&) 함수를 가져야 한다.
-- 2012-09-20 09:43:00
■ NsType::CTypeCRTP2_T<> 는 NsType::CTypeCRTP_T<> 에서 TypeBase 가 추가된 것이다.
-- 2012-09-20 09:57:00
//////////////////////////////////////////////////////////////////////////////////////////////////
}
CWorkExec::SetCloseMark(RR(ARR_CWork));
}
//void SetCloseMark(CWork& ARR_CWork)
// some code
}
즉 아래 코드로
typedef typename CTypeCRTP::TypeData CCtrlAllocWorkEx;
CCtrlAllocWork_T 의 상속 클래스에 접근하고 있는데, 이것은 좀 이상하다.
즉 CTypeCRTP::TypeData 은 NsIFace::ICtrlAllocWork 이기 때문이다. 예전
코드라 그런지 나쁜 냄새가 난다.
-- 2025-09-28 07-27
//////////////////////////////////////////////////////////////////////////////////////////*/
/*#########################################################################################
■ class ZtCTypeCRTP<> 의 단점은 상속하지 않은 class 형은 알 수 없는데, 이것을 알아내기 위해
class ZtCTypeNowCRTP<>
을 설계한다. 이 클래스의 사용예는 예전 파일 CCtrlAsyncSock.H 에 있었다.
-- 현재(2025-08-02 22:37) CCtrlAsyncSock.H 는 없다.
아래 코드에서 TAsyncServ 의 상속 클래스가
없다면, CMainServ 는 TAsyncServ 과 같고,
있다면, CMainServ0 가 상속 클래스
가 된다.
typedef typename TAsyncServ::ZtCTypeCRTP ZtCTypeCRTP ;
typedef typename ZtCTypeCRTP ::TypeData CMainServ0 ;
typedef std::ZNsType::ZtCTypeNowCRTP<
TAsyncServ, CMainServ0>::TypeData CMainServ ;
CMainServ& VR_CMainServ=
static_cast<CMainServ&>(ArCAsyncServ);
ZtCTypeNowCRTP<> 이 없었을 때에는 TAsyncServ 이 상속 클래스를 갖지 않은 경우, CMainServ0 이 ZCEmpty 가 되어서,
컴파일 에러를 피하기가 매우 복잡한 경우가 있었다. 지금은 상속 클래스가 없다면 그냥 자기 자신의 인터페이스를
사용하니까 컴파일 에러가 전혀 없다.
정말 멋진 기교가 아닌가. C++ 의 향기에 잠시 취해 보자. -- 2013-06-10 00:33:00
■ ZtCTypeNowCRTP 의 template parameter 에 bool TTypebUseCRTP 추가. -- 2025-09-28 15:55
TTypeChild 가 ZCEmpty 이거나 TTypebUseCRTP 이 false 이면, 아래가 된다.
public: enum{ZEUseCRTP=0};
public: typedef TTypeNow TypeData;
public: typedef TTypeNow TypeBase;
그리고 TTypeChild 가 ZCEmpty 이고 TTypebUseCRTP 이 false 인 경우도 전문화해주어야 한다.
class ZtCTypeNowCRTP<TTypeNow, ZCEmpty, false>
■ 3번 template parameter 가 bool TTypebUseCRTP 인데, 만약 TTypeChild 가 유효한 자료형이라
면, TTypebUseCRTP 이 true 인 것이 맞겠으나, DEBUG 등의 특수한 용도로 TTypebUseCRTP 을
false 로 설정할 수 있게 한 것이다.
주로 ZtCTypeCRTP 와 같이 사용해, 가상 함수를 사용하지 않고도 상속을 통해 다형성을 구현하
거나 기능 확장을 하고 싶을 때 사용한다. 보통 CRTP 는 상속을 전제로 하는 상황에서 주로 쓰
이지만, ZtCTypeNowCRTP 는 꼭 상속을 강제하지 않는다.
사용예는 ZtCBaseList 에 있다.
-- 2025-09-28 16:13
#########################################################################################*/
template
<typename TTypeNow, typename TTypeChild, bool TTypebUseCRTP>
class ZtCTypeNowCRTP
{
public: enum{ZEUseCRTP=(ZTypIntE)TTypebUseCRTP};
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public: typedef TTypeChild TypeData;
public: typedef TTypeNow TypeBase;
};
template
<typename TTypeNow, typename TTypeChild>
class ZtCTypeNowCRTP<TTypeNow, TTypeChild, false /*++*/ >
{
public: enum{ZEUseCRTP=0};
public: typedef TTypeNow TypeData;
public: typedef TTypeNow TypeBase;
};
template
<typename TTypeNow, bool TTypebUseCRTP>
class ZtCTypeNowCRTP<TTypeNow, ZCEmpty , TTypebUseCRTP>
{
public: enum{ZEUseCRTP=0};
public: typedef TTypeNow TypeData;
public: typedef TTypeNow TypeBase;
};
template
<typename TTypeNow>
class ZtCTypeNowCRTP<TTypeNow, ZCEmpty , false /*++*/ >
{
public: enum{ZEUseCRTP=0};
public: typedef TTypeNow TypeData;
public: typedef TTypeNow TypeBase;
};
/////////////////////////////////////////////////////////
namespace ZNsTmplParam
{
/*//////////////////////////////////////////////////////////////////////////
■ 이 이름 공간에는 어떤 템플릿의 인수가 많고, 이 인수가 몇 개의 인수가 기본
값을 갖는 경우, 끝 부분에 있는 기본값 정의 인수에 명시적인 자료형을 지정
해야 할 때, 그 이전의 기본 인수에 대해서도 일일이 지정을 해야 하는데, 이
런 불편을 일부 덜기 위해서 기본값 정의 순서가 다른 template 을 설계한다.
여기에 놓이는 클래스는 CParam~ 으로 시작하자.
■ ZNsTmplParam 이름공간은 꼭 ZNsType 에만 있을 필요는 없다. 그보다 더 적절한
장소가 있다면 그 곳에 선언하자.
//////////////////////////////////////////////////////////////////////////*/
}/*
namespace ZNsTmplParam*/
}/*
namespace ZNsType*/
/*//////////////////////////////////////////////////////////////
■ 가끔 템플릿으로 클래스 설계를 하다보면 템플릿의 parameter 가
포인터나 참조일 경우, 무엇의 포인터나 참조형인지 알고 싶을 때
가 있다. 이런 경우에 ZtCTypeData<> 를 사용한다.
cf)
cout<<typeid(std::ZtCTypeData<ZTypIntI >::TypeData).name()<<endl;
cout<<typeid(std::ZtCTypeData<ZTypIntI*>::TypeData).name()<<endl;
cout<<typeid(std::ZtCTypeData<ZTypIntI&>::TypeData).name()<<endl;
-- 2010-01-15 00:11:00
■ ZtCTypeData<>::GetObjRef(~) 는 주로 참조나 포인터 자료형에 대
해, 무슨 자료형에 대한 참조 혹은 포인터인지 판단해서, 가급적
참조로 전달하도록 한다. 참조도 아니고 포인터도 아닌 자료형이
면, 당연히 보통의 복사 생성으로 자료형의 값을 반환한다.
주로 (멤버) 함수 템플릿에서 사용할 것이다. -- 2025-09-28 22:08
■ --
//////////////////////////////////////////////////////////////*/
typedef void (*ZfpNone)(void*); void ZfNone(void* AP_Void=0){};
template<typename TType> class ZtCTypeData
{ public: typedef TType TypeData;
static TType& GetObjRef(TType& AR_Type){return AR_Type ;}};
template<typename TType> class ZtCTypeData<TType*>
{ public: typedef TType TypeData;
static TType& GetObjRef(TType* AP_Type){return *AP_Type;}};
template<typename TType> class ZtCTypeData<TType&>
{ public: typedef TType TypeData;
static TType& GetObjRef(TType& AR_Type){return AR_Type ;}};
template< /*########*/ > class ZtCTypeData<void* >
{ public: typedef ZfpNone TypeData;
static ZfpNone GetObjRef(void* AP_Void){return ZfNone ;}};
template<typename TType> class ZtCTypeData< ZtCRef<TType> >
{ public: typedef TType TypeData; static TType&
GetObjRef(ZtCRef<TType>& AR_CRef)
{return AR_CRef.GetData() /*//////////////*/ ;}
};
template<typename TType> class ZtCTypeData< ZtCRef<TType>* >
{ public: typedef TType TypeData; static TType&
GetObjRef(ZtCRef<TType>* AP_CRef)
{return *reinterpret_cast<TypeData*>(AP_CRef);}
};
template<typename TType> class ZtCTD
{ public: typedef TType TypeData;
static TType& GetObjRef(TType& AR_Type){return AR_Type ;}
static TType& GOR (TType& AR_Type){return AR_Type ;}};
template<typename TType> class ZtCTD<TType*>
{ public: typedef TType TypeData;
static TType& GetObjRef(TType* AP_Type){return *AP_Type;}
static TType& GOR (TType* AP_Type){return *AP_Type;}};
template<typename TType> class ZtCTD<TType&>
{ public: typedef TType TypeData;
static TType& GetObjRef(TType& AR_Type){return AR_Type ;}
static TType& GOR (TType& AR_Type){return AR_Type ;}};
template< /*########*/ > class ZtCTD<void* >
{ public: typedef ZfpNone TypeData;
static ZfpNone GetObjRef(void* AP_Void){return ZfNone ;}
static ZfpNone GOR (void* AP_Void){return ZfNone ;}};
template<typename TType> class ZtCTD< ZtCRef<TType> >
{ public: typedef TType TypeData;
static TType& GetObjRef(ZtCRef<TType>& AR_CRef){return AR_CRef.GetData() ;}
static TType& GOR (ZtCRef<TType>& AR_CRef){return AR_CRef.GetData() ;}
};
template<typename TType> class ZtCTD< ZtCRef<TType>* >
{ public: typedef TType TypeData;
static TType& GetObjRef(ZtCRef<TType>* AP_CRef)
{return *reinterpret_cast<TypeData*>(AP_CRef);}
static TType& GOR (ZtCRef<TType>* AP_CRef)
{return *reinterpret_cast<TypeData*>(AP_CRef);}
};
/*/////////////////////////////////////////////////////////////////////////////////////////////
■ template 인수가 Type11 까지 있음에 주의한다. 그러면 Type10 까지 전문화할 수 있는 것이다.
-- 2015-02-16 21:20:00
단, template 인수는 2개부터가 유효하다.
typedef ZtStTuple<int> CTupleInt1 는 오류다.
typedef ZtStTuple<int, int> CTupleInt2 는 정상이다.
상식적으로도 ZtStTuple<int> 으로 쓸 일은 없다. -- 2021-03-04 16:27
지금은 template 인수가 Type13 까지 있다. 그러면 Type12 까지 전문화할 수 있는 것이다. -- 2025-09-07 12:55
■ 이젠 ZtStTuple<int> 형태도 가능하다. ZftMakeTuple() 도 추가. - -2025-09-05 21:01
■ RVO(Return Value Optimization) 로 인해 아래가 가능하다. -- 2025-09-06 21:23
int VariMy=0; ZtStTuple<int&> myt1 = ZftMakeTuple(ZftMCP(VariMy));
■ std::tuple<> 용례-1 -- 2025-09-07 12:08
#include <tuple>
#include <iostream>
int main() {
int nownum=42;
// Creating a tuple
std::tuple<int&, std::string, double> myTuple(nownum, "Hello", 3.14);
// Accessing elements
std::cout << std::get<0>(myTuple) << "\n"; // Outputs: 42
std::cout << std::get<1>(myTuple) << "\n"; // Outputs: Hello
std::cout << std::get<2>(myTuple) << "\n"; // Outputs: 3.14
// Modifying elements
std::get<1>(myTuple) = "World";
std::cout << std::get<1>(myTuple) << "\n"; // Outputs: World
return 0;
}
■ std::tuple<> 용례-2 -- 2025-09-07 12:09
#include <tuple>
#include <iostream>
std::tuple<int, double, std::string> getValues() {
return {42, 3.14, "Hello"};
}
int main() {
auto [x, y, z] = getValues(); // Structured binding (C++17)
std::cout << x << ", " << y << ", " << z << "\n"; // Outputs: 42, 3.14, Hello
return 0;
}
■ std::tuple<> 용례-3 -- 2025-09-07 12:11
#include <iostream>
#include <tuple>
#include <string>
int main() {
// 기본 생성 및 값 할당
std::tuple<std::string, int, double> tpl;
std::get<0>(tpl) = "Example";
std::get<1>(tpl) = 42 ;
std::get<2>(tpl) = 3.14 ;
// make_tuple을 사용한 초기화
auto tpl2 = std::make_tuple("Hello", 100, 1.23);
// 구조적 바인딩 (C++17 이상)
auto [str, num, val] = tpl2;
std::cout << "Tuple 1: " << std::get<0>(tpl) << ", " << std::get<1>(tpl) << ", " << std::get<2>(tpl) << '\n';
std::cout << "Tuple 2: " << str << ", " << num << ", " << val << '\n';
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////*/
template< typename Type1 =void*, 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*, typename Type12=void*,
typename Type13=void*
>
struct ZtStTuple //////////////////////////////////////////////////////////////////////////////
{
ZtStTuple(){}
};
/*###########################################################################################*/
template<typename Type1> struct ZtStTuple<Type1>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
TypeData1 _1;
ZtStTuple<Type1>(){}
ZtStTuple<Type1>(Type1 _T1) :
_1(CCheckRef1::PassData(_T1))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2 >
struct ZtStTuple<Type1, Type2>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
TypeData1 _1; TypeData2 _2;
ZtStTuple<Type1, Type2>(){}
ZtStTuple<Type1, Type2>(Type1 _T1, Type2 _T2) :
_1(CCheckRef1::PassData(_T1)),
_2(CCheckRef2::PassData(_T2))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3 >
struct ZtStTuple<Type1, Type2, Type3>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3;
ZtStTuple<Type1, Type2, Type3>(){}
ZtStTuple<Type1, Type2, Type3>
(Type1 _T1, Type2 _T2, Type3 _T3) :
_1(CCheckRef1::PassData(_T1)),
_2(CCheckRef2::PassData(_T2)),
_3(CCheckRef3::PassData(_T3))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3, typename Type4 >
struct ZtStTuple<Type1, Type2, Type3, Type4>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3; TypeData4 _4;
ZtStTuple<Type1, Type2, Type3, Type4>(){}
ZtStTuple<Type1, Type2, Type3, Type4>
(Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5
>
struct ZtStTuple<Type1, Type2, Type3, Type4, Type5>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3; TypeData4 _4; TypeData5 _5;
ZtStTuple<Type1, Type2, Type3, Type4, Type5>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5>
(Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
, _5(CCheckRef5::PassData(_T5))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6
>
struct ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3;
TypeData4 _4; TypeData5 _5; TypeData6 _6;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6>
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6
) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
, _5(CCheckRef5::PassData(_T5))
, _6(CCheckRef6::PassData(_T6))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6, typename Type7
>
struct ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3; TypeData4 _4;
TypeData5 _5; TypeData6 _6; TypeData7 _7;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7>
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7
) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
, _5(CCheckRef5::PassData(_T5))
, _6(CCheckRef6::PassData(_T6))
, _7(CCheckRef7::PassData(_T7))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8
>
struct ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8> CCheckRef8 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
typedef typename CCheckRef8::TypeData TypeData8 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3; TypeData4 _4;
TypeData5 _5; TypeData6 _6; TypeData7 _7; TypeData8 _8;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8>
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8
) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
, _5(CCheckRef5::PassData(_T5))
, _6(CCheckRef6::PassData(_T6))
, _7(CCheckRef7::PassData(_T7))
, _8(CCheckRef8::PassData(_T8))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8, typename Type9
>
struct ZtStTuple
<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9>
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8> CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9> CCheckRef9 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
typedef typename CCheckRef8::TypeData TypeData8 ;
typedef typename CCheckRef9::TypeData TypeData9 ;
TypeData1 _1; TypeData2 _2; TypeData3 _3; TypeData4 _4;
TypeData5 _5; TypeData6 _6; TypeData7 _7; TypeData8 _8; TypeData9 _9;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9>
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8, Type9 _T9
) :
_1(CCheckRef1::PassData(_T1))
, _2(CCheckRef2::PassData(_T2))
, _3(CCheckRef3::PassData(_T3))
, _4(CCheckRef4::PassData(_T4))
, _5(CCheckRef5::PassData(_T5))
, _6(CCheckRef6::PassData(_T6))
, _7(CCheckRef7::PassData(_T7))
, _8(CCheckRef8::PassData(_T8))
, _9(CCheckRef9::PassData(_T9))
{}
};
/*###########################################################################################*/
template
< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8, typename Type9, typename Type10
>
struct ZtStTuple
<
Type1, Type2, Type3, Type4, Type5,
Type6, Type7, Type8, Type9, Type10
>
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
TypeData1 _1 ; TypeData2 _2 ; TypeData3 _3 ; TypeData4 _4 ;
TypeData5 _5 ; TypeData6 _6 ; TypeData7 _7 ; TypeData8 _8 ;
TypeData9 _9 ; TypeData10 _10;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10>
(
Type1 _T1, Type2 _T2 , Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6 , Type7 _T7, Type8 _T8,
Type9 _T9, Type10 _T10
) :
_1 (CCheckRef1 ::PassData(_T1 ))
, _2 (CCheckRef2 ::PassData(_T2 ))
, _3 (CCheckRef3 ::PassData(_T3 ))
, _4 (CCheckRef4 ::PassData(_T4 ))
, _5 (CCheckRef5 ::PassData(_T5 ))
, _6 (CCheckRef6 ::PassData(_T6 ))
, _7 (CCheckRef7 ::PassData(_T7 ))
, _8 (CCheckRef8 ::PassData(_T8 ))
, _9 (CCheckRef9 ::PassData(_T9 ))
, _10(CCheckRef10::PassData(_T10))
{}
};
/*###########################################################################################*/
template
< typename Type1 , typename Type2 , typename Type3,
typename Type4 , typename Type5 , typename Type6,
typename Type7 , typename Type8 , typename Type9,
typename Type10, typename Type11
>
struct ZtStTuple
<
Type1, Type2, Type3, Type4 , Type5, Type6,
Type7, Type8, Type9, Type10, Type11
>
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef ZNsMain::ZtCCheckRef<Type11> CCheckRef11;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
typedef typename CCheckRef11::TypeData TypeData11 ;
TypeData1 _1 ; TypeData2 _2 ; TypeData3 _3 ; TypeData4 _4 ;
TypeData5 _5 ; TypeData6 _6 ; TypeData7 _7 ; TypeData8 _8 ;
TypeData9 _9 ; TypeData10 _10; TypeData11 _11;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10, Type11>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10, Type11>
(
Type1 _T1, Type2 _T2 , Type3 _T3 , Type4 _T4,
Type5 _T5, Type6 _T6 , Type7 _T7 , Type8 _T8,
Type9 _T9, Type10 _T10, Type11 _T11
) :
_1 (CCheckRef1 ::PassData(_T1 ))
, _2 (CCheckRef2 ::PassData(_T2 ))
, _3 (CCheckRef3 ::PassData(_T3 ))
, _4 (CCheckRef4 ::PassData(_T4 ))
, _5 (CCheckRef5 ::PassData(_T5 ))
, _6 (CCheckRef6 ::PassData(_T6 ))
, _7 (CCheckRef7 ::PassData(_T7 ))
, _8 (CCheckRef8 ::PassData(_T8 ))
, _9 (CCheckRef9 ::PassData(_T9 ))
, _10(CCheckRef10::PassData(_T10))
, _11(CCheckRef11::PassData(_T11))
{}
};
/*###########################################################################################*/
template
< typename Type1 , typename Type2 , typename Type3 ,
typename Type4 , typename Type5 , typename Type6 ,
typename Type7 , typename Type8 , typename Type9 ,
typename Type10, typename Type11, typename Type12
>
struct ZtStTuple
<
Type1, Type2, Type3, Type4 , Type5 , Type6 ,
Type7, Type8, Type9, Type10, Type11, Type12
>
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef ZNsMain::ZtCCheckRef<Type11> CCheckRef11;
typedef ZNsMain::ZtCCheckRef<Type12> CCheckRef12;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
typedef typename CCheckRef11::TypeData TypeData11 ;
typedef typename CCheckRef12::TypeData TypeData12 ;
TypeData1 _1 ; TypeData2 _2 ; TypeData3 _3 ; TypeData4 _4 ;
TypeData5 _5 ; TypeData6 _6 ; TypeData7 _7 ; TypeData8 _8 ;
TypeData9 _9 ; TypeData10 _10; TypeData11 _11; TypeData12 _12;
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10, Type11, Type12>(){}
ZtStTuple<Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, Type10, Type11, Type12>
(
Type1 _T1, Type2 _T2 , Type3 _T3 , Type4 _T4 ,
Type5 _T5, Type6 _T6 , Type7 _T7 , Type8 _T8 ,
Type9 _T9, Type10 _T10, Type11 _T11, Type12 _T12
) :
_1 (CCheckRef1 ::PassData(_T1 ))
, _2 (CCheckRef2 ::PassData(_T2 ))
, _3 (CCheckRef3 ::PassData(_T3 ))
, _4 (CCheckRef4 ::PassData(_T4 ))
, _5 (CCheckRef5 ::PassData(_T5 ))
, _6 (CCheckRef6 ::PassData(_T6 ))
, _7 (CCheckRef7 ::PassData(_T7 ))
, _8 (CCheckRef8 ::PassData(_T8 ))
, _9 (CCheckRef9 ::PassData(_T9 ))
, _10(CCheckRef10::PassData(_T10))
, _11(CCheckRef11::PassData(_T11))
, _12(CCheckRef12::PassData(_T12))
{}
};
/*###########################################################################################*/
/*/////////////////////////////////////////////////////////////////////////////////////////////
■ RVO(Return Value Optimization) 로 인해 아래가 가능하다. -- 2025-09-06 21:23
int VariMy=0; ZtStTuple<int&> myt1 = ZftMakeTuple(ZftMCP(VariMy));
/////////////////////////////////////////////////////////////////////////////////////////////*/
ZtStTuple<> ZftMakeTuple()
{
return ZtStTuple<>();
}
/*####################################################################*/
template
<typename Type1>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<typename ZNsMain::ZtCCheckRef<Type1>::TypeData>
ZftMakeTuple(Type1 _T1)
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
return ZtStTuple<TypeData1> /*::::::::::::::::::::::::::::::::::::*/
(
CCheckRef1::PassData(_T1)
);
}
/*####################################################################*/
template
<typename Type1, typename Type2>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
>
ZftMakeTuple(Type1 _T1, Type2 _T2)
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
return ZtStTuple<TypeData1, TypeData2> /*:::::::::::::::::::::::::*/
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
);
}
/*####################################################################*/
template
<typename Type1, typename Type2, typename Type3>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
>
ZftMakeTuple(Type1 _T1, Type2 _T2, Type3 _T3)
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
return ZtStTuple<TypeData1, TypeData2, TypeData3> /*::::::::::::::*/
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
);
}
/*####################################################################*/
template
< typename Type1, typename Type2, typename Type3, typename Type4 >
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
return ZtStTuple<TypeData1, TypeData2, TypeData3, TypeData4> /*:::*/
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
);
}
/*####################################################################*/
template< typename Type1, typename Type2,
typename Type3, typename Type4, typename Type5
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
, typename ZNsMain::ZtCCheckRef<Type5>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2,
TypeData3, TypeData4, TypeData5
>
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
, CCheckRef5::PassData(_T5)
);
}
/*####################################################################*/
template< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
, typename ZNsMain::ZtCCheckRef<Type5>::TypeData
, typename ZNsMain::ZtCCheckRef<Type6>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4, Type5 _T5, Type6 _T6
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2, TypeData3,
TypeData4, TypeData5, TypeData6
>
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
, CCheckRef5::PassData(_T5)
, CCheckRef6::PassData(_T6)
);
}
/*####################################################################*/
template< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6, typename Type7
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
, typename ZNsMain::ZtCCheckRef<Type5>::TypeData
, typename ZNsMain::ZtCCheckRef<Type6>::TypeData
, typename ZNsMain::ZtCCheckRef<Type7>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2, TypeData3, TypeData4,
TypeData5, TypeData6, TypeData7
>
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
, CCheckRef5::PassData(_T5)
, CCheckRef6::PassData(_T6)
, CCheckRef7::PassData(_T7)
);
}
/*####################################################################*/
template< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
, typename ZNsMain::ZtCCheckRef<Type5>::TypeData
, typename ZNsMain::ZtCCheckRef<Type6>::TypeData
, typename ZNsMain::ZtCCheckRef<Type7>::TypeData
, typename ZNsMain::ZtCCheckRef<Type8>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8> CCheckRef8 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
typedef typename CCheckRef8::TypeData TypeData8 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2, TypeData3, TypeData4,
TypeData5, TypeData6, TypeData7, TypeData8
>
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
, CCheckRef5::PassData(_T5)
, CCheckRef6::PassData(_T6)
, CCheckRef7::PassData(_T7)
, CCheckRef8::PassData(_T8)
);
}
/*####################################################################*/
template< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8, typename Type9
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1>::TypeData
, typename ZNsMain::ZtCCheckRef<Type2>::TypeData
, typename ZNsMain::ZtCCheckRef<Type3>::TypeData
, typename ZNsMain::ZtCCheckRef<Type4>::TypeData
, typename ZNsMain::ZtCCheckRef<Type5>::TypeData
, typename ZNsMain::ZtCCheckRef<Type6>::TypeData
, typename ZNsMain::ZtCCheckRef<Type7>::TypeData
, typename ZNsMain::ZtCCheckRef<Type8>::TypeData
, typename ZNsMain::ZtCCheckRef<Type9>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2, Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6, Type7 _T7, Type8 _T8, Type9 _T9
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1> CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2> CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3> CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4> CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5> CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6> CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7> CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8> CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9> CCheckRef9 ;
typedef typename CCheckRef1::TypeData TypeData1 ;
typedef typename CCheckRef2::TypeData TypeData2 ;
typedef typename CCheckRef3::TypeData TypeData3 ;
typedef typename CCheckRef4::TypeData TypeData4 ;
typedef typename CCheckRef5::TypeData TypeData5 ;
typedef typename CCheckRef6::TypeData TypeData6 ;
typedef typename CCheckRef7::TypeData TypeData7 ;
typedef typename CCheckRef8::TypeData TypeData8 ;
typedef typename CCheckRef9::TypeData TypeData9 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2, TypeData3, TypeData4,
TypeData5, TypeData6, TypeData7, TypeData8, TypeData9
>
(
CCheckRef1::PassData(_T1)
, CCheckRef2::PassData(_T2)
, CCheckRef3::PassData(_T3)
, CCheckRef4::PassData(_T4)
, CCheckRef5::PassData(_T5)
, CCheckRef6::PassData(_T6)
, CCheckRef7::PassData(_T7)
, CCheckRef8::PassData(_T8)
, CCheckRef9::PassData(_T9)
);
}
/*####################################################################*/
template< typename Type1, typename Type2, typename Type3,
typename Type4, typename Type5, typename Type6,
typename Type7, typename Type8, typename Type9, typename Type10
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type2 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type3 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type4 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type5 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type6 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type7 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type8 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type9 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type10>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2 , Type3 _T3, Type4 _T4,
Type5 _T5, Type6 _T6 , Type7 _T7, Type8 _T8,
Type9 _T9, Type10 _T10
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2, TypeData3, TypeData4,
TypeData5, TypeData6, TypeData7, TypeData8,
TypeData9, TypeData10
>
(
CCheckRef1 ::PassData(_T1 )
, CCheckRef2 ::PassData(_T2 )
, CCheckRef3 ::PassData(_T3 )
, CCheckRef4 ::PassData(_T4 )
, CCheckRef5 ::PassData(_T5 )
, CCheckRef6 ::PassData(_T6 )
, CCheckRef7 ::PassData(_T7 )
, CCheckRef8 ::PassData(_T8 )
, CCheckRef9 ::PassData(_T9 )
, CCheckRef10::PassData(_T10)
);
}
/*####################################################################*/
template< typename Type1 , typename Type2, typename Type3,
typename Type4 , typename Type5, typename Type6,
typename Type7 , typename Type8, typename Type9,
typename Type10, typename Type11
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type2 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type3 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type4 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type5 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type6 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type7 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type8 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type9 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type10>::TypeData
, typename ZNsMain::ZtCCheckRef<Type11>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2 , Type3 _T3 , Type4 _T4,
Type5 _T5, Type6 _T6 , Type7 _T7 , Type8 _T8,
Type9 _T9, Type10 _T10, Type11 _T11
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef ZNsMain::ZtCCheckRef<Type11> CCheckRef11;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
typedef typename CCheckRef11::TypeData TypeData11 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2 , TypeData3, TypeData4,
TypeData5, TypeData6 , TypeData7, TypeData8,
TypeData9, TypeData10, TypeData11
>
(
CCheckRef1 ::PassData(_T1 )
, CCheckRef2 ::PassData(_T2 )
, CCheckRef3 ::PassData(_T3 )
, CCheckRef4 ::PassData(_T4 )
, CCheckRef5 ::PassData(_T5 )
, CCheckRef6 ::PassData(_T6 )
, CCheckRef7 ::PassData(_T7 )
, CCheckRef8 ::PassData(_T8 )
, CCheckRef9 ::PassData(_T9 )
, CCheckRef10::PassData(_T10)
, CCheckRef11::PassData(_T11)
);
}
/*####################################################################*/
template< typename Type1 , typename Type2 , typename Type3,
typename Type4 , typename Type5 , typename Type6,
typename Type7 , typename Type8 , typename Type9,
typename Type10, typename Type11, typename Type12
>
ZtStTuple /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
<
typename ZNsMain::ZtCCheckRef<Type1 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type2 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type3 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type4 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type5 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type6 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type7 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type8 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type9 >::TypeData
, typename ZNsMain::ZtCCheckRef<Type10>::TypeData
, typename ZNsMain::ZtCCheckRef<Type11>::TypeData
, typename ZNsMain::ZtCCheckRef<Type12>::TypeData
>
ZftMakeTuple /*#######################################################*/
(
Type1 _T1, Type2 _T2 , Type3 _T3 , Type4 _T4 ,
Type5 _T5, Type6 _T6 , Type7 _T7 , Type8 _T8 ,
Type9 _T9, Type10 _T10, Type11 _T11, Type12 _T12
)
/*####################################################################*/
{
typedef ZNsMain::ZtCCheckRef<Type1 > CCheckRef1 ;
typedef ZNsMain::ZtCCheckRef<Type2 > CCheckRef2 ;
typedef ZNsMain::ZtCCheckRef<Type3 > CCheckRef3 ;
typedef ZNsMain::ZtCCheckRef<Type4 > CCheckRef4 ;
typedef ZNsMain::ZtCCheckRef<Type5 > CCheckRef5 ;
typedef ZNsMain::ZtCCheckRef<Type6 > CCheckRef6 ;
typedef ZNsMain::ZtCCheckRef<Type7 > CCheckRef7 ;
typedef ZNsMain::ZtCCheckRef<Type8 > CCheckRef8 ;
typedef ZNsMain::ZtCCheckRef<Type9 > CCheckRef9 ;
typedef ZNsMain::ZtCCheckRef<Type10> CCheckRef10;
typedef ZNsMain::ZtCCheckRef<Type11> CCheckRef11;
typedef ZNsMain::ZtCCheckRef<Type12> CCheckRef12;
typedef typename CCheckRef1 ::TypeData TypeData1 ;
typedef typename CCheckRef2 ::TypeData TypeData2 ;
typedef typename CCheckRef3 ::TypeData TypeData3 ;
typedef typename CCheckRef4 ::TypeData TypeData4 ;
typedef typename CCheckRef5 ::TypeData TypeData5 ;
typedef typename CCheckRef6 ::TypeData TypeData6 ;
typedef typename CCheckRef7 ::TypeData TypeData7 ;
typedef typename CCheckRef8 ::TypeData TypeData8 ;
typedef typename CCheckRef9 ::TypeData TypeData9 ;
typedef typename CCheckRef10::TypeData TypeData10 ;
typedef typename CCheckRef11::TypeData TypeData11 ;
typedef typename CCheckRef12::TypeData TypeData12 ;
return ZtStTuple /*:::::::::::::::::::::::::::::::::::::::::::::::*/
<
TypeData1, TypeData2 , TypeData3 , TypeData4,
TypeData5, TypeData6 , TypeData7 , TypeData8,
TypeData9, TypeData10, TypeData11, TypeData12
>
(
CCheckRef1 ::PassData(_T1 )
, CCheckRef2 ::PassData(_T2 )
, CCheckRef3 ::PassData(_T3 )
, CCheckRef4 ::PassData(_T4 )
, CCheckRef5 ::PassData(_T5 )
, CCheckRef6 ::PassData(_T6 )
, CCheckRef7 ::PassData(_T7 )
, CCheckRef8 ::PassData(_T8 )
, CCheckRef9 ::PassData(_T9 )
, CCheckRef10::PassData(_T10)
, CCheckRef11::PassData(_T11)
, CCheckRef12::PassData(_T12)
);
}
/*####################################################################*/
template< typename TTypeArg1,
typename TTypeArg2,
bool TTypebCompareObj=true
>
class ZtCCompare /////////////////////////
{
public:
enum {ZEUseCompareObj=(ZTypIntE)TTypebCompareObj};
public:
template<typename TTypeArg11, typename TTypeArg22>
static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2)
{
#ifdef _DEBUG_CCOMPARE_EXEC
cout<<" ※※ ZtCCompare<TTypeArg1, TTypeArg2, true> is called."<<endl;
#endif //_DEBUG_CCOMPARE_EXEC
return AR_TypeArg1.Compare(AR_TypeArg2);
}/*
template<typename TTypeArg11, typename TTypeArg22>
static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2) */
public:
};/*
template< typename TTypeArg1,
typename TTypeArg2,
bool TTypebCompareObj=true
>
class ZtCCompare ///////////////////////*/
template<typename TTypeArg1, typename TTypeArg2
>
class ZtCCompare<TTypeArg1, TTypeArg2, false>
{
public:
enum {ZEUseCompareObj=0};
public:
template<typename TTypeArg11, typename TTypeArg22>
static ZTypInt Exec(TTypeArg11 AR_TypeArg1, TTypeArg22 AR_TypeArg2)
{
return ZNsEnum::ZECompareResult_Equal;
}/*
template<typename TTypeArg11, typename TTypeArg22>
static ZTypInt Exec(TTypeArg1 AR_TypeArg1, TTypeArg2 AR_TypeArg2)*/
public:
};/*
template<typename TTypeArg1, typename TTypeArg2
>
class ZtCCompare<TTypeArg1, TTypeArg2, false> */
template<> class ZtCCompare<ZTypInt, ZTypInt, true>
{
public:
enum {ZEUseCompareObj=1};
public:
static ZTypInt Exec(ZTypInt AI_Int1, ZTypInt AI_Int2)
{
#ifdef _DEBUG_CCOMPARE_EXEC
cout<<" ※※ ZtCCompare<int, int, true> is called."<<endl;
#endif //_DEBUG_CCOMPARE_EXEC
return AI_Int1 - AI_Int2 ;
}/*
static ZTypInt Exec(ZTypInt AI_Int1, ZTypInt AI_Int2)*/
public:
};/*
template<> class ZtCCompare<ZTypInt, ZTypInt, true>*/
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 ZNsHelp
{
/*//////////////////////////////////////////////////
■ 주로 특정 클래스에 도움이 되는 클래스는 여기에 둔다.
-- 2025-09-13 00:59:00
//////////////////////////////////////////////////*/
}/*
namespace ZNsHelp*/
namespace ZNsFunc
{
/*///////////////////////////////////////////////////////////////////////////
■ 특수한 목적으로 쓰이는 전역 템플릿 함수는 여기에 놓는다.
■ ZftMoveFast<>(Type1& AR_Type1, Type2& AR_Type2)
차기 표준에서 구현하는 RValue Reference 를 흉내낸 함수다. Move 생성자와
Move 대입연산 중 대입연산만을 흉내내는 것이며, 일반적으로 이 함수 호출후에
AR_Type2 의 크기는 0 이 되거나 줄어들 것이다.
해당 object 에 Move 대입연산이 필요하면 해당 object 를 인수로 갖는
ZftMoveFast() 함수 템플릿을 전문화하면 된다.
■ 어느 함수 func()가 인수로 전달되는 object 의 초기/종료 멤버함수를 요구하는
경우, 그때마다 해당 object class 를 선언할 때, 특정한 이름의 초기/종료 멤버
함수를 선언/정의해야 하는데, 이런 불편함을 약간이라도 감소시키기 위해, func()
에서 해당 object 를 인수로 갖는 전역함수 __Init<>(), __Fini<>() 를 호출하는
것으로 하면 다소 편해질 것이다. 그 후 필요에 따라, __Init, __Fini 템플릿을
전문화하면 된다.
현재(2025-08-20) __init() 와 __Fini() 는 _CODE_OLD_ 으로 사실상 삭제되었다.
■ -- 2009-08-15 19:57:00
///////////////////////////////////////////////////////////////////////////*/
template<typename Type1, typename Type2>
void ZftMoveFast(Type1& AR_Type1, Type2& AR_Type2)
{
#ifdef _DEBUG_FAST_MOVE_OBJ_
cout<<" ※※ ZftMoveFast Start : Type1="<<typeid(Type1).name()<<", Type2="<<typeid(Type2).name()<<endl;
#endif //_DEBUG_FAST_MOVE_OBJ_
AR_Type1 = AR_Type2 ;
#ifdef _DEBUG_FAST_MOVE_OBJ_
cout<<" ※※ ZftMoveFast Close : Type2="<<typeid(Type1).name()<<", Type2="<<typeid(Type2).name()<<endl;
#endif //_DEBUG_FAST_MOVE_OBJ_
}/*
template<typename Type1, typename Type2>
void ZftMoveFast(Type& AR_Type1, Type& AR_Type2) */
#if(_CODE_OLD_)
template<typename Type> void __Init(Type& AR_Type)
{
#ifdef _DEBUG
cout<<"void ZNsFunc::__Init<Type>(Type&), Type="<<typeid(Type).name()<<endl;
#endif //_DEBUG
}/*
template<typename Type> void __Init(Type& AR_Type)*/
template<typename Type> void __Fini(Type& AR_Type)
{
#ifdef _DEBUG
cout<<"void ZNsFunc::__Fini<Type>(Type&), Type="<<typeid(Type).name()<<endl;
#endif //_DEBUG
}/*
template<typename Type> void __Fini(Type& AR_Type)*/
#endif //(_CODE_OLD_)
/*///////////////////////////////////////////////////////////////////////////
■ 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::ZECompareResult_Equal ,
AR_Type1>=AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 이상의 값,
AR_Type1> AR_Type2 이면 ZNsEnum::ZECompareResult_More 이상의 값,
AR_Type1<=AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 이하의 값,
AR_Type1< AR_Type2 이면 ZNsEnum::ZECompareResult_Less 이하의 값,
을 리턴하거나
AR_Type1>=AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 이상의 값,
AR_Type1> AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 보다 큰 값,
AR_Type1<=AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 이하의 값,
AR_Type1< AR_Type2 이면 ZNsEnum::ZECompareResult_Equal 보다 작은 값,
을 리턴한다.
-- 2012-09-01 20:20:00
최초에는
template<typename Type1,typename Type2> __CompareObj(Type1, Type2)
라는 함수를 만들어 사용했는데, 템플릿 중첩 정의 시에 상당히 불편했었다.
분명히 문법에 맞게 썼는 것 같은데, 컴파일 에러가 자꾸 나고... 단순히 문
법에 안맞게 써서 그렇다고 한 마디 말로 표현하기에는 어려운 상황이다.
-- 2012-09-02 22:49:00
ZtCCompare<>::Exec(~) 가 template 함수로 선언되어 있는데, 이전에는 template
함수가 아니었다. 이것을 template 함수로 바꾼 이유는 ZtCCompare<> 의 template
인자에 TTypeArg1, TTypeArg2 에 구애받지 않기 위해서다. 따라서 확장성이
약간 상승한다.
-- 2012-10-09 09:14:00
///////////////////////////////////////////////////////////////////////////*/
}/*
namespace ZNsFunc*/
/*/////////////////////////////////////////////
■ ZtCMoveObj<> 의 사용례는 CObjAVL.H 에 있다.
-- 2013-08-26 19:18:00
/////////////////////////////////////////////*/
template< typename TTypeArg1 ,
typename TTypeArg2 ,
bool TTypebMoveObj=true
>
class ZtCMoveObj /*###############################################*/
{
public:
enum {ZEUseMoveObj = (ZTypIntE)TTypebMoveObj} ;
public:
typedef typename ZNsMain::ZtCRef<TTypeArg1>::TypeRef TypeRef1;
typedef typename ZNsMain::ZtCRef<TTypeArg2>::TypeRef TypeRef2;
public:
static void Exec(TypeRef1 AR_TypeArg1, TypeRef2 AR_TypeArg2)
{
#ifdef _DEBUG_MOVEOBJ_EXEC
cout<<" ※※ ZtCMoveObj<TTypeArg1, TTypeArg2, true> is called."<<endl;
#endif //_DEBUG_MOVEOBJ_EXEC
ZNsFunc::ZftMoveFast(AR_TypeArg1, AR_TypeArg2);
}/*
static void Exec(TTypeArg1& AR_TypeArg1, TTypeArg2& AR_TypeArg2)*/
public:
};/*
template< typename TTypeArg1 ,
typename TTypeArg2 ,
bool TTypebMoveObj=true
>
class ZtCMoveObj #################################################*/
template /*######################################################*/
<
typename TTypeArg1, typename TTypeArg2
>
class ZtCMoveObj<TTypeArg1, TTypeArg2, false> /*//////////////////*/
{
public:
enum {ZEUseMoveObj=0};
public:
typedef typename ZNsMain::ZtCRef<TTypeArg1>::TypeRef TypeRef1;
typedef typename ZNsMain::ZtCRef<TTypeArg2>::TypeRef TypeRef2;
public:
static void Exec(TypeRef1 AR_TypeArg1, TypeRef2 AR_TypeArg2)
{
AR_TypeArg1 = AR_TypeArg2 ;
}/*
static void Exec(TypeRef1 AR_TypeArg1, TypeRef2 AR_TypeArg2)*/
public:
};/*
template ###########################################################
<
typename TTypeArg1, typename TTypeArg2
>
class ZtCMoveObj<TTypeArg1, TTypeArg2, false> ////////////////////*/
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{ZENextObjNo =ZCObjNext::ENextObjNo+1};
enum{ZEBoolNextObj=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<typename TTypeNow> class ZtCTmplChain<TTypeNow, ZCEmpty>
{
public :
typedef TTypeNow ZCObjNow ;
typedef TTypeNow ZCObjNext;
public :
enum{ZENextObjNo =1};
enum{ZEBoolNextObj=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<typename TTypeNow> class ZtCTmplChain<TTypeNow, ZCEmpty> */
/*//////////////////////////////////////////////////////////////////////////////
■ 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{ZENextObjNo =TTypeNext ::ENextObjNo +1};
enum{ZENextObjNo2 =TTypeNext2::ENextObjNo2+1};
enum{ZEBoolNextObj =1};
enum{ZEBoolNextObj2=1};
enum{ZEObjChainCnt =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<TTypeNow, TTypeNext, ZCEmpty>
{
public :
enum{ZENextObjNo =TTypeNext::ENextObjNo +1};
enum{ZENextObjNo2 =0 };
enum{ZEBoolNextObj =1 };
enum{ZEBoolNextObj2=0 };
enum{ZEObjChainCnt =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<TTypeNow, TTypeNext, ZCEmpty> */
template< typename TTypeNow, typename TTypeNext2
>
class ZtCTmplTreeChain<TTypeNow, ZCEmpty, TTypeNext2>
{
public :
enum{ZENextObjNo =0 };
enum{ZENextObjNo2 =TTypeNext2::ENextObjNo2 +1 };
enum{ZEBoolNextObj =0 };
enum{ZEBoolNextObj2=1 };
enum{ZEObjChainCnt =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<TTypeNow, ZCEmpty, TTypeNext2> */
template< typename TTypeNow ////////////////////
>
class ZtCTmplTreeChain<TTypeNow, ZCEmpty, ZCEmpty>
{
public :
enum{ZENextObjNo =0};
enum{ZENextObjNo2 =0};
enum{ZEBoolNextObj =0};
enum{ZEBoolNextObj2=0};
enum{ZEObjChainCnt =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<TTypeNow, ZCEmpty, ZCEmpty>
*/
}/*
namespace ZNsTmplChain*/
/*///////////////////////////////////////////////////////////////////
■ 함수가 어떤 조건에서 실행을 중지할 때,
bool 값으로 표시해도 되지만 가독성을 위해서 enum ZERun 을 사용하자.
■ enum ZERun 의 값을 포함해서 에러 상태를 표현하고 싶을 때에는,
enum ZERunEx 를 사용하자.
-- 2011-09-27 05:37:00
■ ZEActRun
연결 리스트 같은 자료구조에서 각 원소를 순회하면서 특정 조건에 맞
으면 원소를 삭제하거나, 순회를 중지하는 등의 행위를 동시에 표현하
고 싶을 때, ZEActRun 을 사용하자.
-- 2025-10-03 19:01
///////////////////////////////////////////////////////////////////*/
namespace ZNsEnum
{
enum ZERun
{
ZERun_NO, // 실행 중지
ZERun_OK // 실행 계속
};/*
enum ZERun*/
enum ZERunEx
{
ZERunEx_NO, // 실행 중지
ZERunEx_OK, // 실행 계속
ZERunEx_Err // 실행 에러
};/*
enum ZERun*/
enum ZEAct
{
ZEAct_NO, // (함수 등이) 어떤 조건에 맞지 않아서 아무 짓도 하지 않았다.
ZEAct_OK // (함수 등이) 어떤 조건에 맞아서 지정된 처리를 하였다.
};/*
enum ZEAct*/
enum ZEActEx
{
ZEActEx_NO, // (함수 등이) 어떤 조건에 맞지 않아서 아무 짓도 하지 않았다.
ZEActEx_OK, // (함수 등이) 어떤 조건에 맞아서 지정된 처리를 하였다.
ZEActEx_Err // (함수 등이) 수행 중에 에러가 발생하였다.
};/*
enum ZEAct*/
enum ZEActRun
{
ZEActRun_RunNO =0x01, // 실행 중지
ZEActRun_RunOK =0x02, // 실행 계속
ZEActRun_RunErr=0x04, // 실행 오류
ZEActRun_ActNO =0x08, // 처리 중지
ZEActRun_ActOK =0xA0, // 처리 계속
ZEActRun_ActErr=0xB0 // 처리 오류
};/*
enum ZEAct*/
enum ZEThrowFinally
{
ZEThrowFinally_NO,
ZEThrowFinally_OK
};/*
enum ZEThrowFinally*/
/*////////////////////////////////////////////////
■ 타 언어의 throw ~ catch ~ finally 를 흉내낼 때
EThrowFinally 예외를 던진다.
////////////////////////////////////////////////*/
}/*
namespace ZNsEnum*/
using ZNsEnum::ZERun ;
using ZNsEnum::ZERun_NO ;
using ZNsEnum::ZERun_OK ;
using ZNsEnum::ZERunEx ;
using ZNsEnum::ZERunEx_NO ;
using ZNsEnum::ZERunEx_OK ;
using ZNsEnum::ZERunEx_Err;
namespace ZNsIFace
{
/*////////////////////////////////////////////////////////////////////////////////////
■ class ZIDelgtMSG 는 C# 의 delegate 삼아서 만든 클래스.
어느 object 가 하나 이상의 다른 object 에게 어떤 메시지를 전달하고 싶을 때, 메시지를
전송하는 object 는, 수신하는 object 의 기반클래스 ZIDelgtMSG 의 참조나 포인터를 멤버
로 가지고 있다가, ZIDelgtMSG::SendMSG() 나 ZIDelgtMSG::RecvMSG() 을 호출하면 된다.
■ COM 개념을 상당부분 포함하고 있다. 간단하게 COM 대용으로 써도 될 듯 하다.
-- 2009-03-08 02:26:00
■ class ZIDelgtMSG 를 상속하여 추가 멤버함수를 가진 인터페이스를 구현하는 클래스일 경우
에는 namespace ZNsIFace 에 두지 말고 namespace ZNsIDelgt 에 두자.
-- 2009-03-08 19:17:00
■ A, B, C 클래스가 서로의 존재를 알아야 한다고 할 때도 사용할 수 있겠다. 그런데 이런 경
우는 굳이 ZIDelgtMSG 를 사용하지 말고, 단순 가상 함수 클래스를 사용해도 된다. 그게 더
간단할 것이다. 그래도 ZIDelgtMSG 를 사용한다면, interface 의 일관성을 얻을 수 있다는 게
장점이 될 수 있다.
-- 2010-03-13 22:28:00
////////////////////////////////////////////////////////////////////////////////////*/
class ZIDelgtMSG
{
public:
enum ZEIMsg{ZEIMsg_NO=0, ZEIMsg_OK=1};
public:
virtual ~ZIDelgtMSG(){}
virtual ZTypLLong GetTypeID() const
{
return 0;
}/*
virtual ZTypLLong GetTypeID() const*/
virtual const char* GetTypeName() const
{
return 0;
}/*
virtual const char* GetTypeID() const*/
virtual ZTypLLong GetIMSGPtrOfID(ZTypLLong AI_TypeID, ZIDelgtMSG*& APR_ZIDelgtMSG)
{
APR_ZIDelgtMSG=0; return ZEIMsg_OK;
}/*
virtual ZTypLLong GetIMSGPtrOfID(ZTypLLong AI_TypeID, ZIDelgtMSG*R APR_ZIDelgtMSG)*/
virtual ZTypIntPtr SendMSG(ZIDelgtMSG& ArZIDelgtMSG, ZTypIntI AI_MsgNo, const char* ApcMsgData, ZTypIntI AI_MsgLen, void* AP_Void=0, ...)
{
return ZEIMsg_OK;
}/*
virtual ZTypIntPtr SendMSG(ZIDelgtMSG& ArZIDelgtMSG, ZTypIntI AI_MsgNo, const char* ApcMsgData, ZTypIntI AI_MsgLen,void* AP_Void=0, ...)*/
virtual ZTypIntPtr RecvMSG(ZTypIntI AI_MsgNo, const char* ApcMsgData, ZTypLength AI_MsgLen, void* AP_Void=0, ...)
{
return ZEIMsg_OK;
}/*
virtual ZTypIntPtr RecvMSG(ZTypIntI AI_MsgNo, const char* ApcMsgData, ZTypLength AI_MsgLen, void* AP_Void=0, ...)*/
public:
};/*
class ZIDelgtMSG*/
}/*
namespace ZNsIFace*/
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<typename TType> class ZtCAllocClass : public ZCAllocator
{
public:
TType* InitMem (size_t AL_AllocSize){return (TType*)::malloc(AL_AllocSize) ;}
TType* InitMemArr(size_t AL_AllocSize){return (TType*)::malloc(AL_AllocSize*sizeof(TType));}
public:
void FiniMem (void* AP_Void){if(AP_Void!=0) ::free(AP_Void);}
void FiniMemArr(void* AP_Void){if(AP_Void!=0) ::free(AP_Void);}
public:
};/*
template<typename TType> class ZtCAllocClass : public ZCAllocator*/
class ZCAllocClass : public ZCAllocator
{
public:
void* InitMem (size_t AL_AllocSize){return ::malloc(AL_AllocSize) ;}
void FiniMem (void* AP_Void ){if(AP_Void!=0) ::free(AP_Void);}
public:
};/*
class ZCAllocClass : public ZCAllocator*/
/*////////////////////////////////////////////////////////////////////////////////
■ 문자열 클래스에서 새로 메모리를 증가시켜야 할 때, 필요한 메모리보다 약간 더 할
당하는 것이 좋을 경우가 있는데, 이 경우에 필요한 메모리보다 어느 정도 만큼의 메
모리를 할당한 것인지를 지정한다.
////////////////////////////////////////////////////////////////////////////////*/
template<typename TTypeCh> class ZtCAllocMemSize
{
public:
template<typename TTypeSize> static 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<typenanme TTypeSize> static TTypeSize
GetNewAllocSize(TTypeSize AL_NowAllocSize, TTypeSize AL_AllAllocSize ) */
public:
};/*
template<typename TTypeCh> class ZtCAllocMemSize */
/*//////////////////////////////////////////////////////////////
■ 아래 템플릿은 양방향 리스트에서 n 번째 원소에 접근할 때, 앞에
서부터 접근하는 것이 빠를지, 뒤에서부터 접근하는 것이 빠를지
판단할 때 사용한다.
//////////////////////////////////////////////////////////////*/
template<typename TTypSize> 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 ZTypIntI 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 ZTypIntI GetAbsMinOrder(TTypSize AI_One,TTypSize AI_Two, TTypSize AI_Three)*/
public:
};/*
template<typename TTypSize> class ZtCShortCut*/
#ifdef _WIN
using ::GetLastError;
inline ZTypIntI ZfGetLastError(){ return ::GetLastError(); }
template<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0)
{
LPVOID VP_MsgBuff=0; 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<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0) */
// defined(_WIN)
#elif defined(__unix__)
inline ZTypIntI GetLastError(){return errno ;} // for compatibility with windows
inline ZTypIntI ZfGetLastError()
{
return errno ; // ::error 로 하면 안된다.
}/*
inline ZTypIntI ZfGetLastError()*/
template<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0)
{
if(AI_ErrNo==0)
ARR_BuffCStr = ::strerror(errno );
else ARR_BuffCStr = ::strerror(AI_ErrNo);
return true; // for compatibility with window
}/*
template<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0) */
//#elif defined(__unix__)
#else
inline ZTypIntI ZfGetLastError(){return errno ;}
template<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0)
{
if(AI_ErrNo==0)
ARR_BuffCStr = ::strerror(errno );
else ARR_BuffCStr = ::strerror(AI_ErrNo);
return true; // for compatibility with window
}/*
template<typename TString> static bool
ZftGetLastErrMSG(TString& ARR_BuffCStr, ZTypIntI AI_ErrNo=0) */
#endif
template
<typename TTypChar, typename TTypLength>
static TTypChar* ZftTrimDecimalZero
(TTypChar* APC_Data, TTypLength& ARRI_Length)
{
/* 문자열 APC_Data 이 어떤 소수를 표현할 경우
소수점 뒤에 맨 끝에 있는 의미없는 0 을 지운다.
*/
typedef TTypChar TypeChar ;
typedef TTypLength TypeLength ;
TypeChar* VPC_StartChar= APC_Data;
if(ARRI_Length<=0)
{ ARRI_Length=0; return 0; }
TypeLength VL_PeriodPos =0;
TypeLength VL_CurrentPos=0;
for(; VL_PeriodPos<ARRI_Length; ++VL_PeriodPos)
{ if( *VPC_StartChar++ =='.' ) break; }
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
// 마침표가 없거나, 맨 앞에 오거나 맨 끝에 오는 경우도 유효하지 않다.
if(VL_PeriodPos<1 || VL_PeriodPos>=ARRI_Length-1)
{ return APC_Data; }
/*+++++++++++++++++++++++++++++++++++++++++++++*/
VPC_StartChar = APC_Data +
( VL_CurrentPos = ARRI_Length-1 ) ;
while(VL_PeriodPos<VL_CurrentPos)
{
if(*VPC_StartChar!=TypeChar('0'))
{ break; }
/*+++++++++++++++++++++++++++++*/
*VPC_StartChar=0;
--VL_CurrentPos;
--VPC_StartChar;
--ARRI_Length ;
}/*
while(VL_PeriodPos<VL_CurrentPos)*/
/* 소수부 맨 끝에 0 을 삭제한 결과,
마침표가 끝에 온다면 그 마침표도 지운다.
*/
if(VL_PeriodPos==VL_CurrentPos)
{ * VPC_StartChar =TypeChar(0); --ARRI_Length; }
else{ *(VPC_StartChar+1)=TypeChar(0); }
return APC_Data; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}/*
template
<typename TTypChar, typename TTypLength>
static TTypChar* ZftTrimDecimalZero
(TTypChar* APC_Data, TTypLength& ARRI_Length)*/
// 절대값을 가져온다.
template<typename TLong> TLong ZfABS(TLong AL_Value)
{
if(AL_Value<0){return -AL_Value;} return AL_Value;
}/*
template<typename TLong> TLong ZfABS(TLong AL_Value) */
template<typename TypeInt>
TypeInt ZfAToInt(const char* ApcChar, ZTypIntI AI_Length)
{
if(AI_Length<1) return 0;
while(AI_Length>0 && ApcChar[AI_Length-1]==' ')
--AI_Length; // 뒤에 있는 공백을 제외.
/*+++++++++++++++++++++++++++++++++++++++++++*/
if(AI_Length<1) return 0;
ZTycChar* VPC_Char = ApcChar+AI_Length-1;
TypeInt VL_Temp = 0 ;
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<typename TypeInt>
TypeInt ZfAToInt(const char* ApcChar, ZTypIntI AI_Length) */
#ifdef _WIN
inline ZTypLLong ZfAtoLL(const char* ApcChar)
{
if(ApcChar==0) return 0; return ::_atoi64(ApcChar);
}/*
inline ZTypLLong ZfAtoLL(const char* ApcChar)*/
#else // !defined(_WIN)
inline ZTypLLong ZfAtoLL(const char* ApcChar)
{
if(ApcChar==0){ return 0;} return ::atoll(ApcChar);
}/*
inline ZTypLLong ZfAtoLL(const char* ApcChar)*/
#endif // !defined(_WIN)
inline ZTypLLong ZfAtoLL(const char* ApcChar, ZTypIntI AI_Length)
{
return ZfAToInt<ZTypLLong>(ApcChar, AI_Length);
}/*
inline ZTypLLong ZfAtoL(const char* ApcChar, ZTypIntI AI_Length)*/
inline ZTypLong ZfAtoL(const char* ApcChar)
{
if(ApcChar==0){return 0;} return ::atol(ApcChar);
}/*
inline ZTypLong ZfAtoL(const char* ApcChar)*/
inline ZTypLong ZfAtoL(const char* ApcChar, ZTypIntI AI_Length)
{
return ZfAToInt<ZTypLong>(ApcChar, AI_Length);
}/*
inline ZTypLong ZfAtoL(const char* ApcChar, ZTypIntI AI_Length)*/
inline ZTypIntI ZfAtoI(const char* ApcChar)
{
if(ApcChar==0){return 0;} return ::atoi(ApcChar);
}/*
inline ZTypIntI ZfAtoI(const char* ApcChar)*/
inline ZTypIntI ZfAtoI(const char* ApcChar, ZTypIntI AI_Length)
{
return ZfAToInt<ZTypIntI>(ApcChar, AI_Length);
}/*
inline ZTypIntI ZfAtoI(const char* ApcChar, ZTypIntI AI_Length)*/
inline double ZfAtoD(const char* ApcChar)
{
return ApcChar==0 ? 0 : ::atof(ApcChar) ;
}/*
inline double ZfAtoD(const char* ApcChar)*/
/*#############################################################################
■ #include <wchar.h>
long int wcstol(const wchar_t *nptr, wchar_t **endptr, int base);
#include <wchar.h>
long long int wcstoll(const wchar_t *nptr, wchar_t **endptr, int base);
*******************************************************************************
# https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/reference/strtoll-strtoll-l-wcstoll-wcstoll-l?view=msvc-170
base가 0 인 경우에는 strSource 에서 가리키는 문자열의 초기 문자를 사용하 여
밑을 결정합니다. 첫 번째 문자가 '0' 이고 두 번째 문자가 'x' 또는 'X' 가 아닌
경우 문자열은 8진수 정수로 해석됩니다. 첫 번째 문자가 '0' 이고 두 번째 문자
가 'x' 또는 'X'이면 문자열은 16진수 정수로 해석됩니다.
첫 번째 문자가 '1'~'9' 이면 문자열은 10진수 정수로 해석됩니다.
문자 'a'~'z' 또는 'A'~'Z'에는 값 10~35가 할당됩니다. 할당된 값이 base 보다
작은 문자만 사용할 수 있습니다. 밑의 범위를 벗어난 첫 번째 문자가 발견되면
검색이 중지됩니다. 예를 들어 base 가 0 인데 처음 검색된 문자가 '0' 이면 문
자열은 8진수 정수로 간주되며 '8' 또는 '9' 문자가 발견되면 검색은 중지됩니다.
*******************************************************************************
float wcstof ( const wchar_t* str, wchar_t** str_end ); (since C++11)
double wcstod ( const wchar_t* str, wchar_t** str_end );
long double wcstold( const wchar_t* str, wchar_t** str_end ); (since C++11)
-- 2025-10-08 09:23
#############################################################################*/
template<typename TTypChar> inline
ZTypInt ZftAtoI (const TTypChar* ApcChar){ return 0; }
template<> inline
ZTypInt ZftAtoI (const char* ApcChar){ return ZfAtoI(ApcChar); }
template<> inline
ZTypInt ZftAtoI (const wchar_t* ApcChar){ return (ZTypInt)::wcstol(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
ZTypLong ZftAtoL (const TTypChar* ApcChar){ return 0; }
template<> inline
ZTypLong ZftAtoL (const char* ApcChar){ return ZfAtoI(ApcChar); }
template<> inline
ZTypLong ZftAtoL (const wchar_t* ApcChar){ return ::wcstol(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
ZTypLLong ZftAtoLL(const TTypChar* ApcChar){ return 0; }
template<> inline
ZTypLLong ZftAtoLL(const char* ApcChar){ return ZfAtoLL(ApcChar); }
template<> inline
ZTypLLong ZftAtoLL(const wchar_t* ApcChar){ return ::wcstoll(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
double ZftAtoD (const TTypChar* ApcChar){ return 0; }
template<> inline
double ZftAtoD (const char* ApcChar){ return ZfAtoD(ApcChar); }
template<> inline
double ZftAtoD (const wchar_t* ApcChar){ return ::wcstod(ApcChar, 0) ; }
template<typename TTypChar> inline
ZTypInt ZftAtoI (const TTypChar* ApcChar, ZTypInt AI_Length){ return 0; }
template<> inline
ZTypInt ZftAtoI (const char* ApcChar, ZTypInt AI_Length){ return ZfAtoI(ApcChar); }
template<> inline
ZTypInt ZftAtoI (const wchar_t* ApcChar, ZTypInt AI_Length){ return (ZTypInt)::wcstol(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
ZTypLong ZftAtoL (const TTypChar* ApcChar, ZTypInt AI_Length){ return 0; }
template<> inline
ZTypLong ZftAtoL (const char* ApcChar, ZTypInt AI_Length){ return ZfAtoI(ApcChar); }
template<> inline
ZTypLong ZftAtoL (const wchar_t* ApcChar, ZTypInt AI_Length){ return ::wcstol(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
ZTypLLong ZftAtoLL(const TTypChar* ApcChar, ZTypInt AI_Length){ return 0; }
template<> inline
ZTypLLong ZftAtoLL(const char* ApcChar, ZTypInt AI_Length){ return ZfAtoLL(ApcChar); }
template<> inline
ZTypLLong ZftAtoLL(const wchar_t* ApcChar, ZTypInt AI_Length){ return ::wcstoll(ApcChar, 0, 0) ; }
template<typename TTypChar> inline
double ZftAtoD (const TTypChar* ApcChar, ZTypInt AI_Length){ return 0; }
template<> inline
double ZftAtoD (const char* ApcChar, ZTypInt AI_Length){ return ZfAtoD(ApcChar); }
template<> inline
double ZftAtoD (const wchar_t* ApcChar, ZTypInt AI_Length){ return ::wcstod(ApcChar, 0) ; }
inline ZTypLLong AtoLL(const char* ApcChar){return ZfAtoLL(ApcChar);}
inline ZTypLong AtoL (const char* ApcChar){return ZfAtoL (ApcChar);}
inline ZTypIntI AtoI (const char* ApcChar){return ZfAtoI (ApcChar);}
inline double AtoD (const char* ApcChar){return ZfAtoD (ApcChar);}
inline ZTypLLong AtoLL(const char* ApcChar, ZTypIntI AI_Length)
{ return ZfAToInt<ZTypLLong>(ApcChar, AI_Length); }
inline ZTypLong AtoL (const char* ApcChar, ZTypIntI AI_Length)
{ return ZfAToInt<ZTypLong >(ApcChar, AI_Length); }
inline ZTypIntI AtoI (const char* ApcChar, ZTypIntI AI_Length)
{ return ZfAToInt<ZTypIntI >(ApcChar, AI_Length); }
template<typename TTypeCh> inline
ZTypLength ZftGetLength(const TTypeCh* ApcChar)
{
if(ApcChar==0) return 0;
ZTypLength VL_Length=0;
while(*(ApcChar+VL_Length)!=TTypeCh('\0'))
++VL_Length;
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
return VL_Length;
}/*
template<typename TTypeCh> inline
ZTypLength ZftGetLength(const TTypeCh* ApcChar) */
template<typename TTypeSize, typename TTypeCh>
inline TTypeSize ZftGetLengthType(const TTypeCh* ApcChar)
{
if(ApcChar==0) return 0;
TTypeSize VL_Length=0 ;
while(*(ApcChar+VL_Length)!=_T('\0'))
++VL_Length;
/////////////////////////////////////
return VL_Length;
}/*
template<typename TTypeSize, typename TTypeCh>
inline TTypeSize ZftGetLengthType(const TTypeCh* ApcChar) */
template<typename TTypeCh>
inline ZTypLength ZftLength(const TTypeCh* ApcChar)
{
return ZftGetLength(ApcChar);
}/*
template<typename TTypeCh>
inline ZTypLength ZftLength(const TTypeCh* ApcChar) */
template<typename TTypeSize, typename TTypeCh>
inline TTypeSize ZftLengthType(const TTypeCh* ApcChar)
{
return ZftGetLengthType<TTypeSize, TTypeCh>(ApcChar);
}/*
template<typename TTypeSize, typename TTypeCh>
inline TTypeSize ZftLengthType(const TTypeCh* ApcChar) */
/*//////////////////////////////////////////////////////////////////////////////////////
■ ZftCopyChars() 함수는 최대 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<typename TTypeCh, typename TTypeSize> TTypeSize
ZftCopyChars(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 에 복사된 길이를 리턴한다.
*/
typedef const TTypeCh TTypcCh;
if(ApcSource==0) return 0 ;
TTypeSize VL_SourceSize=0 ;
TTypeCh* VPC_Dest =ApcDest ;
TTypcCh* VPC_Source =ApcSource;
for(; VL_SourceSize<AL_DestSize; ++VL_SourceSize)
{
if(*ApcSource==0)
{
if(VL_SourceSize<AL_DestSize+1)
{ *VPC_Dest=0; return VL_SourceSize+1; }
return VL_SourceSize;
}/*
if(*ApcSource==0)*/
*VPC_Dest = *VPC_Source;
}/*
for(; VL_SourceSize<AL_DestSize; ++VL_SourceSize)*/
}/*
template<typename TTypeCh, typename TTypeSize> TTypeSize
ZftCopyChars(TTypeCh* ApcDest, TTypeSize AL_DestSize, const TTypeCh* ApcSource) */
/*######################################################################################
■ ZtCInit<>, ZCInit 은 주로 자유 기억 공간을 구현하는 자료 구조에서 사용한다.
1) 자유 기억 공간에서 나오는 data 에 대하여 OnInit() 를 호출한다.
2) 자유 기억 공간으로 가 는 data 에 대하여 OnFini() 를 호출한다.
그런데 2) 는 자료 구조에 따라 호출하지 않을 수도 있다. 다수의 원소가 자유 기억 공간으
로 들어갈 때, 일일이 그 모든 원소에 대해 Onfini() 를 호출하는 것은 낭비일 수 있는 것이
다.
-- 2025-09-11 11:00
■ 주로 container 인 typename TType2 을 인수로 받아, container 와의 활용도롤 높이고 있다.
-- 2025-09-11 11:03
######################################################################################*/
template<typename TType> class ZtCInit
{
public:
enum{ZEUseInit=0};
enum{ZEUseFini=0};
public:
template<typename TType2>
static void OnInit(TType& AR_TypeArg, TType2& AR_TypeArg2){}
template<typename TType2>
static void OnFini(TType& AR_TypeArg, TType2& AR_TypeArg2){}
public:
};/*
template<typename TType> class ZtCInit*/
class ZCInit
{
public:
enum{ZEUseInit=0};
enum{ZEUseFini=0};
public:
template<typename TType, typename TType2>
static void OnInit(TType& AR_TypeArg, TType2& AR_TypeArg2){}
template<typename TType, typename TType2>
static void OnFini(TType& AR_TypeArg, TType2& AR_TypeArg2){}
public:
};/*
class ZCInit*/
class ZCExceptBase
{
public: void* operator()(){return 0;}
};/*
class ZCExceptBase*/
// 예외 기반 클래스를 template 로 하면 여러 기법을 사용할 수 있다.
template< typename TType, typename TypeArg=const TType&
>
class ZtCExceptBase /*/////////////////////////////////*/
{
protected:
TType mo_Type;
public :
ZtCExceptBase(){}
ZtCExceptBase(TypeArg TypeArgObj):mo_Type(TypeArgObj){}
TType& operator()(){return mo_Type;}
public :
};/*
template< typename TType, typename TypeArg=const TType&
>
class ZtCExceptBase ///////////////////////////////////*/
/*/////////////////////////////////////////////////////////////////////////////////
■ 이 클래스를 private 상속하는 클래스에서 복사생성자와 대입연산자의 사용을 막는다.
■ template class 나 class member template 을 사용할 때, 인수가 class object 이고
이 인수가 반드시 참조형으로 전달되어야하고, 복사 생성되어 전달될 수 없을때, 이를
보장하기 위해 해당 class 를 아래 class 로부터 상속할 필요가 있다.
이를 모르고 있다가, CAsyncServ_H 에 정의된 CAsyncServ_T<> 클래스를 사용할 때, 이
클래스가 작업쓰레드 풀 인수로 복사 생성되어 전달되는 것을 나중에 알고 깜짝 놀랬다.
-- 2010-12-20 23:51:00
/////////////////////////////////////////////////////////////////////////////////*/
class ZCNonCopyable
{
private:
ZCNonCopyable(const ZCNonCopyable& rhs){}
ZCNonCopyable& operator=(const ZCNonCopyable& rhs){return *this;}
public :
ZCNonCopyable(){}
public :
};/*
class ZCNonCopyable*/
/*///////////////////////////////////////////////////////////////////////////
■ 리스트나 트리 구조에서 쓰는 링크의 힙-자유 기억 공간-을 구현하는 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*/
namespace ZNsIFace
{
// 자료 구조에서 자유 기억 공간을 구현하는 interface
class ZIFreeHeap
{
public:
template<typename TLinkList> class ZtCBody
{
public:
typedef typename TLinkList::ZCLink ZCLink ;
typedef typename TLinkList::TypeSize TypeSize;
public:
_NP_ void RecvFreeIn(ZCLink* AP_CutLink){}
_NP_ void RecvFreeIn /////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
{ } //////////////////////////////////////
_NP_ ZCLink* SendFreeOut(){}
_NP_ void SendFreeOut /////////////////
(
TypeSize AL_NeedCnt ,
ZCLink*& APR_NewHead,
ZCLink*& APR_NewTail
)
{ } //////////////////////////////////////
_NP_ void SendFreeOutCopy /*//////////////////////*/
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
{ } /*//////////////////////////////////////////////////*/
_NP_ void DeleteHeap(){}
_NP_ void MakeEuqal(ZtCBody& rhs)
{
}/*
_NP_ void MakeEuqal(ZtCBody& rhs)*/
_NP_ TypeSize GetUseHeapSize() const
{
return 0;
}/*
_NP_ TypeSize GetUseHeapSize() const*/
_NP_ TypeSize GetAllHeapSize() const
{
return 0;
}/*
_NP_ TypeSize GetAllHeapSize() const*/
_NP_ TypeSize size() const
{
return GetUseHeapSize();
}/*
_NP_ TypeSize size() const*/
public:
};/*
template<typename TLinkList> class ZtCBody*/
public:
};/*
class ZIFreeHeap*/
}/*
namespace ZNsIFace*/
namespace ZNsIFaceEx
{
/*################################################################
■ 자료 구조에서 자유 기억 공간을 구현하는 interface
만약 다르게 구헌한 자유 기억 공간 class 가 필요하다면,
단방향 연결 리스트는 ZtCFreeHeapSngl<> 를 통해 중첩 정의하고,
양방향 연결 리스트는 ZtCFreeHeapCDL <> 를 통해 중첩 정의하자.
이렇게 하면,
ZtCFreeHeapSngl<>::ZCLink 와 ZtCFreeHeapCDL<>::ZCLink
에서 friend 선언을 아래처럼 고정시켜 놓을 수 있다.
template<int>
friend class ZNsIFaceEx::ZtCFreeHeapSngl ;
################################################################*/
template<int TTypIListKind=0> class ZtCFreeHeapSngl // Single List
{
public:
template<typename TSnglList> class ZtCBody
{
public:
typedef typename TSnglList::ZCLink ZCLink ;
typedef typename TSnglList::TypeSize TypeSize;
/*:::::::::::::::::::::::::::::::::::::::::::::::::::
■ 만약 ZCLink 의 non-public 멤버에 접근해야 하는 경우,
ZCLink 에서 ZtCBody 에 friend 선언을 해줘야 하는 것
이 맞겠지만, friend 선언 없이 해야 한다면, ZCLink 와
같은 멤버를 가진 class 를 선언하고 그 class 로 강제
형변환을 해서 해결하자.
-- 2025-09-14 12:34
:::::::::::::::::::::::::::::::::::::::::::::::::::*/
public:
_NP_ void RecvFreeIn(ZCLink* AP_CutLink){delete AP_CutLink;}
_NP_ void RecvFreeIn ///////////////////////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
////////////////////////////////////////////////////////////
{
ZCLink* VP_DelLink = AP_CutHead;
__for0(TypeSize, i, AL_CutCnt)
{
AP_CutHead = AP_CutHead->GetNextPtr();
delete VP_DelLink; VP_DelLink=AP_CutHead;
}/*
__for0(TypeSize, i, AL_CutCnt)*/
}
////////////////////////////////////////////////////////////
_NP_ ZCLink* SendFreeOut(){return new ZCLink;}
_NP_ void SendFreeOut ///////////////////////////////////
(
TypeSize AL_NeedCnt ,
ZCLink*& APR_HeadLink ,
ZCLink*& APR_TailLink
)
////////////////////////////////////////////////////////////
{
APR_HeadLink = new ZCLink;
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = APR_HeadLink;
while(--AL_NeedCnt>0) // AL_NeedCnt - 1 번 순환
{
// AL_NeedCnt - 1 번 순환
VP_MakeLink = new ZCLink;
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink ;
}/*
while(--AL_NeedCnt>0)*/
APR_TailLink = VP_TailLink;
}
////////////////////////////////////////////////////////////
_NP_ void SendFreeOutCopy /*////////////////////////////*/
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
//////////////////////////////////////////////////////////
{
// 총 AL_FarNum+1 개의 링크가 만들어짊.
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = 0 ;
VP_TailLink = VP_MakeLink =
new ZCLink( **AP_LinkOrgin );
APR_HeadCopy = VP_MakeLink;
while(--AL_FarNum >= 0)
{
AP_LinkOrgin= AP_LinkOrgin->GetNextPtr();
VP_MakeLink = new ZCLink(**AP_LinkOrgin);
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink ;
}/*
while(--AL_FarNum >= 0)*/
APR_TailCopy=VP_TailLink;
}/*
_NP_ void SendFreeOutCopy ////////////////////////////////
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
////////////////////////////////////////////////////////*/
_NP_ void DeleteHeap(){}
_NP_ void MakeEuqal(ZtCBody& rhs)
{
}/*
_NP_ void MakeEuqal(ZtCBody& rhs)*/
_NP_ TypeSize GetUseHeapSize() const
{
return 0;
}/*
_NP_ TypeSize GetUseHeapSize() const*/
_NP_ TypeSize size() const
{
return GetUseHeapSize();
}/*
_NP_ TypeSize size() const*/
public:
};/*
template<typename TSnglList> class ZtCBody*/
public:
};/*
template<int TTypIListKind=0> class ZtCFreeHeapSngl*/
template<int TTypIListKind=0> class ZtCFreeHeapCDL // Circular Double List
{
public:
template<typename TLinkList> class ZtCBody
{
public:
typedef typename TLinkList::ZCLink ZCLink ;
typedef typename TLinkList::TypeSize TypeSize;
public:
_NP_ void RecvFreeIn(ZCLink* AP_CutLink){delete AP_CutLink;}
_NP_ void RecvFreeIn ///////////////////////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
////////////////////////////////////////////////////////////
{
ZCLink* VP_DelLink = AP_CutHead;
__for0(TypeSize, i, AL_CutCnt)
{
AP_CutHead = AP_CutHead->GetNextPtr() ;
delete VP_DelLink; VP_DelLink=AP_CutHead;
}/*
__for0(TypeSize, i, AL_CutCnt)*/
}
////////////////////////////////////////////////////////////
_NP_ ZCLink* SendFreeOut(){return new ZCLink;}
_NP_ void SendFreeOut ///////////////////////////////////
(
TypeSize AL_NeedCnt ,
ZCLink*& APR_HeadLink ,
ZCLink*& APR_TailLink
)
////////////////////////////////////////////////////////////
{
APR_HeadLink = new ZCLink;
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = APR_HeadLink;
while(--AL_NeedCnt>0) // AL_NeedCnt - 1 번 순환
{
// AL_NeedCnt - 1 번 순환
VP_MakeLink = new ZCLink;
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink ;
}/*
while(--AL_NeedCnt>0)*/
APR_TailLink = VP_TailLink;
}
////////////////////////////////////////////////////////////
_NP_ void SendFreeOutCopy /*////////////////////////////*/
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
//////////////////////////////////////////////////////////
{
// 총 AL_FarNum+1 개의 링크가 만들어짊
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = 0 ;
VP_TailLink = VP_MakeLink =
new ZCLink(**AP_LinkOrgin) ;
APR_HeadCopy = VP_MakeLink;
while(--AL_FarNum >= 0)
{
AP_LinkOrgin= AP_LinkOrgin->GetNextPtr();
VP_MakeLink = new ZCLink(**AP_LinkOrgin);
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink;
}/*
while(--AL_FarNum >= 0)*/
APR_TailCopy=VP_TailLink;
}/*
_NP_ void SendFreeOutCopy ////////////////////////////////
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
////////////////////////////////////////////////////////*/
_NP_ void DeleteHeap(){}
_NP_ void MakeEuqal(ZtCBody& rhs)
{
}/*
_NP_ void MakeEuqal(ZtCBody& rhs)*/
_NP_ TypeSize GetUseHeapSize() const
{
return 0;
}/*
_NP_ TypeSize GetUseHeapSize() const*/
_NP_ TypeSize size() const
{
return GetUseHeapSize();
}/*
_NP_ TypeSize size() const*/
public:
};/*
template<typename TLinkList> class ZtCBody*/
public:
};/*
template<int TTypIListKind=0> class ZtCFreeHeapCDL*/
}/*
namespace ZNsIFaceEx*/
namespace ZNsConst
{
// cf) ZtCSimList, ZtObjList
const int CI_ListKind_Single = 10 ;
const int CI_ListKind_Double = 20 ;
}/*
namespace ZNsConst*/
/*//////////////////////////////////////////////////////////////////
■ 템플릿 인자를 정의할 때 참조로 하지 않은 경우에 object 의 크기가
크면 포인터로 넘겨야 하는데, 이러면 어느 object 의 포인터인지 알
수 있지만 그 object 에 속한 enum 형이나 typedef 선언 및 기타 자료
형은 알 수 없다. 그래서 object 의 포인터를 포장하는 클래스 템플릿
ZtCObjPtr<> 을 설계한다.
■ typedef ZtCStringBase<char > CStringBase;
typedef ZtCObjPtr <CStringBase> CObjectPtr ;
라는 선언이 있으면 CStringBase::TypeChar 에 접근할 때에는
CObjectPtr::TypeData::TypeChar 로 하면 된다.
■ 포인터 자료형에 대하여 ZtCObjPtr<> 대신 더 간단하게
ZtCTypeData<> 를 사용해도 된다. 이 편이 오히려 낳을 것 같다.
-- 2010-01-24 22:25:00
//////////////////////////////////////////////////////////////////*/
template
<typename TType, typename TTypArgu=const TType&>
class ZtCObjPtr
{
public :
typedef TType TypeData ;
typedef TTypArgu TypeArg ;
protected:
TypeData& mr_TypeData;
public :
ZtCObjPtr(TType& AR_CData) : mr_TypeData(AR_CData ){}
ZtCObjPtr(ZtCObjPtr& AR_Rhs ) : mr_TypeData(AR_Rhs.mr_TypeData){}
TypeData* operator->(){return &mr_TypeData;}
TypeData& operator* (){return mr_TypeData;}
operator TypeData& (){return mr_TypeData;}
ZtCObjPtr& operator=(const ZtCObjPtr& rhs)
{
if(this==&rhs) return *this;
mr_TypeData = rhs.mr_TypeData; return *this;
}/*
ZtCObjPtr& operator=(const ZtCObjPtr& rhs)*/
ZtCObjPtr& operator=(TTypArgu AO_ArguData)
{
mr_TypeData = AO_ArguData; return *this;
}/*
ZtCObjPtr& operator=(TTypArgu AO_ArguData)*/
public :
};/*
template
<typename TType, typename TTypArgu=const TType&>
class ZtCObjPtr
*/
template<typename TType> class ZtCObjOpt // C++ 17 에 추가된 optional 구현
{
public :
typedef TType TypeData;
protected:
TypeData* mp_TypeData ;
public :
ZtCObjOpt(TypeData& AR_CData) : mp_TypeData(&AR_CData ){}
ZtCObjOpt(TypeData* AP_CData) : mp_TypeData( AP_CData ){}
ZtCObjOpt(ZtCObjOpt& AR_Rhs ) : mp_TypeData(AR_Rhs.mp_TypeData){}
TypeData* operator->(){return mp_TypeData;}
TypeData& operator* (){return *mp_TypeData;}
TypeData& operator()(){return *mp_TypeData;}
operator TypeData& (){return *mp_TypeData;}
const TypeData* operator->() const{return mp_TypeData;}
const TypeData& operator* () const{return *mp_TypeData;}
const TypeData& operator()() const{return *mp_TypeData;}
operator const TypeData& () const{return *mp_TypeData;}
ZtCObjOpt& operator=(const ZtCObjOpt& rhs)
{ mp_TypeData=rhs.mp_TypeData; return *this; }
operator bool () const{return mp_TypeData!=0;}
bool has_value () const{return mp_TypeData!=0;}
/***/ TypeData& value() {return *mp_TypeData;}
const TypeData& value() const{return *mp_TypeData;}
TypeData* Raw() const{return mp_TypeData;}
public :
};/*
template<typename TType> class ZtCObjOpt */
/*///////////////////////////////////////////////////////////
■ object 를 heap 에 생성하고, 참조 카운트를 이용하여 관리.
-- 2014-07-20 04:49:00
///////////////////////////////////////////////////////////*/
template< typename TType, typename TAllocClass=ZCAllocClass
>
class ZtCObjNew : public TAllocClass ////////////////////////
{
public :
typedef TType TypeData ;
typedef TAllocClass ZCAllocator;
typedef TAllocClass ZCAlloClass;
private:
struct StTypeRefCnt
{
TType MO_TypeData;
ZTypInt MI_RefCount;
StTypeRefCnt(){MI_RefCount=0;}
};/*
struct StTypeRefCnt*/
private:
StTypeRefCnt* mp_StTypeRefCnt;
public :
ZtCObjNew()
{
mp_StTypeRefCnt = (StTypeRefCnt*)
this->ZCAllocator::InitMem(sizeof(StTypeRefCnt));
mp_StTypeRefCnt->MI_RefCount = 1 ;
new(&mp_StTypeRefCnt->MO_TypeData) TypeData;
}/*
ZtCObjNew()*/
ZtCObjNew(const TypeData& AR_TypeData)
{
mp_StTypeRefCnt = (StTypeRefCnt*)
this->ZCAllocator::InitMem(sizeof(StTypeRefCnt));
mp_StTypeRefCnt->MI_RefCount = 1 ;
new(&mp_StTypeRefCnt->MO_TypeData) TypeData(AR_TypeData);
}/*
ZtCObjNew(const TypeData& AR_TypeData)*/
template<typename TTypeArg1, typename TTypeArg2>
ZtCObjNew(TTypeArg1& ArTTypeArg1, TTypeArg2& ArTTypeArg2)
{
mp_StTypeRefCnt = (StTypeRefCnt*)
this->ZCAllocator::InitMem(sizeof(StTypeRefCnt));
mp_StTypeRefCnt->MI_RefCount = 1 ;
new(&mp_StTypeRefCnt->MO_TypeData)
TypeData(ArTTypeArg1, ArTTypeArg2);
}/*
template<typename TTypeArg1, typename TTypeArg2>
ZtCObjNew(TTypeArg1& ArTTypeArg1, TTypeArg2& ArTTypeArg2))*/
ZtCObjNew(const ZtCObjNew& rhs)
{
mp_StTypeRefCnt = rhs.mp_StTypeRefCnt ;
++mp_StTypeRefCnt->MI_RefCount ;
}/*
ZtCObjNew(const ZtCObjNew& rhs)*/
~ZtCObjNew()
{
if(--mp_StTypeRefCnt->MI_RefCount <= 0)
this->ZCAllocator::FiniMem(mp_StTypeRefCnt);
}/*
~ZtCObjNew()*/
ZtCObjNew& operator=(const ZtCObjNew& rhs)
{
if(this==&rhs || mp_StTypeRefCnt==rhs.mp_StTypeRefCnt)
{ return *this; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
#if(_CODE_OLD_)
mp_StTypeRefCnt->MO_TypeData =
rhs.mp_StTypeRefCnt->MO_TypeData ;
#else
/*//////////////////////////////////////////////
■ ZtCObjNew 를 설계한 뜻에 비추어,
위보다 아래 코드가 더 적합해 보인다.
만약 위 코드의 동작을 수행하려면
**this = *rhs
처럼 하면 된다. -- 2025-10-05 21:42
//////////////////////////////////////////////*/
if(--mp_StTypeRefCnt->MI_RefCount <= 0)
this->ZCAllocator::FiniMem(mp_StTypeRefCnt);
mp_StTypeRefCnt = rhs.mp_StTypeRefCnt ;
++mp_StTypeRefCnt->MI_RefCount ;
#endif
return *this; /*::::::::::::::::::::::::::::::*/
}/*
ZtCObjNew& operator=(const ZtCObjNew& rhs)*/
ZtCObjNew& operator=(const TypeData& AR_TypeData)
{
if(&mp_StTypeRefCnt->MO_TypeData==&AR_TypeData) return *this;
mp_StTypeRefCnt->MO_TypeData = AR_TypeData; return *this;
}/*
ZtCObjNew& 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& GetObjRef () const{return &mp_StTypeRefCnt->MO_TypeData;}
public :
};/*
template< typename TType, typename TAllocClass=ZCAllocClass
>
class ZtCObjNew : 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"<<std::endl;
fileout.close();
::exit(1);
}/*
if(_REENTRANT_BOOL_<1)*/
}/*
inline void _DEBUG_REENTRANT_Check()*/
#define _DEBUG_REENTRANT_CHECK_ _DEBUG_REENTRANT_Check();
#else // !defined(_DEBUG)
#define _DEBUG_REENTRANT_CHECK_
#endif // !defined(_DEBUG)
#if defined(_REENTRANT)
class ZCExceptSmallLock : public ZCExceptBase
{
private:
long ml_ErrCode;
string mo_ErrMSG ;
public :
ZCExceptSmallLock(long AL_ErrCode, const char* AP_ErrMSG)
{
ml_ErrCode=AL_ErrCode; //////////////
if(AP_ErrMSG!=0) mo_ErrMSG=AP_ErrMSG;
}/*
ZCExceptSmallLock(long AL_ErrCode, const char* AP_ErrMSG)*/
long GetErrCode() const{return ml_ErrCode;}
const string& GetErrMSG () const{return mo_ErrMSG ;}
public:
};/*
class ZCExceptSmallLock : public ZCExceptBase*/
#endif //defined(_REENTRANT)
#if defined(_REENTRANT) && defined(_WIN)
/*//////////////////////////////////////////////////////
■ 아래 클래스는 여러 자료구조에서 내부적으로 정적변수나
정적 object 를 동기화하기 위해 사용한다.
윈도우에서는 크리티컬 섹션을 쓰는 것이 좋으나
BOOL TryEnterCriticalSection(LPCRITICAL_SECTION)
함수가 제대로 지원되지 않고 있다.
//////////////////////////////////////////////////////*/
class ZCMutexSmallLock;
class ZCMutexSmallInit
{
private:
HANDLE mh_Mutex;
public :
/*/////////////////////////////////////////////////////////
Administrator@q381-2673 UCRT64 /e/my_CPP/ZCpp/ZCppMainTest
# g++.exe -o ZtCArray_000_mw.exe ZtCArray_000.cpp -I../
In file included from ../ZCppMain/ZtCArray.H:7,
from ZtCArray_000.cpp:4:
../ZCppMain/ZMainHead.H:3115:21: error: ISO C++17 does not allow dynamic exception specifications
3115 | void Lock() throw(ZCExceptSmallLock&)
/////////////////////////////////////////////////////////*/
void Lock() /*throw(ZCExceptSmallLock&)*/
{
long VL_ErrCode=0;
if((VL_ErrCode = ::WaitForSingleObject(mh_Mutex, INFINITE))==WAIT_ABANDONED)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::Lock()");
}/*
if((VL_ErrCode = ::WaitForSingleObject(mh_Mutex, INFINITE))==WAIT_ABANDONED)*/
}/*
void Lock() //throw(ZCExceptSmallLock&)*/
void UnLock()
{
::ReleaseMutex(mh_Mutex);
}/*
void UnLock()*/
ZCMutexSmallInit()
{
/* MUTEX 를 신호 상태로 만들고 이 함수를 호출한 쓰레드가 MUTEX 를 소유하지 않게
한다. 신호 상태라 함은 다른 쓰레드가 진입할 수 있는 상태를 말한다. */
mh_Mutex = ::CreateMutex(NULL, FALSE, NULL);
}/*
ZCMutexSmallInit()*/
~ZCMutexSmallInit()
{
::CloseHandle(mh_Mutex);
}/*
~ZCMutexSmallInit()*/
public:
};/*
class ZCMutexSmallInit*/
class ZCMutexSmallLock
{
private:
ZCMutexSmallInit& mr_ZCMutexInit;
public :
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit):mr_ZCMutexInit(ArZCMutexInit)
{
mr_ZCMutexInit.Lock();
}/*
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit)*/
~ZCMutexSmallLock()
{
mr_ZCMutexInit.UnLock();
}/*
~ZCMutexSmallLock()*/
public:
};/*
class ZCMutexSmallLock*/
#elif defined(_REENTRANT) && defined(__unix__)
// 유닉스(특히 리눅스) 상에서 _REENTRANT 이 정의되어 있으면
// -lpthread 옵션을 잊지 말 것.
class ZCMutexSmallLock;
class ZCMutexSmallInit
{
private:
::pthread_mutex_t mo_Mutex;
public :
void Lock() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode = ::pthread_mutex_lock(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::Lock()");
}/*
if((VL_ErrCode = ::pthread_mutex_lock(&mo_Mutex))!=0)*/
}/*
void Lock() throw(ZCExceptSmallLock&)*/
void UnLock() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode=::pthread_mutex_unlock(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::UnLock()");
}/*
if((VL_ErrCode=::pthread_mutex_unlock(&mo_Mutex))!=0)*/
}/*
void UnLock() throw(ZCExceptSmallLock&)*/
ZCMutexSmallInit() throw(ZCExceptSmallLock&)
{
::pthread_mutexattr_t VO_MutexAttr;
::pthread_mutexattr_init(&VO_MutexAttr);
::pthread_mutexattr_settype(&VO_MutexAttr, PTHREAD_MUTEX_RECURSIVE);
long VL_ErrCode=0;
if((VL_ErrCode = ::pthread_mutex_init(&mo_Mutex, &VO_MutexAttr))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::ZCMutexSmallInit()");
}/*
if((VL_ErrCode = ::pthread_mutex_init(&mo_Mutex, &VO_MutexAttr))!=0)*/
}/*
ZCMutexSmallInit() throw(ZCExceptSmallLock&)*/
~ZCMutexSmallInit() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode = ::pthread_mutex_destroy(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::~ZCMutexSmallInit()");
}/*
if((VL_ErrCode = ::pthread_mutex_destroy(&mo_Mutex))!=0)*/
}/*
~ZCMutexSmallInit() throw(ZCExceptSmallLock&)*/
public:
};/*
class ZCMutexSmallInit*/
class ZCMutexSmallLock
{
private:
ZCMutexSmallInit& mr_ZCMutexInit;
public :
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit):mr_ZCMutexInit(ArZCMutexInit)
{
mr_ZCMutexInit.Lock();
}/*
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit)*/
~ZCMutexSmallLock()
{
mr_ZCMutexInit.UnLock();
}/*
~ZCMutexSmallLock()*/
public:
};/*
class ZCMutexSmallLock*/
// defined(_REENTRANT) && defined(__unix__)
#elif defined(_REENTRANT)
// _REENTRANT 이 정의되어 있으면 -lpthread 옵션을 잊지 말 것.
class ZCMutexSmallLock;
class ZCMutexSmallInit
{
private:
::pthread_mutex_t mo_Mutex;
public :
void Lock() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode=::pthread_mutex_lock(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::Lock()");
}/*
if((VL_ErrCode=::pthread_mutex_lock(&mo_Mutex))!=0)*/
}/*
void Lock() throw(ZCExceptSmallLock&)*/
void UnLock() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode=::pthread_mutex_unlock(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::UnLock()");
}/*
if((VL_ErrCode=::pthread_mutex_unlock(&mo_Mutex))!=0)*/
}/*
void UnLock() throw(ZCExceptSmallLock&)*/
ZCMutexSmallInit() throw(ZCExceptSmallLock&)
{
::pthread_mutexattr_t VO_MutexAttr;
::pthread_mutexattr_init(&VO_MutexAttr);
::pthread_mutexattr_settype(&VO_MutexAttr, PTHREAD_MUTEX_RECURSIVE);
long VL_ErrCode=0;
if((VL_ErrCode= ::pthread_mutex_init(&mo_Mutex, &VO_MutexAttr))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::ZCMutexSmallInit()");
}/*
if((VL_ErrCode= ::pthread_mutex_init(&mo_Mutex, &VO_MutexAttr))!=0)*/
}/*
ZCMutexSmallInit() throw(ZCExceptSmallLock&)*/
~ZCMutexSmallInit() throw(ZCExceptSmallLock&)
{
long VL_ErrCode=0;
if((VL_ErrCode= ::pthread_mutex_destroy(&mo_Mutex))!=0)
{
throw ZCExceptSmallLock(VL_ErrCode, "ZCMutexSmallInit::~ZCMutexSmallInit()");
}/*
if((VL_ErrCode= ::pthread_mutex_destroy(&mo_Mutex))!=0)*/
}/*
~ZCMutexSmallInit() throw(ZCExceptSmallLock&)*/
public:
};/*
class ZCMutexSmallInit*/
class ZCMutexSmallLock
{
private:
ZCMutexSmallInit& mr_ZCMutexInit;
public :
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit):mr_ZCMutexInit(ArZCMutexInit)
{
mr_ZCMutexInit.Lock();
}/*
ZCMutexSmallLock(ZCMutexSmallInit& ArZCMutexInit)*/
~ZCMutexSmallLock()
{
mr_ZCMutexInit.UnLock();
}/*
~ZCMutexSmallLock()*/
public :
};/*
class ZCMutexSmallLock*/
#endif //defined(_REENTRANT)
#if defined(_DEBUG) && defined(_REENTRANT)
class ZCSyncLog
{
private :
typedef ZCMutexSmallInit ZCSync;
protected:
static ZCSync& GetCSync()
{
static ZCSync SO_CSyncLog; return SO_CSyncLog;
}/*
static ZCSync& GetCSync()*/
public :
ZCSyncLog (){GetCSync().Lock ();}
~ZCSyncLog(){GetCSync().UnLock();}
public :
};/*
class ZCSyncLog*/
#endif // defined(_DEBUG) && defined(_REENTRANT)
#ifdef _DEBUG
static inline void ZfWriteError(const char* ApcErrorStr)
{
std::fstream fileout(
"DEBUG.txt", std::ios::out | std::ios::app);
fileout<<ApcErrorStr<<std::endl;
fileout.close();
::exit(1);
}/*
static inline void ZfWriteError(const char* ApcErrorStr)*/
/*///////////////////////////////////////////////////////////////////
■ 이 object 를 멤버로 가진 object 는 container 외부에 만들어질 수 없다.
container 의 링크나 노드를 설계할 때 그 링크나 노드가(DEBUG 모드에서)
Stack 에 만들어지는지 혹은 container 외부에서 new 로 만들어지는지를
체크할 때 유용하다. container 의 링크는 container 내부에서만 new,
delete 되어야 한다.
///////////////////////////////////////////////////////////////////*/
class ZCCheckAlloc
{
public :
class ZCAllowAlloc; friend class ZCAllowAlloc;
private:
static bool& GetAllowAllocBool()
{
static bool SB_AllowAlloc=false; return SB_AllowAlloc;
}/*
static bool& GetAllowAllocBool()*/
/*private:*/
public :
ZCCheckAlloc()
{
if(GetAllowAllocBool()==false)
{
cout<<endl<<"Warning! Unallowed Object Memory Allocation!"<<endl<<endl;
}/*
if(GetAllowAllocBool()==false)*/
}/*
ZCCheckAlloc()*/
static bool IsAllowAlloc()
{
return GetAllowAllocBool();
}/*
static bool IsAllowAlloc()*/
/*public:*/
public:
class ZCAllowAlloc
{
private:
bool mb_AllowAlready ;
/*///////////////////////////////////////////////////////
■ 위 멤버변수를 설계하면 ZCAllowAlloc object 멤버함수가
중첩호출될 경우, 가장 처음에 호출하는 함수가
ZCCheckAlloc::GetAllowAllocBool()=false;
이 부분을 수행하게 된다. 결국 중첩호출 도중에
ZCCheckAlloc::GetAllowAllocBool() 은 항상 true 가 된다.
■ --
///////////////////////////////////////////////////////*/
/*private:*/
public :
ZCAllowAlloc()
{
mb_AllowAlready=ZCCheckAlloc::GetAllowAllocBool();
ZCCheckAlloc::GetAllowAllocBool()=true; //////////
}/*
ZCAllowAlloc()*/
~ZCAllowAlloc()
{
if(mb_AllowAlready==false)
ZCCheckAlloc::GetAllowAllocBool()=false;
}/*
ZCAllowAlloc()*/
public:
};/*
class ZCAllowAlloc()*/
public:
};/*
class ZCCheckAlloc*/
#endif //_DEBUG
/*###################################################################
■ template<typename TClass, typename TTypInt> class ZtCCount 는
주로 DEBUG 용도나 어떤 객체의 수행 상태를 추적할 때 사용할 것
이다. -- 2025-10-10 21:43
###################################################################*/
template<typename TClass, typename TTypInt=ZTypLong> class ZtCCount
{
public :
typedef TTypInt TypeInt ;
typedef TClass TypeData;
private:
static TypeInt msi_Count;
public :
/*******************************************************************/
static TypeInt Curr (){return ZtCCount::msi_Count;}
/*******************************************************************/
static TypeInt Plus (ZTypLong AL_Plus=1)
{ return ZtCCount::msi_Count += AL_Plus; }
static TypeInt Minus(ZTypLong AL_Plus=1)
{ return ZtCCount::msi_Count -= AL_Plus; }
/*******************************************************************/
public :
};/*
template<typename TClass, typename TTypInt=ZTypLong> class ZtCCount*/
/*******************************************************************/
template<typename TClass, typename TTypInt>
TTypInt ZtCCount<TClass, TTypInt>::msi_Count= 0 ;
/*******************************************************************/
namespace ZNsConst
{
#if defined(_WIN)
#define __DIR_DELIMITERS__ "\\"
#define __DIR_DELIMITER__ '\\'
ZTypCPCCh CPC_DirDelimiter="\\";
ZTypCChar CC_DirDelimiter ='\\';
ZTypCPCCh CPC_Delm ="\\";
ZTypCChar CC_Delm ='\\';
#else //!(defined(_WIN)
#define __DIR_DELIMITERS__ "/"
#define __DIR_DELIMITER__ '/'
ZTypCPCCh CPC_DirDelimiter="/" ;
ZTypCChar CC_DirDelimiter ='/' ;
ZTypCPCCh CPC_Delm ="/" ;
ZTypCChar CC_Delm ='/' ;
#endif //!(defined(_WIN)
}/*
namespace ZNsConst*/
template<typename TStringData> TStringData& ZftConvertXhtml(TStringData& ARRoCString)
{
/* 데이타를 그대로 클라이언트에 전송하면, HTML 태그와
혼동될 수 있는데, 이를 방지하기 위해 적절히 인코딩한다.
*/
return ARRoCString.
Replace("&" ,"&amp;" ). Replace("<" ,"&lt;" ).
Replace(">" ,"&gt;" ). Replace(" " ,"&nbsp;").
Replace("\n","<br />" );
}/*
template<typename TStringData> TStringData& ConvertXhtml(TStringData& ARRoCString) */
template<typename TStringData> TStringData& ZftMakeXmlAttEnc(TStringData& ARRoCStringData)
{
return ARRoCStringData.
Replace("&" , "&amp;" ).Replace("\r", "&#xA;" ).
Replace("\n", "&#xD;" ).Replace("\t", "&#x9;" ).
Replace("\"", "&quot;").Replace(">" , "&gt;" ).Replace("<", "&lt;");
}/*
template<typename TStringData> TStringData& ZftMakeXmlAttEnc(TStringData& ARRoCStringData)*/
template<typename TStringData> TStringData& ZftMakeXmlAttDec(TStringData& ARRoCStringData)
{
return ARRoCStringData.
Replace("&#xA;" ,"\r" ). Replace("&#xD;" ,"\n").
Replace("&#x9;" ,"\t" ). Replace("&quot;","\"").
Replace("&gt;" ,">" ). Replace("&lt;" ,"<" ). Replace("&amp;" ,"&" );
}/*
template<typename TStringData> TStringData& ZftMakeXmlAttDec(TStringData& ARRoCStringData)*/
template<typename TString, typename TObject>
TString& ZftMakeStr(TString& ARR_SaveCStr, TObject AO_Object)
{ return ARR_SaveCStr; }
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, const string& AR_DataCStr)
{ ARR_SaveCStr.append(AR_DataCStr); return ARR_SaveCStr; }
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, const wstring& AR_DataCStr)
{ ARR_SaveCStr.append(AR_DataCStr); return ARR_SaveCStr; }
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, int AI_Int)
{
ZTycInt CI_BuffSize = 31 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
::sprintf(VCA_BuffParam, "%d", AI_Int);
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, int AI_Int)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, int AI_Int)
{
ZTycInt CI_BuffSize = 31 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%d", AI_Int);
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize) ;
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, int AI_Int)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, long AL_Long)
{
ZTycInt CI_BuffSize = 31 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
::sprintf(VCA_BuffParam, "%ld", AL_Long);
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, long AL_Long)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, long AL_Long)
{
ZTycInt CI_BuffSize = 31 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%ld", AL_Long);
ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize) ;
return ARR_SaveCStr;
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, long AL_Long)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypLLong ALL_Long)
{
ZTycInt CI_BuffSize = 41 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
( ::sprintf(VCA_BuffParam, "%lld" , ALL_Long) );
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypLLong ALL_Long)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypLLong ALL_Long)
{
ZTycInt CI_BuffSize = 41 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%lld" , ALL_Long) ;
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypLLong ALL_Long)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntUI AUI_Int)
{
ZTycInt CI_BuffSize = 31 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
( ::sprintf(VCA_BuffParam, "%u" , AUI_Int) );
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntUI AUI_Int)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntUI AUI_Int)
{
ZTycInt CI_BuffSize = 31 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%u" , AUI_Int) ;
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntUI AUI_Int)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntUL AUL_Int)
{
ZTycInt CI_BuffSize = 41 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
( ::sprintf(VCA_BuffParam, "%lu" , AUL_Int) );
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntUL AUL_Int)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntUL AUL_Int)
{
ZTycInt CI_BuffSize = 41 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%lu" , AUL_Int) ;
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntUL AUL_Int)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntULL AULL_Int)
{
ZTycInt CI_BuffSize = 41 ;
ZTypChar VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize =
( ::sprintf(VCA_BuffParam, "%llu" , AULL_Int) );
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, ZTypIntULL AULL_Int)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntULL AULL_Int)
{
ZTycInt CI_BuffSize = 41 ;
ZTypCharW VCA_BuffParam[CI_BuffSize] ;
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%llu" , AULL_Int) ;
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, ZTypIntULL AULL_Int)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, double AD_Double)
{
ZTycInt CI_BuffSize=51 ;
ZTypChar VCA_BuffParam[CI_BuffSize];
ZTypInt VI_ResultSize = ::sprintf
( VCA_BuffParam, "%f", AD_Double );
/********************************/
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> string& ZftMakeStr(string& ARR_SaveCStr, double AD_Double)*/
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, double AD_Double)
{
ZTycInt CI_BuffSize=51 ;
ZTypCharW VCA_BuffParam[CI_BuffSize];
ZTypInt VI_ResultSize = ::swprintf
(VCA_BuffParam, CI_BuffSize, L"%f", AD_Double);
/*********************************/
return ARR_SaveCStr.append
(VCA_BuffParam, VI_ResultSize);
}/*
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, double AD_Double)*/
/*============================================================================*/
template<> string& ZftMakeStr(string& ARR_SaveCStr, bool AB_Bool)
{ return ARR_SaveCStr.append( AB_Bool ? "true" : "false" ); }
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, bool AB_Bool)
{ return ARR_SaveCStr.append( AB_Bool ? L"true" : L"false" ); }
/*============================================================================*/
template<typename TTypeChar, typename TTypeLength>
class ZtCChars ;
/*++++++++++++++++++++++++++++++++++++++++++++++*/
template<> string & ZftMakeStr
(string& ARR_SaveCStr, const ZtCChars<char , ZTypLength>& AR_View);
template<> wstring& ZftMakeStr
(wstring& ARR_SaveCStr, const ZtCChars<wchar_t, ZTypLength>& AR_View);
// class ZtCBaseList : circular double linked list
template //////////////////////////////////////////////////////////////////
<
typename TType ,
typename TTypArgu = const TType& ,
typename TTypeAlloc = ZCAllocator ,
typename TTypSize = ZTypLong ,
typename TMoveObj = ZNsMain::
ZtCMoveObj<TType, TTypArgu, true> ,
typename TTypeCRTP = ZNsType::ZtCTypeCRTP<ZCEmpty, false>
>
class ZtCBaseList /*#####################################################*/
{
public:
class ZCLink; class ZCNodePoint; class ZCNodePointN;
/*************************************************************************/
typedef ZtCObjOpt<ZCLink> ZCLinkOpt ;
typedef ZtCObjOpt<TType > ZCDataOpt ;
/*************************************************************************/
typedef ZtCBaseList TypeThis ;
typedef ZtCBaseList TypeList ;
typedef TType TypeData ;
typedef TTypArgu TypeArg ;
typedef TTypeAlloc TypeAlloc ;
typedef TTypSize TypeSize ;
typedef TMoveObj TypeMoveObj ;
typedef ZCLink TypeLink ;
typedef ZCLink TypeNode ; // ZCNodePoint::GetNode() 의 반환형.
typedef ZCNodePoint TypeNodePoint ;
typedef ZCNodePoint TypeIter ;
typedef ZCLink* IterEasy ; // 가장 쉽게 쓸 수 있는 반복자.
typedef ZCNodePointN iteratorN ;
typedef ZCNodePoint iterator ; // 다양한 기능을 가진 반복자.
typedef ZCNodePointN const_iterator;
typedef const TypeThis TypeThisC ;
typedef const TypeList TypeListC ;
typedef const TypeData TypeDataC ;
typedef const TypeNode TypeNodeC ; // ZCNodePoint::GetNode() const 의 반환형.
typedef const TypeLink TypeLinkC ;
typedef const TypeIter TypeIterC ;
typedef const ZCLink ZCLinkC ;
typedef const ZCLink* IterEasyC ;
typedef const ZCLinkOpt ZCLinkOptC ;
typedef const ZCDataOpt ZCDataOptC ;
typedef ZCNodePointN TypeIterN ;
/*************************************************************************/
typedef ZNsType::ZtCTypeNowCRTP ///////////////////////////////////////
<
ZtCBaseList, typename TTypeCRTP::TypeData, TTypeCRTP::ZEUseCRTP
>
ZCTypeNowCRTP ; ///////////////////////////////////////////////////////
typedef typename ZCTypeNowCRTP::TypeData TypeChild;
/*************************************************************************/
public :
class ZCLink : public TypeAlloc
{
public :
friend class ZtCBaseList;
private:
ZCLink* mp_NextLink ;
ZCLink* mp_PrevLink ;
TypeData mo_DataObjt ;
private:
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
ZCLink* GetNextPtr() {return mp_NextLink;}
ZCLink* GetPrevPtr() {return mp_PrevLink;}
const ZCLink* GetNextPtr()const{return mp_NextLink;}
const ZCLink* GetPrevPtr()const{return mp_PrevLink;}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
private:
static void JoinLink(ZCLink* AP_PrevLink, ZCLink* AP_NextLink)
{
AP_PrevLink->mp_NextLink=AP_NextLink;
AP_NextLink->mp_PrevLink=AP_PrevLink;
}/*
static void JoinLink(ZCLink* AP_PrevLink, ZCLink* AP_NextLink)*/
static void MakeRing(ZCLink* AP_HeadLink, ZCLink* AP_TailLink)
{
AP_HeadLink->mp_PrevLink=AP_TailLink;
AP_TailLink->mp_NextLink=AP_HeadLink;
}/*
static void MakeRing(ZCLink* AP_HeadLink, ZCLink* AP_TailLink)*/
public:
ZCLink()
{
mp_NextLink = mp_PrevLink = 0;
}/*
ZCLink()*/
ZCLink(const ZCLink& rhs)
{
mo_DataObjt = rhs.mo_DataObjt ;
mp_NextLink = 0 ;
mp_PrevLink = 0 ;
}/*
ZCLink(const ZCLink& rhs)*/
ZCLink(TypeArg AR_Data)
{
mo_DataObjt = AR_Data ;
mp_NextLink = 0 ;
mp_PrevLink = 0 ;
}/*
ZCLink(const ZCLink& rhs)*/
ZCLink& operator=(const ZCLink& rhs)
{
mo_DataObjt = rhs.mo_DataObjt; return *this;
}/*
ZCLink& operator=(const ZCLink& rhs)*/
ZCLink * GetNextPrevPtr(TypeSize AL_FarNum)
{
ZCLink* VP_TmpLink=this;
if(AL_FarNum>=0)
{ while(--AL_FarNum>=0) VP_TmpLink=VP_TmpLink->mp_NextLink; }
else{ while(++AL_FarNum<=0) VP_TmpLink=VP_TmpLink->mp_PrevLink; }
return VP_TmpLink;
}/*
ZCLink * GetNextPrevPtr(TypeSize AL_FarNum)*/
ZCLinkC* GetNextPrevPtr(TypeSize AL_FarNum) const
{
ZCLinkC* VP_TmpLink = this;
if(AL_FarNum>=0)
{ while(--AL_FarNum>=0) VP_TmpLink=VP_TmpLink->mp_NextLink; }
else{ while(++AL_FarNum<=0) VP_TmpLink=VP_TmpLink->mp_PrevLink; }
return VP_TmpLink;
}/*
ZCLinkC* GetNextPrevPtr(TypeSize AL_FarNum) const*/
operator TypeData& () {return mo_DataObjt;}
operator TypeData () {return mo_DataObjt;}
TypeData & GetData () {return mo_DataObjt;}
TypeData & operator* () {return mo_DataObjt;}
TypeData & operator()() {return mo_DataObjt;}
operator TypeDataC&() const{return mo_DataObjt;}
TypeDataC& GetData () const{return mo_DataObjt;}
TypeDataC& operator* () const{return mo_DataObjt;}
TypeDataC& operator()() const{return mo_DataObjt;}
ZCLink & operator+(TypeSize AL_Distance)
{ return *GetNextPrevPtr( AL_Distance); }
ZCLink & operator-(TypeSize AL_Distance)
{ return *GetNextPrevPtr(-AL_Distance); }
ZCLinkC& operator+(TypeSize AL_Distance) const
{ return *GetNextPrevPtr( AL_Distance); }
ZCLinkC& operator-(TypeSize AL_Distance) const
{ return *GetNextPrevPtr(-AL_Distance); }
public:
};/*
class ZCLink*/
class ZCNodePoint
{
private:
/*****/ TypeList& mr_CurrList;
mutable TypeLink* mp_CurrLink; // 사실상 mp_CurrLink!=0
mutable TypeSize ml_CurrPos ;
public:
ZCNodePoint(TypeList& AR_TypeList) :
mr_CurrList(AR_TypeList)
{
mp_CurrLink = AR_TypeList.HeadPtr();
ml_CurrPos = 1 ;
}
ZCNodePoint(const ZCNodePoint& rhs) :
mr_CurrList(rhs.mr_CurrList),
mp_CurrLink(rhs.mp_CurrLink),
ml_CurrPos (rhs.ml_CurrPos )
{}
public :
static ZCNodePoint MakeTailPoint(TypeList& AR_TypeList)
{
ZCNodePoint VO_ZCLinkPoint(AR_TypeList);
VO_ZCLinkPoint.mp_CurrLink = AR_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = AR_TypeList.ml_LinkSize;
return VO_ZCLinkPoint; /****************************/
}/*
static ZCNodePoint MakeTailPoint(TypeList& AR_TypeList)*/
static ZCNodePoint MakeTailPoint(const TypeIter& AR_TypeIter)
{
ZCNodePoint VO_ZCLinkPoint(AR_TypeIter);
VO_ZCLinkPoint.mp_CurrLink = VO_ZCLinkPoint.mr_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = VO_ZCLinkPoint.mr_TypeList.ml_LinkSize;
return VO_ZCLinkPoint; /****************************/
}/*
static ZCNodePoint MakeTailPoint(const TypeIter& AR_TypeIter)*/
public :
TypeThis & GetMain() {return mr_CurrList;}
TypeNode & GetNode() {return *mp_CurrLink;}
TypeThisC& GetMain() const{return mr_CurrList;}
TypeNodeC& GetNode() const{return *mp_CurrLink;}
/***************************************************/
TypeSize GetPos () const{return ml_CurrPos ;}
/***************************************************/
bool IsValid() const{return mr_CurrList.size()>0;}
bool IsEmpty() const{return mr_CurrList.size()<1;}
ZCNodePoint& operator= (const ZCNodePoint& rhs){ return *this; }
TypeData & operator*() {return **mp_CurrLink;}
TypeDataC& operator*() const{return **mp_CurrLink;}
operator TypeLink * () {return mp_CurrLink;}
operator TypeLinkC* () const{return mp_CurrLink;}
operator TypeLink & () {return *mp_CurrLink;}
operator TypeLinkC& () const{return *mp_CurrLink;}
bool operator == (const ZCNodePoint& rhs) const
{ return ml_CurrPos == rhs.ml_CurrPos; }
bool operator != (const ZCNodePoint& rhs) const
{ return ml_CurrPos != rhs.ml_CurrPos; }
bool operator > (const ZCNodePoint& rhs) const
{ return ml_CurrPos > rhs.ml_CurrPos; }
bool operator >= (const ZCNodePoint& rhs) const
{ return ml_CurrPos >= rhs.ml_CurrPos; }
bool operator < (const ZCNodePoint& rhs) const
{ return ml_CurrPos < rhs.ml_CurrPos; }
bool operator <= (const ZCNodePoint& rhs) const
{ return ml_CurrPos <= rhs.ml_CurrPos; }
bool operator == (TypeSize AL_Size) const
{ return ml_CurrPos == AL_Size; }
bool operator != (TypeSize AL_Size) const
{ return ml_CurrPos != AL_Size; }
bool operator > (TypeSize AL_Size) const
{ return ml_CurrPos > AL_Size; }
bool operator >= (TypeSize AL_Size) const
{ return ml_CurrPos >= AL_Size; }
bool operator < (TypeSize AL_Size) const
{ return ml_CurrPos < AL_Size; }
bool operator <= (TypeSize AL_Size) const
{ return ml_CurrPos <= AL_Size; }
const ZCNodePoint& operator++() const
{
mp_CurrLink = mp_CurrLink->mp_NextLink;
++ml_CurrPos; return *this ;
}/*
const ZCNodePoint& operator++() const*/
const ZCNodePoint& operator--() const
{
mp_CurrLink = mp_CurrLink->mp_PrevLink;
--ml_CurrPos; return *this ;
}/*
const ZCNodePoint& operator--() const*/
ZCNodePoint operator++(int) const
{
ZCNodePoint VO_NowPoint(*this);
mp_CurrLink = mp_CurrLink->mp_NextLink;
++ml_CurrPos ; return VO_NowPoint ;
}/*
ZCNodePoint operator++(int) const*/
ZCNodePoint operator--(int) const
{
ZCNodePoint VO_NowPoint(*this);
mp_CurrLink = mp_CurrLink->mp_PrevLink;
--ml_CurrPos; return VO_NowPoint ;
}/*
ZCNodePoint operator--(int) const*/
const ZCNodePoint& operator+=(TypeSize AL_Distance) const
{
if(IsEmpty()){return *this;}
mp_CurrLink = &((*mp_CurrLink)+AL_Distance) ;
ml_CurrPos += AL_Distance ;
return *this; /*:::::::::::::::::::::::::::*/
}/*
const ZCNodePoint& operator+=(TypeSize AL_Distance) const*/
const ZCNodePoint& operator-=(TypeSize AL_Distance) const
{
mp_CurrLink = &((*mp_CurrLink)-AL_Distance);
ml_CurrPos -= AL_Distance ;
return *this; /*::::::::::::::::::::::::::*/
}/*
const ZCNodePoint& operator-=(TypeSize AL_Distance) const*/
public:
};/*
class ZCNodePoint*/
/*///////////////////////////////////////////////////////////////
■ 상수 전용 클래스에는 const 의 N 을 붙이는 것으로 하자.
C 는 보통의 클래스가 특정 상황에서 읽기 전용일 경우에
typdef const some_class some_classC;
형태로 사용할 때 붙였다. -- 2025-10-14 09:08
그렇다면 const ZCNodePointN 을 간단하게 하면 ZCNodePointNC
로 해야 할까? 그런데 ZCNodePointN 자체가 const 전용이므로,
const ZCNodePointN 는 사실 별 의미가 없다. 복사 생성자나 대입
연산자나 비교 연산자 정의에서나 잠깐 필요하다.
-- 2025-10-14 10:38
///////////////////////////////////////////////////////////////*/
class ZCNodePointN
{
protected:
const TypeList& mr_CurrList;
mutable TypeLinkC* mp_CurrLink; // 사실상 mp_CurrLink!=0
mutable TypeSize ml_CurrPos ;
public :
ZCNodePointN(const TypeList& AR_TypeList) :
mr_CurrList(AR_TypeList)
{
mp_CurrLink = AR_TypeList.HeadPtr();
ml_CurrPos = 1 ;
}
ZCNodePointN(const ZCNodePoint & rhs) :
mr_CurrList( rhs.GetMain()),
mp_CurrLink(&rhs.GetNode()),
ml_CurrPos ( rhs.GetPos ())
{}
ZCNodePointN(const ZCNodePointN& rhs) :
mr_CurrList(rhs.mr_CurrList),
mp_CurrLink(rhs.mp_CurrLink),
ml_CurrPos (rhs.ml_CurrPos )
{}
public :
static ZCNodePointN MakeTailPoint(const TypeList& AR_TypeList)
{
ZCNodePointN VO_ZCLinkPoint(AR_TypeList);
VO_ZCLinkPoint.mp_CurrLink = AR_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = AR_TypeList.ml_LinkSize;
return VO_ZCLinkPoint; /****************/
}/*
static ZCNodePointN MakeTailPoint(const TypeList& AR_TypeList)*/
static ZCNodePointN MakeTailPoint(const ZCNodePoint & AR_TypeIter)
{
ZCNodePointN VO_ZCLinkPoint(AR_TypeIter);
VO_ZCLinkPoint.mp_CurrLink = VO_ZCLinkPoint.mr_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = VO_ZCLinkPoint.mr_TypeList.ml_LinkSize;
return VO_ZCLinkPoint; /****************/
}/*
static ZCNodePointN MakeTailPoint(const ZCNodePoint & AR_TypeIter)*/
static ZCNodePointN MakeTailPoint(const ZCNodePointN& AR_TypeIter)
{
ZCNodePointN VO_ZCLinkPoint(AR_TypeIter);
VO_ZCLinkPoint.mp_CurrLink = VO_ZCLinkPoint.mr_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = VO_ZCLinkPoint.mr_TypeList.ml_LinkSize;
return VO_ZCLinkPoint; /****************/
}/*
static ZCNodePointN MakeTailPoint(const ZCNodePointN& AR_TypeIter)*/
public :
TypeThisC& GetMain() const{return mr_CurrList;}
TypeNodeC& GetNode() const{return *mp_CurrLink;}
/***************************************************/
TypeSize GetPos () const{return ml_CurrPos ;}
/***************************************************/
bool IsValid() const{return mr_CurrList.size()>0;}
bool IsEmpty() const{return mr_CurrList.size()<1;}
ZCNodePointN& operator= (const ZCNodePointN& rhs){ return *this; }
TypeDataC& operator*() const{return **mp_CurrLink;}
operator TypeNodeC* () const{return mp_CurrLink;}
operator TypeNodeC& () const{return *mp_CurrLink;}
operator TypeNode * () const{return 0 ;}
bool operator == (const ZCNodePointN& rhs) const
{ return ml_CurrPos == rhs.ml_CurrPos; }
bool operator != (const ZCNodePointN& rhs) const
{ return ml_CurrPos != rhs.ml_CurrPos; }
bool operator > (const ZCNodePointN& rhs) const
{ return ml_CurrPos > rhs.ml_CurrPos; }
bool operator >= (const ZCNodePointN& rhs) const
{ return ml_CurrPos >= rhs.ml_CurrPos; }
bool operator < (const ZCNodePointN& rhs) const
{ return ml_CurrPos < rhs.ml_CurrPos; }
bool operator <= (const ZCNodePointN& rhs) const
{ return ml_CurrPos <= rhs.ml_CurrPos; }
bool operator == (TypeSize AL_Size) const
{ return ml_CurrPos == AL_Size; }
bool operator != (TypeSize AL_Size) const
{ return ml_CurrPos != AL_Size; }
bool operator > (TypeSize AL_Size) const
{ return ml_CurrPos > AL_Size; }
bool operator >= (TypeSize AL_Size) const
{ return ml_CurrPos >= AL_Size; }
bool operator < (TypeSize AL_Size) const
{ return ml_CurrPos < AL_Size; }
bool operator <= (TypeSize AL_Size) const
{ return ml_CurrPos <= AL_Size; }
const ZCNodePointN& operator++() const
{
mp_CurrLink = mp_CurrLink->mp_NextLink;
++ml_CurrPos; return *this ;
}/*
const ZCNodePointN& operator++() const*/
const ZCNodePointN& operator--() const
{
mp_CurrLink = mp_CurrLink->mp_PrevLink;
--ml_CurrPos; return *this ;
}/*
const ZCNodePointN& operator--() const*/
ZCNodePointN operator++(int) const
{
ZCNodePointN VO_NowPoint(*this);
mp_CurrLink = mp_CurrLink->mp_NextLink;
++ml_CurrPos ; return VO_NowPoint ;
}/*
ZCNodePointN operator++(int) const*/
ZCNodePointN operator--(int) const
{
ZCNodePointN VO_NowPoint(*this);
mp_CurrLink = mp_CurrLink->mp_PrevLink;
--ml_CurrPos; return VO_NowPoint ;
}/*
ZCNodePointN operator--(int) const*/
const ZCNodePointN& operator+=(TypeSize AL_Distance) const
{
if(IsEmpty()){return *this;}
mp_CurrLink = &((*mp_CurrLink)+AL_Distance) ;
ml_CurrPos += AL_Distance ;
return *this; /*:::::::::::::::::::::::::::*/
}/*
const ZCNodePointN& operator+=(TypeSize AL_Distance) const*/
const ZCNodePointN& operator-=(TypeSize AL_Distance) const
{
mp_CurrLink = &((*mp_CurrLink)-AL_Distance);
ml_CurrPos -= AL_Distance ;
return *this; /*::::::::::::::::::::::::::*/
}/*
const ZCNodePointN& operator-=(TypeSize AL_Distance) const*/
public:
};/*
class ZCNodePointN*/
class ZCLinkPointEx : public ZCNodePoint
{
public:
ZCLinkPointEx(TypeList& AR_TypeList): ZCNodePoint(AR_TypeList){}
ZCLinkPointEx(const ZCNodePoint & rhs): ZCNodePoint(rhs ){}
ZCLinkPointEx(const ZCLinkPointEx& rhs): ZCNodePoint(rhs ){}
public:
static ZCLinkPointEx MakeTailPoint(const ZCLinkPointEx& AR_TypeIter)
{
ZCLinkPointEx VO_ZCLinkPoint(AR_TypeIter);
if(!AR_TypeIter.IsEmpty()) /****************************/
{
VO_ZCLinkPoint.mp_CurrLink = VO_ZCLinkPoint.mr_TypeList.mp_TailLink;
VO_ZCLinkPoint.ml_CurrPos = VO_ZCLinkPoint.mr_TypeList.ml_LinkSize;
}
return VO_ZCLinkPoint; /********************************/
}/*
static ZCLinkPointEx MakeTailPoint(const ZCLinkPointEx& AR_TypeIter)*/
public:
ZCLinkPointEx& operator= (const ZCLinkPointEx& rhs){ return *this; }
const ZCLinkPointEx& operator++() const
{
if(this->IsEmpty()){return *this;}
this->mp_CurrLink = this->mp_CurrLink->mp_NextLink ;
if(++this->ml_CurrPos>this->mr_CurrList.size())
{ this->ml_CurrPos -= this->mr_CurrList.size(); }
return *this; /*******************************/
}/*
const ZCLinkPointEx& operator++() const*/
const ZCLinkPointEx& operator--() const
{
if(this->IsEmpty()){return *this;}
this->mp_CurrLink = this->mp_CurrLink->mp_PrevLink ;
if(--this->ml_CurrPos<1)
{ this->ml_CurrPos += this->mr_CurrList.size(); }
return *this; /********/
}/*
const ZCLinkPointEx& operator--() const*/
ZCLinkPointEx operator++(int) const
{
ZCLinkPointEx VO_NowPoint(*this);
if(this->IsEmpty()){return VO_NowPoint;}
this->mp_CurrLink = this->mp_CurrLink->mp_NextLink ;
if(++this->ml_CurrPos>this->mr_CurrList.size())
{ this->ml_CurrPos -= this->mr_CurrList.size(); }
return VO_NowPoint; /*************************/
}/*
ZCLinkPointEx operator++(int) const*/
ZCLinkPointEx operator--(int) const
{
ZCLinkPointEx VO_NowPoint(*this);
if(this->IsEmpty()){return VO_NowPoint;}
this->mp_CurrLink = this->mp_CurrLink->mp_PrevLink ;
if(--this->ml_CurrPos<1)
{ this->ml_CurrPos += this->mr_CurrList.size(); }
return VO_NowPoint;
}/*
ZCLinkPointEx operator--(int) const*/
const ZCLinkPointEx& operator+=(TypeSize AL_Distance) const
{
if(this->IsEmpty()){return *this;}
this->mp_CurrLink = &((*this->mp_CurrLink)+AL_Distance) ;
if(this->ml_CurrPos+=AL_Distance > this->mr_CurrList.size())
{ this->ml_CurrPos %= this->mr_CurrList.size(); }
else if(this->ml_CurrPos<1) // AL_Distance<0
{ while(this->ml_CurrPos+= this->mr_CurrList.size()<1){} }
return *this; /****************************/
}/*
const ZCLinkPointEx& operator+=(TypeSize AL_Distance) const*/
const ZCLinkPointEx& operator-=(TypeSize AL_Distance) const
{
if(this->IsEmpty()){return *this;}
this->mp_CurrLink = &((*this->mp_CurrLink)-AL_Distance);
if(this->ml_CurrPos-=AL_Distance > this->mr_CurrList.size())
{ this->ml_CurrPos %= this->mr_CurrList.size(); }
else if(this->ml_CurrPos<1) // AL_Distance>=0
{ while(this->ml_CurrPos+= this->mr_CurrList.size()<1){} }
return *this; /*****************************/
}/*
const ZCLinkPointEx& operator-=(TypeSize AL_Distance) const*/
public:
};/*
class ZCLinkPointEx*/
/*///////////////////////////////////////////////////////////////
■ class ZCLinkFake 는 가상의 맨 앞과 맨 뒤를 표시하는 링크로써,
연결리스트 내부에서 특정 링크를 어떤 기준 링크의 앞이나 뒤로
이동할 때,
이동 링크가 맨 앞에 있는지 맨 뒤에 있는지,
기준 링크가 맨 앞에 있는지 맨 뒤에 있는지,
등을 판단해서 처리할 때, ZCLinkFake 를 2개 만들어 가상으로
하나는 맨 앞 링크를, 또 하나는 맨 뒤 링크
를 표시하게 해서 처리를 단순하게 한다. 따라서, ZCLink 와 메모
리 구조가 최대한 같아야 한다. 그래서 ZCLink 와 같이 TypeAlloc
를 상속하고 있다.
MoveLinkIn() 에서 사용한다. -- 2025-10-15 23:44
///////////////////////////////////////////////////////////////*/
class ZCLinkFake : public TypeAlloc
{
public:
friend class ZtCBaseList;
private:
ZCLink* mp_NextLink;
ZCLink* mp_PrevLink;
public :
ZCLinkFake()
{
mp_NextLink = 0;
mp_PrevLink = 0;
}
public :
};/*
class ZCLinkFake : public TypeAlloc*/
public :
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
private :
ZCLink* mp_HeadLink ;
ZCLink* mp_TailLink ;
TypeSize ml_LinkSize ;
private :
TypeChild& GetChildObj()
{
return *static_cast<TypeChild*>(this);
}/*
TypeChild& GetChildObj()*/
const TypeChild& GetChildObj() const
{
return *static_cast<const TypeChild*>(this);
}/*
const TypeChild& GetChildObj() const*/
protected:
ZCLink* NewLink() const
{
return new ZCLink;
}/*
ZCLink* NewLink() const*/
ZCLink* NewLink(TypeArg AO_ArgData) const
{
return new ZCLink(AO_ArgData);
}/*
ZCLink* NewLink(TypeArg AO_ArgData) const*/
void NewLink ////////////////////////////////////////
(
TypeSize AL_NeedCnt ,
ZCLink*& APR_HeadLink ,
ZCLink*& APR_TailLink
) const
/////////////////////////////////////////////////////
{
APR_HeadLink = new ZCLink;
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = APR_HeadLink;
while(--AL_NeedCnt>0) // AL_NeedCnt - 1 번 순환
{
// AL_NeedCnt - 1 번 순환
VP_MakeLink = new ZCLink;
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink ;
}/*
while(--AL_NeedCnt>0)*/
APR_TailLink = VP_TailLink;
}/*
void NewLink ////////////////////////////////////////
(
TypeSize AL_NeedCnt ,
ZCLink*& APR_HeadLink ,
ZCLink*& APR_TailLink
) const
///////////////////////////////////////////////////*/
void NewLinkCopy //////////////////////////////////
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
/////////////////////////////////////////////////////
{
// 총 AL_FarNum+1 개의 링크가 만들어짊
ZCLink* VP_MakeLink = 0 ;
ZCLink* VP_TailLink = 0 ;
VP_TailLink = VP_MakeLink =
new ZCLink(**AP_LinkOrgin) ;
APR_HeadCopy = VP_MakeLink;
while(--AL_FarNum >= 0)
{
AP_LinkOrgin= AP_LinkOrgin->GetNextPtr();
VP_MakeLink = new ZCLink(**AP_LinkOrgin);
ZCLink::JoinLink
(VP_TailLink, VP_MakeLink);
VP_TailLink = VP_MakeLink;
}/*
while(--AL_FarNum >= 0)*/
APR_TailCopy=VP_TailLink;
}/*
void NewLinkCopy //////////////////////////////////
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
///////////////////////////////////////////////////*/
void DelLink(ZCLink* AP_DelLink)
{
delete AP_DelLink;
}/*
void DelLink(ZCLink* AP_DelLink)*/
void DelLink //////////////////////////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
///////////////////////////////////////////////////////
{
ZCLink* VP_DelLink = AP_CutHead;
__for0(TypeSize, i, AL_CutCnt)
{
AP_CutHead = AP_CutHead->GetNextPtr() ;
delete VP_DelLink; VP_DelLink=AP_CutHead;
}/*
__for0(TypeSize, i, AL_CutCnt)*/
}
///////////////////////////////////////////////////////
/*protected:*/
private :
_VT_ ZCLink* SendFreeOut() const
{
if(TTypeCRTP::ZEUseCRTP<1) return NewLink();
return GetChildObj().SendFreeOut();
}/*
_VT_ ZCLink* SendFreeOut() const*/
_VT_ void SendFreeOut
(TypeSize AL_NeedCnt, ZCLink*& APR_HeadLink, ZCLink*& APR_TailLink) const
{
if(TTypeCRTP::ZEUseCRTP<1)
{
NewLink(AL_NeedCnt, APR_HeadLink, APR_TailLink); return;
}/*
if(TTypeCRTP::ZEUseCRTP<1)*/
return GetChildObj().SendFreeOut
(AL_NeedCnt, RR(APR_HeadLink), RR(APR_TailLink));
}/*
_VT_ void SendFreeOut
(TypeSize AL_NeedCnt, ZCLink*& APR_HeadLink, ZCLink*& APR_TailLink) const
*/
_VT_ void SendFreeOutCopy /*///////////////////////*/
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
/////////////////////////////////////////////////////
{
// 총 AL_FarNum+1 개의 링크가 만들어짊
if(TTypeCRTP::ZEUseCRTP<1)
{
NewLinkCopy /*::::::::::::::::::*/
(
AP_LinkOrgin, AL_FarNum ,
APR_HeadCopy, APR_TailCopy
);
return; /*::::::::::::::::::*/
}/*
if(TTypeCRTP::ZEUseCRTP<1)*/
return GetChildObj().SendFreeOutCopy
(AP_LinkOrgin, AL_FarNum, RR(APR_HeadCopy), RR(APR_TailCopy));
}/*
_VT_ void SendFreeOutCopy ///////////////////////////
(
ZCLink* AP_LinkOrgin, TypeSize AL_FarNum ,
ZCLink*& APR_HeadCopy, ZCLink*& APR_TailCopy
) const
///////////////////////////////////////////////////*/
_VT_ void RecvFreeIn(ZCLink* AP_DelLink)
{
if(TTypeCRTP::ZEUseCRTP<1)
{ DelLink(AP_DelLink); return; }
GetChildObj().RecvFreeIn(AP_DelLink);
}/*
_VT_ void RecvFreeIn(ZCLink* AP_DelLink)*/
_VT_ void RecvFreeIn //////////////////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
///////////////////////////////////////////////////////
{
if(TTypeCRTP::ZEUseCRTP<1)
{
DelLink
(AL_CutCnt, AP_CutHead, AP_CutTail);
return;
}/*
if(TTypeCRTP::ZEUseCRTP<1)*/
GetChildObj().RecvFreeIn(AL_CutCnt, AP_CutHead, AP_CutTail);
}/*
_VT_ void RecvFreeIn //////////////////////////////////
(
TypeSize AL_CutCnt ,
ZCLink* AP_CutHead,
ZCLink* AP_CutTail
)
/////////////////////////////////////////////////////*/
/*private :*/
private :
ZCLink* AddTailLink(ZCLink* AP_NewLink)
{
if(ml_LinkSize<1)
{
mp_HeadLink = AP_NewLink;
mp_TailLink = AP_NewLink;
ZCLink::MakeRing
( mp_HeadLink, mp_TailLink ) ;
ml_LinkSize= 1; return AP_NewLink;
}/*
if(ml_LinkSize<1)*/
ZCLink::JoinLink(mp_TailLink, AP_NewLink) ;
ZCLink::MakeRing(mp_HeadLink, AP_NewLink) ;
mp_TailLink = AP_NewLink; ++ml_LinkSize ;
return AP_NewLink; /*::::::::::::::::::::*/
}/*
ZCLink* AddTailLink(ZCLink* AP_NewLink)*/
ZCLink* AddHeadLink(ZCLink* AP_NewLink)
{
if(ml_LinkSize<1)
{
mp_HeadLink = AP_NewLink;
mp_TailLink = AP_NewLink;
ZCLink::MakeRing
( mp_HeadLink, mp_TailLink ) ;
ml_LinkSize= 1; return AP_NewLink;
}/*
if(ml_LinkSize<1)*/
ZCLink::JoinLink(AP_NewLink, mp_HeadLink) ;
ZCLink::MakeRing(AP_NewLink, mp_TailLink) ;
mp_HeadLink = AP_NewLink; ++ml_LinkSize ;
return AP_NewLink; /*::::::::::::::::::::*/
}/*
ZCLink* AddHeadLink(ZCLink* AP_NewLink)*/
ZCLink* AddLinkAfter(ZCLink* AP_StdLink, ZCLink* AP_NewLink)
{
// *this 에 속한 AP_StdLink 의 뒤에, AP_NewLink 를 삽입한다.
// AP_StdLink 이 0 이면, 맨 앞에 삽입한다.
if(AP_StdLink==0) // 맨 앞에 삽입
{
if(ml_LinkSize<1)
{
mp_HeadLink = AP_NewLink;
mp_TailLink = AP_NewLink;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}
else
{
ZCLink::JoinLink(AP_NewLink, mp_HeadLink) ;
ZCLink::MakeRing(AP_NewLink, mp_TailLink) ;
mp_HeadLink = AP_NewLink;
}
}
else if(AP_StdLink==mp_TailLink)
{
ZCLink::JoinLink(mp_TailLink, AP_NewLink) ;
ZCLink::MakeRing(mp_HeadLink, AP_NewLink) ;
mp_TailLink = AP_NewLink;
}
else
{
ZCLink* VP_StdNext = AP_StdLink->mp_NextLink ;
ZCLink::JoinLink(AP_StdLink, AP_NewLink) ;
ZCLink::JoinLink(AP_NewLink, VP_StdNext) ;
}
++ml_LinkSize; return AP_NewLink;
}/*
ZCLink* AddLinkAfter(ZCLink* AP_StdLink, ZCLink* AP_NewLink)*/
ZCLink* AddLinkBefore(ZCLink* AP_StdLink, ZCLink* AP_NewLink)
{
// *this 에 속한 AP_StdLink 의 앞에, AP_NewLink 를 삽입한다.
// AP_StdLink 이 0 이면, 맨 뒤에 삽입한다.
if(AP_StdLink==0) // 맨 뒤에 삽입
{
if(ml_LinkSize<1)
{
mp_HeadLink = AP_NewLink;
mp_TailLink = AP_NewLink;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}
else
{
ZCLink::JoinLink(mp_TailLink, AP_NewLink) ;
ZCLink::MakeRing(mp_HeadLink, AP_NewLink) ;
mp_TailLink = AP_NewLink;
}
}
else if(AP_StdLink==mp_HeadLink)
{
ZCLink::JoinLink(AP_NewLink, mp_HeadLink) ;
ZCLink::MakeRing(AP_NewLink, mp_TailLink) ;
mp_HeadLink = AP_NewLink;
}
else
{
ZCLink* VP_StdPrev = AP_StdLink->mp_PrevLink ;
ZCLink::JoinLink(VP_StdPrev, AP_NewLink) ;
ZCLink::JoinLink(AP_NewLink, AP_StdLink) ;
}
++ml_LinkSize; return AP_NewLink;
}/*
ZCLink* AddLinkBefore(ZCLink* AP_StdLink, ZCLink* AP_NewLink)*/
ZCLink* CutLink(ZCLink* AP_StdLink)
{
if(mp_HeadLink==AP_StdLink)
{
if(ml_LinkSize==1)
{
mp_HeadLink = 0;
mp_TailLink = 0;
}
else // ml_LinkSize>1
{
mp_HeadLink = mp_HeadLink->mp_NextLink ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
else*/
}
else if(mp_TailLink==AP_StdLink)
{
mp_TailLink = mp_TailLink->mp_PrevLink ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}
else
{
ZCLink::JoinLink
(
AP_StdLink->mp_PrevLink, AP_StdLink->mp_NextLink
) ;
////////////////
}/*
else*/
--ml_LinkSize ; return AP_StdLink;
}/*
ZCLink* CutLink(ZCLink* AP_StdLink)*/
ZtCBaseList& CutLinkRangeOut /*///////////////////////////////////////*/
(
ZCLink& AR_CutHead ,
ZCLink& AR_CutTail ,
TypeSize AL_CutSize ,
ZtCBaseList& rhs ,
ZCLink* AP_RhsStd ,
bool AB_After=true
)
/*#####################################################################*/
{
/*///////////////////////////////////////////////////////////
■ AR_CutHead 는 삭제하려는 링크의 범위의 앞의 링크.
AR_CutTail 은 삭제하려는 링크의 범위의 뒤의 링크.
AR_CutHead 의 앞과 AR_CutTail 의 뒤에서 연결 상태를 끊고,
rhs 의 AP_RhsStd 의 뒤에 삽입한다.
AP_RhsStd==0 이면 맨 앞에 삽입한다. -- 2025-10-06 09:16
■ bool AB_After=true 추가.
AB_After==true 이면, rhs 의 AP_RhsStd 의 뒤에 삽입한다.
AB_After==false 이면, rhs 의 AP_RhsStd 의 앞에 삽입한다.
AB_After==true && AP_RhsStd==0 이면 맨 앞에 삽입한다.
AB_After==false && AP_RhsStd==0 이면 맨 뒤에 삽입한다.
-- 2025-10-07 08:36
///////////////////////////////////////////////////////////*/
if(this==&rhs ) return rhs;
if(ml_LinkSize<1) return rhs;
if(AL_CutSize>=ml_LinkSize) // 모든 링크를 삭제할 때.
{
mp_HeadLink=0;
}
else if(&AR_CutHead==mp_HeadLink)
{
ZCLink::MakeRing
( mp_HeadLink=AR_CutTail.mp_NextLink, mp_TailLink );
}
else if(&AR_CutTail==mp_TailLink)
{
ZCLink::MakeRing
( mp_HeadLink, mp_TailLink=AR_CutHead.mp_PrevLink );
}
else
{
ZCLink::JoinLink
( AR_CutHead.mp_PrevLink, AR_CutTail.mp_NextLink );
}/*
else*/
ml_LinkSize -= AL_CutSize;
if(rhs.size()<1)
{
// AP_CutHead 과 AP_CutTail 을 연결하여 이중 원형 연결리스트가 되도록 한다.
ZCLink::MakeRing(&AR_CutHead, &AR_CutTail);
rhs.mp_HeadLink = &AR_CutHead ;
rhs.mp_TailLink = &AR_CutTail ;
}
else if(AB_After)
{
if(AP_RhsStd==0) // 맨 앞에 삽입.
{
ZCLink::JoinLink(&AR_CutTail, rhs.mp_HeadLink);
ZCLink::MakeRing(&AR_CutHead, rhs.mp_TailLink);
rhs.mp_HeadLink = &AR_CutHead;
}
else // AP_RhsStd 의 뒤에 삽입.
{
ZCLink* VP_RhsStdNext = AP_RhsStd->mp_NextLink ;
ZCLink::JoinLink(AP_RhsStd , &AR_CutHead );
ZCLink::JoinLink(&AR_CutTail, VP_RhsStdNext);
if(AP_RhsStd==rhs.mp_TailLink)
{ rhs.mp_TailLink = &AR_CutTail; }
}
}
else // !AB_After
{
if(AP_RhsStd==0) // 맨 뒤에 삽입.
{
ZCLink::JoinLink(rhs.mp_TailLink, &AR_CutHead);
ZCLink::MakeRing(rhs.mp_HeadLink, &AR_CutTail);
rhs.mp_TailLink = &AR_CutTail;
}
else // AP_RhsStd 의 앞에 삽입.
{
ZCLink* VP_RhsStdPrev = AP_RhsStd->mp_PrevLink ;
ZCLink::JoinLink(VP_RhsStdPrev, &AR_CutHead);
ZCLink::JoinLink(&AR_CutTail , AP_RhsStd );
if(AP_RhsStd==rhs.mp_HeadLink)
{ rhs.mp_HeadLink = &AR_CutHead; }
}
}/*
else // !AB_After*/
rhs.ml_LinkSize += AL_CutSize; return rhs;
}/*
ZtCBaseList& CutLinkRangeOut ///////////////////////////////////////////
(
ZCLink& AR_CutHead ,
ZCLink& AR_CutTail ,
TypeSize AL_CutSize ,
ZtCBaseList& rhs ,
ZCLink* AP_RhsStd ,
bool AB_After=true
)
#######################################################################*/
TypeThis& CutLinkRangeIn ///////////////////////////////////////////////
(
ZCLink& AR_CutHead ,
ZCLink& AR_CutTail ,
TypeSize AL_CutSize ,
ZCLink* AP_NowStd ,
bool AB_After=true
)
/*#####################################################################*/
{
/*///////////////////////////////////////////////////////////
■ AR_CutHead 는 삭제하려는 링크의 범위의 앞의 링크.
AR_CutTail 은 삭제하려는 링크의 범위의 뒤의 링크.
AR_CutHead 의 앞과 AR_CutTail 의 뒤에서 연결 상태를 끊고,
AB_After==true 이면, rhs 의 AP_NowStd 의 뒤에
AB_After==false 이면, rhs 의 AP_NowStd 의 앞에
연결한다.
AB_After==true && AP_NowStd==0 이면 맨 앞에
AB_After==false && AP_NowStd==0 이면 맨 뒤에
연결한다. -- 2025-10-12 08:19
///////////////////////////////////////////////////////////*/
if(ml_LinkSize<1){return *this;}
if(AL_CutSize>=ml_LinkSize){return *this;}
if(&AR_CutHead==mp_HeadLink && &AR_CutTail==mp_TailLink)
{ return *this; }
if(&AR_CutHead==AP_NowStd || &AR_CutTail==AP_NowStd )
{ return *this; }
/******************************************************/
if (AB_After && AP_NowStd==0) // 맨 앞에 삽입.
{
if(&AR_CutHead==mp_HeadLink)
{ /* nothing to do.*/ }
else if(mp_HeadLink->mp_NextLink==&AR_CutHead)
{
// mp_HeadLink - &AR_CutHead ~ &AR_CutTail
if(&AR_CutTail==mp_TailLink)
{
// 현재 : mp_HeadLink - &AR_CutHead ~ &AR_CutTail(=mp_TailLink)
// 이후 : &AR_CutHead ~ &AR_CutTail - mp_HeadLink
ZCLink::JoinLink(&AR_CutTail, mp_HeadLink);
ZCLink::MakeRing(&AR_CutHead, mp_HeadLink);
mp_TailLink = mp_HeadLink ;
mp_HeadLink = &AR_CutHead ;
}
else
{
// 현재 : mp_HeadLink - &AR_CutHead ~ &AR_CutTail - VP_CutNext
// 이후 : &AR_CutHead ~ &AR_CutTail - mp_HeadLink - VP_CutNext
ZCLink* VP_CutNext = AR_CutTail.mp_NextLink ;
ZCLink::JoinLink(&AR_CutTail, mp_HeadLink);
ZCLink::JoinLink(mp_HeadLink, VP_CutNext );
ZCLink::MakeRing(&AR_CutHead, mp_TailLink);
mp_HeadLink = &AR_CutHead ;
}
}/*
else if(mp_HeadLink->mp_NextLink==&AR_CutHead)*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mp_HeadLink ~ &AR_CutHead ~ &AR_CutTail
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
else
{
if(&AR_CutTail==mp_TailLink)
{
/*////////////////////////////////////////////
■ 현재 :
mp_HeadLink ~ VP_CutPrev -
&AR_CutHead - &AR_CutTail(mp_TailLink)
이후 :
&AR_CutHead - &AR_CutTail -
mp_HeadLink ~ VP_CutPrev
////////////////////////////////////////////*/
ZCLink* VP_CutPrev = AR_CutHead.mp_PrevLink ;
ZCLink::JoinLink(&AR_CutTail, mp_HeadLink);
ZCLink::MakeRing(&AR_CutHead, VP_CutPrev );
mp_HeadLink = &AR_CutHead ;
mp_TailLink = VP_CutPrev ;
}/*
if(&AR_CutTail==mp_TailLink)*/
else /*************************************************/
{
/*////////////////////////////////////////////
■ 현재 :
mp_HeadLink ~ VP_CutPrev -
&AR_CutHead - &AR_CutTail - VP_CutNext
이후 :
&AR_CutHead - &AR_CutTail -
mp_HeadLink ~ VP_CutPrev - VP_CutNext
////////////////////////////////////////////*/
ZCLink* VP_CutNext = AR_CutTail.mp_NextLink ;
ZCLink* VP_CutPrev = AR_CutHead.mp_PrevLink ;
ZCLink::JoinLink(&AR_CutTail, mp_HeadLink);
ZCLink::JoinLink(&VP_CutPrev, VP_CutNext );
ZCLink::MakeRing(&AR_CutHead, mp_TailLink);
mp_HeadLink = &AR_CutHead ;
}/*
else **************************************************/
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
mp_HeadLink ~ &AR_CutHead ~ &AR_CutTail
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
}/*
if (AB_After && AP_NowStd==0) // 맨 앞에 삽입.*/
else if(!AB_After && AP_NowStd==0) // 맨 뒤에 삽입.
{
if(&AR_CutTail==mp_TailLink)
{ /* nothing to do.*/ }
else if(mp_TailLink->mp_PrevLink==&AR_CutTail)
{
// &AR_CutHead ~ &AR_CutTail - mp_TailLink
if(&AR_CutHead==mp_HeadLink)
{
// 현재 : &AR_CutHead(=mp_HeadLink) ~ &AR_CutTail - mp_TailLink
// 이후 : mp_TailLink - &AR_CutHead ~ &AR_CutTail
ZCLink::JoinLink(mp_TailLink, &AR_CutHead);
ZCLink::MakeRing(mp_TailLink, &AR_CutTail);
mp_HeadLink = mp_TailLink ;
mp_TailLink = &AR_CutTail ;
}
else
{
// 현재 : VP_CutPrev - &AR_CutHead ~ &AR_CutTail - mp_TailLink
// 이후 : VP_CutPrev - mp_TailLink - &AR_CutHead ~ &AR_CutTail
ZCLink* VP_CutPrev = AR_CutHead.mp_PrevLink ;
ZCLink::JoinLink(VP_CutPrev, mp_TailLink);
ZCLink::JoinLink(mp_TailLink, &AR_CutHead);
ZCLink::MakeRing(mp_HeadLink, &AR_CutTail);
mp_TailLink = &AR_CutTail ;
}
}/*
else if(mp_TailLink->mp_PrevLink==&AR_CutTail)*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
&AR_CutHead ~ &AR_CutTail ~ mp_TailLink
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
else
{
if(&AR_CutHead==mp_HeadLink)
{
/*////////////////////////////////////////////
■ 현재 :
(mp_HeadLink=)
&AR_CutHead ~ &AR_CutTail - VP_CutNext ~ mp_TailLink
이후 :
VP_CutNext ~ mp_TailLink - &AR_CutHead ~ &AR_CutTail
////////////////////////////////////////////*/
ZCLink* VP_CutNext = AR_CutTail.mp_NextLink ;
ZCLink::JoinLink(mp_TailLink, &AR_CutHead);
ZCLink::MakeRing(VP_CutNext , &AR_CutTail);
mp_HeadLink = VP_CutNext ;
mp_TailLink = &AR_CutTail ;
}/*
if(&AR_CutHead==mp_HeadlLink)*/
else /*************************************************/
{
/*////////////////////////////////////////////
■ 현재 :
VP_CutPrev - &AR_CutHead ~
&AR_CutTail - VP_CutNext ~ mp_TailLink
이후 :
&VP_CutPrev - VP_CutNext ~
mp_TailLink - &AR_CutHead ~ &AR_CutTail
////////////////////////////////////////////*/
ZCLink* VP_CutNext = AR_CutTail.mp_NextLink ;
ZCLink* VP_CutPrev = AR_CutHead.mp_PrevLink ;
ZCLink::JoinLink(&VP_CutPrev, VP_CutNext );
ZCLink::JoinLink(mp_TailLink, &AR_CutHead);
ZCLink::MakeRing(&AR_CutHead, &AR_CutTail);
mp_TailLink = &AR_CutTail ;
}/*
else **************************************************/
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
&AR_CutHead ~ &AR_CutTail ~ mp_TailLink
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
}/*
else if(!AB_After && AP_NowStd==0) // 맨 뒤에 삽입.*/
/*=================================================================
AP_NowStd!=0 : AP_NowStd 의 앞이나 뒤에 삽입.
=================================================================*/
else if(AR_CutTail.mp_NextLink==AP_NowStd)
{
// &AR_CutHead ~ &AR_CutTail - AP_NowStd
if(!AB_After)
{ /* nothing to do*/ }
else if(&AR_CutHead==mp_HeadLink)
{
/*************************************************************
■ mp_HeadLink==&AR_CutHead && mp_TailLink!=mp_TailLink
현재 : &AR_CutHead ~ &AR_CutTail - AP_NowStd - VP_StdNext ~ mp_TailLink
이후 : AP_NowStd - &AR_CutHead ~ &AR_CutTail- VP_StdNext ~ mp_TailLink
*************************************************************/
ZCLink* VP_StdNext = AP_NowStd->mp_NextLink;
ZCLink::JoinLink(AP_NowStd , &AR_CutHead );
ZCLink::JoinLink(&AR_CutTail, VP_StdNext );
ZCLink::MakeRing(AP_NowStd , mp_TailLink);
mp_HeadLink = AP_NowStd ;
}/*
else if(&AR_CutHead==mp_HeadLink)*/
else if(&AR_CutTail==mp_TailLink)
{ /* nothing to do */ }
/*******************************/
else
{
/*************************************************************
■ mp_HeadLink!=&AR_CutHead && mp_TailLink!=&AR_CutTail
현재 : VP_CutPrev - &AR_CutHead ~ &AR_CutTail - AP_NowStd - VP_StdNext
이후 : VP_CutPrev - AP_NowStd - &AR_CutHead ~ &AR_CutTail- VP_StdNext
*************************************************************/
ZCLink* VP_CutPrev = AR_CutHead.mp_PrevLink;
ZCLink* VP_StdNext = AP_NowStd->mp_NextLink;
ZCLink::JoinLink(VP_CutPrev , AP_NowStd );
ZCLink::JoinLink(AP_NowStd , &AR_CutHead);
ZCLink::JoinLink(&AR_CutTail, VP_StdNext );
}
}/*
else if(AR_CutTail.mp_NextLink==AP_NowStd)*/
else if(AR_CutHead.mp_PrevLink==AP_NowStd)
{
// AP_NowStd - &AR_CutHead ~ &AR_CutTail
if(AB_After)
{ /* nothing to do*/ }
else if(&AR_CutTail==mp_TailLink)
{
if(AP_NowStd==mp_HeadLink)
{
/*************************************************************
■ AP_NowStd==mp_HeadLink && &AR_CutTail==mp_TailLink
현재 : AP_NowStd - &AR_CutHead ~ &AR_CutTail
이후 : &AR_CutHead ~ &AR_CutTail - AP_NowStd
*************************************************************/
ZCLink::JoinLink(&AR_CutTail, AP_NowStd);
ZCLink::MakeRing(&AR_CutHead, AP_NowStd);
mp_HeadLink = &AR_CutHead;
mp_TailLink = AP_NowStd ;
}
else
{
/*************************************************************
■ &AR_CutTail==mp_TailLink
현재 : VP_StdPrev - AP_NowStd - &AR_CutHead ~ &AR_CutTail
이후 : VP_StdPrev - &AR_CutHead ~ &AR_CutTail - AP_NowStd
*************************************************************/
ZCLink* VP_StdPrev = AP_NowStd->mp_PrevLink ;
ZCLink::JoinLink(VP_StdPrev , &AR_CutHead);
ZCLink::JoinLink(&AR_CutTail, AP_NowStd );
ZCLink::MakeRing(mp_HeadLink, AP_NowStd );
mp_TailLink = AP_NowStd ;
}
}/*
else if(&AR_CutHead==mp_HeadLink)*/
// add codes
}/*
else if(AR_CutTail.mp_NextLink==AP_NowStd)*/
/*=================================================================
AP_RhsStd!=0 : AP_RhsStd 의 앞이나 뒤에 삽입.
=================================================================*/
// add codes
return *this;
}/*
TypeThis& CutLinkRangeIn ///////////////////////////////////////////////
(
ZCLink& AR_CutHead ,
ZCLink& AR_CutTail ,
TypeSize AL_CutSize ,
ZCLink* AP_RhsStd ,
bool AB_After=true
)
#######################################################################*/
private :
/***************************************************************************/
public :
ZtCBaseList()
{
mp_HeadLink = 0 ;
mp_TailLink = 0 ;
ml_LinkSize = 0 ;
}/*
ZtCBaseList()*/
ZtCBaseList(const ZtCBaseList& rhs)
{
mp_HeadLink = 0 ;
mp_TailLink = 0 ;
ml_LinkSize = 0 ;
*this = (rhs);
}/*
ZtCBaseList(const ZtCBaseList& rhs)*/
~ZtCBaseList()
{
DeleteAll();
}/*
~ZtCBaseList()*/
ZtCBaseList& operator=(const ZtCBaseList& rhs)
{
if(this==&rhs) return *this;
if(rhs.size()<1)
{ this->DeleteAll(); return *this; }
TypeSize VL_MinusSize = this->size() - rhs.size() ;
if (VL_MinusSize>0)
{
ZCLink* VP_CutTail =
mp_HeadLink->GetNextPrevPtr(VL_MinusSize-1);
ZCLink* VP_CutTailNext = VP_CutTail->mp_NextLink ;
RecvFreeIn ////////////////////////////////////////
(
VL_MinusSize, mp_HeadLink, VP_CutTail
);
///////////////////////////////////////////////////
mp_HeadLink = VP_CutTailNext;
ml_LinkSize -= VL_MinusSize ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}
else if(VL_MinusSize<0)
{
ZCLink* VP_HeadLink=0;
ZCLink* VP_TailLink=0;
SendFreeOut ///////////////////////////////////////
(
-VL_MinusSize ,
RR(VP_HeadLink) ,
RR(VP_TailLink)
);
///////////////////////////////////////////////////
if(ml_LinkSize>0)
{
ZCLink::JoinLink(mp_TailLink, VP_HeadLink);
ZCLink::MakeRing(mp_HeadLink, VP_TailLink);
mp_TailLink = VP_TailLink ;
}
else
{
mp_HeadLink = VP_HeadLink ;
mp_TailLink = VP_TailLink ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
else*/
ml_LinkSize += (-VL_MinusSize);
}/*
else if(VL_MinusSize<0)*/
ZCLink* VP_RhsLink = rhs.mp_HeadLink ;
ZCLink* VP_LhsLink = mp_HeadLink ;
__for0(TypeSize, i, rhs.size())
{
**VP_LhsLink = **VP_RhsLink ;
VP_RhsLink = VP_RhsLink->mp_NextLink;
VP_LhsLink = VP_LhsLink->mp_NextLink;
}/*
__for0(TypeSize, i, rhs.size())*/
return *this;
}/*
ZtCBaseList& operator=(const ZtCBaseList& rhs)*/
void DeleteAll()
{
if(ml_LinkSize<1) return;
RecvFreeIn
(ml_LinkSize, mp_HeadLink, mp_TailLink);
mp_HeadLink =0 ;
mp_TailLink =0 ;
ml_LinkSize =0 ;
}/*
void DeleteAll()*/
TypeData& AddHead()
{ return **AddHeadLink(SendFreeOut()); }
TypeData& AddTail()
{ return **AddTailLink(SendFreeOut()); }
ZCLink& AddHeadDef()
{ return *AddHeadLink(SendFreeOut()); }
ZCLink& AddTailDef()
{ return *AddTailLink(SendFreeOut()); }
TypeData& AddHead(TypeArg AO_ArgData) /*########################*/
{
#if(_CODE_NEW_)
if(TypeMoveObj::ZEUseMoveObj>0) ////////////////////
{
ZCLink* VP_NewNode = SendFreeOut();
TypeMoveObj::Exec(**VP_NewNode, AO_ArgData);
return AddHeadLink(VP_NewNode)->mo_DataObjt;
}
////////////////////////////////////////////////////
#endif
return AddHeadLink(new ZCLink(AO_ArgData))->mo_DataObjt;
}/*
TypeData& AddHead(TypeArg AO_ArgData) ##########################*/
TypeData& AddTail(TypeArg AO_ArgData) /*########################*/
{
#if(_CODE_NEW_)
if(TypeMoveObj::ZEUseMoveObj>0) ////////////////////
{
ZCLink* VP_NewNode = SendFreeOut();
TypeMoveObj::Exec(*VP_NewNode, AO_ArgData);
return AddTailLink(VP_NewNode)->mo_DataObjt;
}
////////////////////////////////////////////////////
#endif
return AddTailLink(new ZCLink(AO_ArgData))->mo_DataObjt;
}/*
TypeData& AddTail(TypeArg AO_ArgData) ##########################*/
ZtCBaseList& AddHead(ZtCBaseList& rhs)
{
if(this == &rhs ) return *this;
if(rhs.size()<1 ) return *this;
ZtCBaseList VO_TempList(rhs);
return JoinHead(VO_TempList);
}/*
ZtCBaseList& AddHead(ZtCBaseList& rhs)*/
ZtCBaseList& AddTail(ZtCBaseList& rhs)
{
if(this == &rhs ) return *this;
if(rhs.size()<1 ) return *this;
ZtCBaseList VO_TempList(rhs);
return JoinTail(VO_TempList);
}/*
ZtCBaseList& AddTail(ZtCBaseList& rhs)*/
void DeleteHead()
{
if(ml_LinkSize<1) return;
ZCLink* VP_TempLink = mp_HeadLink ;
mp_HeadLink = mp_HeadLink->mp_NextLink ;
RecvFreeIn(VP_TempLink);
if(--ml_LinkSize<1)
{
mp_HeadLink = mp_TailLink =0; return;
}/*
if(--ml_LinkSize<1)*/
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
void DeleteHead()*/
void DeleteTail()
{
if(ml_LinkSize<1) return;
ZCLink* VP_TempLink = mp_TailLink ;
mp_TailLink = mp_TailLink->mp_PrevLink ;
RecvFreeIn(VP_TempLink);
if(--ml_LinkSize<1)
{
mp_HeadLink = mp_TailLink =0; return;
}/*
if(--ml_LinkSize<1)*/
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
void DeleteTail()*/
void DeleteHead(TTypSize AL_DelSize)
{
// AL_DelSize 개의 링크를 앞 부분에서 삭제
if(ml_LinkSize<1 || AL_DelSize<1){ return; }
if(AL_DelSize > ml_LinkSize)
{ AL_DelSize = ml_LinkSize; }
if(AL_DelSize== ml_LinkSize)
{
RecvFreeIn
(ml_LinkSize, mp_HeadLink, mp_TailLink);
mp_HeadLink=0 ;
mp_TailLink=0 ;
ml_LinkSize=0 ;
return;
}/*
if(AL_DelSize==ml_LinkSize)*/
ZCLink* VP_NewHead =
mp_HeadLink->GetNextPrevPtr( AL_DelSize ) ;
RecvFreeIn
(AL_DelSize, mp_HeadLink, VP_NewHead->mp_PrevLink);
mp_HeadLink = VP_NewHead ;
ml_LinkSize -= AL_DelSize ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
void DeleteHead(TTypSize AL_DelSize)*/
void DeleteTail(TTypSize AL_DelSize)
{
if(ml_LinkSize==0 || AL_DelSize<1){ return; }
if(AL_DelSize> ml_LinkSize){ AL_DelSize=ml_LinkSize; }
if(AL_DelSize==ml_LinkSize)
{
RecvFreeIn
(ml_LinkSize, mp_HeadLink, mp_TailLink);
mp_HeadLink=0 ;
mp_TailLink=0 ;
ml_LinkSize=0 ;
return;
}/*
if(AL_DelSize==ml_LinkSize)*/
ZCLink* VP_NewTail =
mp_TailLink->GetNextPrevPtr( -AL_DelSize ) ;
RecvFreeIn
(AL_DelSize, VP_NewTail->mp_NextLink, mp_TailLink);
mp_TailLink = VP_NewTail ;
ml_LinkSize -= AL_DelSize ;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
}/*
void DeleteTail(TTypSize AL_DelSize)*/
ZtCBaseList& JoinAfter(TypeThis& rhs, ZCLinkOpt AO_StdOpt)
{
// AP_StdLink 의 뒤에 rhs 를 삽입.
if(rhs.ml_LinkSize<1) return *this;
ZCLink* VP_StdLink = AO_StdOpt.Raw();
if(VP_StdLink==0) // 맨 앞에 삽입
{
if(ml_LinkSize<1)
{
mp_HeadLink = rhs.mp_HeadLink ;
mp_TailLink = rhs.mp_TailLink ;
}
else // ml_LinkSize>=1
{
ZCLink::JoinLink( rhs.mp_TailLink, mp_HeadLink );
ZCLink::MakeRing( rhs.mp_HeadLink, mp_TailLink );
mp_HeadLink = rhs.mp_HeadLink ;
}/*
else // ml_LinkSize>=1*/
ml_LinkSize += rhs.ml_LinkSize;
rhs.mp_HeadLink = 0 ;
rhs.mp_TailLink = 0 ;
rhs.ml_LinkSize = 0 ;
return *this; /////////////////
}/*
if(VP_StdLink==0)*/
ZCLink* VP_StdNext=VP_StdLink->mp_NextLink;
ZCLink::JoinLink(VP_StdLink , rhs.mp_HeadLink );
ZCLink::JoinLink(rhs.mp_TailLink, VP_StdNext );
if(VP_StdLink==mp_TailLink)
{ mp_TailLink=rhs.mp_TailLink; }
ml_LinkSize += rhs.ml_LinkSize;
rhs.mp_HeadLink =0 ;
rhs.mp_TailLink =0 ;
rhs.ml_LinkSize =0 ;
return *this; /*:::::::::::::*/
}/*
ZtCBaseList& JoinAfter(TypeThis& rhs, ZCLinkOpt AO_StdOpt)*/
ZtCBaseList& JoinBefore(TypeThis& rhs, ZCLinkOpt AO_StdOpt)
{
// AO_StdOpt 의 앞에 rhs 를 삽입.
if(rhs.size()<1) return *this;
ZCLink* VP_StdLink = AO_StdOpt.Raw();
if(VP_StdLink==0) // 맨 뒤에 삽입
{
if(ml_LinkSize<1)
{
mp_HeadLink = rhs.mp_HeadLink ;
mp_TailLink = rhs.mp_TailLink ;
}
else // ml_LinkSize>=1
{
ZCLink::JoinLink(mp_TailLink, rhs.mp_HeadLink );
ZCLink::MakeRing(mp_HeadLink, rhs.mp_TailLink );
mp_TailLink = rhs.mp_TailLink ;
}/*
else // ml_LinkSize>=1*/
ml_LinkSize += rhs.ml_LinkSize;
rhs.mp_HeadLink = 0 ;
rhs.mp_TailLink = 0 ;
rhs.ml_LinkSize = 0 ;
return *this; /////////////////
}/*
if(VP_StdLink==0)*/
ZCLink* VP_StdPrev = VP_StdLink->mp_PrevLink;
ZCLink::JoinLink( VP_StdPrev , rhs.mp_HeadLink );
ZCLink::JoinLink(rhs.mp_TailLink, VP_StdLink );
if(VP_StdLink==mp_HeadLink)
{ mp_HeadLink = rhs.mp_HeadLink; }
ml_LinkSize += rhs.ml_LinkSize;
rhs.mp_HeadLink =0 ;
rhs.mp_TailLink =0 ;
rhs.ml_LinkSize =0 ;
return *this; /*:::::::::::::*/
}/*
ZtCBaseList& JoinBefore(TypeThis& rhs, ZCLinkOpt AO_StdOpt)*/
ZtCBaseList& JoinHead(TypeThis& rhs)
{ if(this==&rhs) return *this; return JoinAfter (rhs, ZCLinkOpt(0)); }
ZtCBaseList& JoinTail(TypeThis& rhs)
{ if(this==&rhs) return *this; return JoinBefore(rhs, ZCLinkOpt(0)); }
void SendOutAfter (ZCLink& AR_CutLink, TypeThis& rhs, ZCLinkOpt AO_StdOpt)
{
// AP_CutLink 를 잘라서 rhs 의 AP_StdLink 뒤에 연결한다.
CutLink(&AR_CutLink); rhs.AddLinkAfter(AO_StdOpt.Raw(), &AR_CutLink);
}/*
void SendOutAfter (ZCLink& AR_CutLink, TypeThis& rhs, ZCLinkOpt AO_StdOpt)*/
void SendOutBefore(ZCLink& AR_CutLink, TypeThis& rhs, ZCLinkOpt AO_StdOpt)
{
// AP_CutLink 를 잘라서 rhs 의 AP_StdLink 앞에 연결한다.
CutLink(&AR_CutLink); rhs.AddLinkBefore(AO_StdOpt.Raw(), &AR_CutLink);
}/*
void SendOutBefore(ZCLink& AR_CutLink, TypeThis& rhs, ZCLinkOpt AO_StdOpt)*/
ZtCBaseList& SwapLinkNext(ZCLink& AR_LinkPrev)
{
// 다음 링크와 위치를 맞바꾼다.
if(size()<=1){return *this;}
ZCLink* VP_LinkNext = AR_LinkPrev.mp_NextLink;
if(&AR_LinkPrev == VP_LinkNext){ return *this; }
if(size()==2)
{
if(&AR_LinkPrev==mp_HeadLink) /*************************/
{
// VP_LinkNext==mp_TailLink
mp_HeadLink = VP_LinkNext ;
mp_TailLink = &AR_LinkPrev;
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::*/
else // VP_LinkNext==mp_HeadLink
{
mp_HeadLink = &AR_LinkPrev ;
mp_TailLink = VP_LinkNext ;
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::*/
}
else if(&AR_LinkPrev==mp_HeadLink)
{
// VP_LinkNext == mp_HeadLink.mp_NextLink;
ZCLink* VP_HeadNext2 =
VP_LinkNext->mp_NextLink ;
ZCLink::JoinLink(VP_LinkNext , &AR_LinkPrev);
ZCLink::JoinLink(&AR_LinkPrev, VP_HeadNext2);
ZCLink::MakeRing(VP_LinkNext , mp_TailLink );
mp_HeadLink = VP_LinkNext ;
}
else if(&AR_LinkPrev==mp_TailLink)
{
// VP_LinkNext==mp_HeadLink
ZCLink* VP_HeadNext =
mp_HeadLink->mp_NextLink ;
ZCLink* VP_TailPrev =
mp_TailLink->mp_PrevLink ;
ZCLink::JoinLink(mp_TailLink, VP_HeadNext);
ZCLink::JoinLink(VP_TailPrev, mp_HeadLink);
ZCLink::MakeRing(mp_TailLink, mp_HeadLink);
mp_HeadLink = &AR_LinkPrev ;
mp_TailLink = VP_LinkNext ;
}
else if(VP_LinkNext==mp_TailLink)
{
ZCLink* VP_TailPrev2 =
AR_LinkPrev.mp_PrevLink ;
ZCLink::JoinLink(VP_TailPrev2, VP_LinkNext );
ZCLink::JoinLink(VP_LinkNext , &AR_LinkPrev );
ZCLink::MakeRing(mp_HeadLink , &AR_LinkPrev );
mp_TailLink = &AR_LinkPrev ;
}
else
{
ZCLink* VP_SwapPrev = AR_LinkPrev. mp_PrevLink;
ZCLink* VP_SwapNext = VP_LinkNext->mp_NextLink;
ZCLink::JoinLink(VP_SwapPrev , VP_LinkNext ) ;
ZCLink::JoinLink(VP_LinkNext , &AR_LinkPrev ) ;
ZCLink::JoinLink(&AR_LinkPrev, VP_SwapNext ) ;
}
return *this; /***********************************/
}/*
ZtCBaseList& SwapLinkNext(ZCLink& AR_LinkPrev)*/
ZtCBaseList& SwapLinkPrev(ZCLink& AR_LinkNext)
{
// 이전 링크와 위치를 맞바꾼다.
return SwapLinkNext(*AR_LinkNext.mp_PrevLink);
}/*
ZtCBaseList& SwapLinkPrev(ZCLink& AR_LinkNext)*/
ZtCBaseList& SwapLink(ZCLink& AR_LinkOne, ZCLink& AR_LinkTwo)
{
// AR_LinkOne 와 AR_LinkTwo 의 위치를 바꾼다.
if(size()<=1){return *this;}
if(&AR_LinkOne==&AR_LinkTwo){return *this;}
if(&AR_LinkOne==mp_HeadLink && &AR_LinkTwo==mp_TailLink)
{ return SwapLinkNext(AR_LinkTwo); }
if(&AR_LinkOne==mp_TailLink && &AR_LinkTwo==mp_HeadLink)
{ return SwapLinkNext(AR_LinkOne); }
/******************************************************/
if(&AR_LinkTwo==AR_LinkOne.mp_NextLink)
{ return SwapLinkNext(AR_LinkOne); }
if(&AR_LinkOne==AR_LinkTwo.mp_NextLink)
{ return SwapLinkNext(AR_LinkTwo); }
/******************************************************/
if(&AR_LinkOne==mp_HeadLink)
{
ZCLink* VP_HeadNext=mp_HeadLink->mp_NextLink;
ZCLink* VP_TwoNext =AR_LinkTwo. mp_NextLink;
ZCLink* VP_TwoPrev =AR_LinkTwo. mp_PrevLink;
ZCLink::JoinLink(&AR_LinkTwo, VP_HeadNext) ;
ZCLink::JoinLink( VP_TwoPrev, &AR_LinkOne ) ;
ZCLink::JoinLink(&AR_LinkOne, VP_TwoNext ) ;
ZCLink::MakeRing(&AR_LinkTwo, mp_TailLink) ;
mp_HeadLink = &AR_LinkTwo ; return *this;
}
if(&AR_LinkOne==mp_TailLink)
{
ZCLink* VP_TailPrev= mp_TailLink->mp_PrevLink;
ZCLink* VP_TwoNext = AR_LinkTwo. mp_NextLink;
ZCLink* VP_TwoPrev = AR_LinkTwo. mp_PrevLink;
ZCLink::JoinLink( VP_TwoPrev , &AR_LinkOne ) ;
ZCLink::JoinLink(&AR_LinkOne , VP_TwoNext ) ;
ZCLink::JoinLink( VP_TailPrev, &AR_LinkTwo ) ;
ZCLink::MakeRing( mp_HeadLink, &AR_LinkTwo ) ;
mp_TailLink = &AR_LinkTwo ; return *this;
}
/******************************************************/
if(&AR_LinkTwo==mp_HeadLink)
{
ZCLink* VP_HeadNext=mp_HeadLink->mp_NextLink;
ZCLink* VP_OneNext =AR_LinkOne. mp_NextLink;
ZCLink* VP_OnePrev =AR_LinkOne. mp_PrevLink;
ZCLink::JoinLink(&AR_LinkTwo, VP_HeadNext) ;
ZCLink::JoinLink( VP_OnePrev, &AR_LinkOne ) ;
ZCLink::JoinLink(&AR_LinkOne, VP_OneNext ) ;
ZCLink::MakeRing(&AR_LinkTwo, mp_TailLink) ;
mp_HeadLink = &AR_LinkTwo ; return *this;
}
if(&AR_LinkTwo==mp_TailLink)
{
ZCLink* VP_TailPrev=mp_TailLink->mp_PrevLink;
ZCLink* VP_OneNext =AR_LinkOne. mp_NextLink;
ZCLink* VP_OnePrev =AR_LinkOne. mp_PrevLink;
ZCLink::JoinLink( VP_OnePrev , &AR_LinkTwo ) ;
ZCLink::JoinLink(&AR_LinkTwo, VP_OneNext ) ;
ZCLink::JoinLink( VP_TailPrev, &AR_LinkTwo ) ;
ZCLink::MakeRing( mp_HeadLink, &AR_LinkTwo ) ;
mp_TailLink = &AR_LinkTwo ; return *this;
}
/********************************************************/
ZCLink* VP_OnePrev= AR_LinkOne.mp_PrevLink ;
ZCLink* VP_OneNext= AR_LinkOne.mp_NextLink ;
ZCLink* VP_TwoPrev= AR_LinkTwo.mp_PrevLink ;
ZCLink* VP_TwoNext= AR_LinkTwo.mp_NextLink ;
ZCLink::JoinLink( VP_OnePrev, &AR_LinkTwo) ;
ZCLink::JoinLink(&AR_LinkTwo, VP_OneNext) ;
ZCLink::JoinLink( VP_TwoPrev, &AR_LinkOne) ;
ZCLink::JoinLink(&AR_LinkOne, VP_TwoNext) ; return *this;
}/*
ZtCBaseList& SwapLink(ZCLink& AR_LinkOne, ZCLink& AR_LinkTwo)*/
ZtCBaseList& MoveLinkIn(ZCLink& AR_MoveLink, ZCLink& AR_StdLink, bool AB_After)
{
if(size()<=1 || &AR_MoveLink==&AR_StdLink){return *this;}
const bool CB_NeedFakeLink = ////////////////////////////////////
(
&AR_MoveLink==mp_HeadLink || &AR_MoveLink==mp_TailLink ||
&AR_StdLink ==mp_HeadLink || &AR_StdLink ==mp_TailLink
) ;
if(CB_NeedFakeLink) /////////////////////////////////////////////
{
// AR_MoveLink 를 떼어 내고, AR_MoveLink 의 앞뒤 링크를 연결.
ZCLinkFake VO_FakeHead ;
ZCLinkFake VO_FakeTail ;
ZCLink* VP_FakeHead =
reinterpret_cast<ZCLink*>(&VO_FakeHead ) ;
ZCLink* VP_FakeTail =
reinterpret_cast<ZCLink*>(&VO_FakeTail ) ;
ZCLink::JoinLink( VP_FakeHead, mp_HeadLink ) ;
ZCLink::JoinLink( mp_TailLink, VP_FakeTail ) ;
ZCLink* VP_MoveNext = AR_MoveLink.mp_NextLink;
ZCLink* VP_MovePrev = AR_MoveLink.mp_PrevLink;
ZCLink::JoinLink(VP_MovePrev, VP_MoveNext);
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
AR_MoveLink 떼어 내기 완료.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
ZCLink* VP_StdNext = AR_StdLink .mp_NextLink;
ZCLink* VP_StdPrev = AR_StdLink .mp_PrevLink;
if(AB_After)
{
ZCLink::JoinLink(&AR_StdLink , &AR_MoveLink);
ZCLink::JoinLink(&AR_MoveLink, VP_StdNext );
}
else
{
ZCLink::JoinLink( VP_StdPrev , &AR_MoveLink);
ZCLink::JoinLink(&AR_MoveLink, &AR_StdLink );
}
mp_HeadLink = VP_FakeHead->mp_NextLink;
mp_TailLink = VP_FakeTail->mp_PrevLink;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
return *this; /***************************/
}/*
const bool CB_NeedFakeLink = ////////////////////////////////////
(
&AR_MoveLink==mp_HeadLink || &AR_MoveLink==mp_TailLink ||
&AR_StdLink ==mp_HeadLink || &AR_StdLink ==mp_TailLink
) ;
if(CB_NeedFakeLink) ///////////////////////////////////////////*/
if( AB_After && AR_MoveLink.mp_PrevLink==&AR_StdLink)
{ return *this; }
if(!AB_After && AR_MoveLink.mp_NextLink==&AR_StdLink)
{ return *this; }
/*:::::::::::::::::::::::::::::::::::::::::::::::::*/
ZCLink* VP_MoveNext = AR_MoveLink.mp_NextLink;
ZCLink* VP_MovePrev = AR_MoveLink.mp_PrevLink;
ZCLink::JoinLink( VP_MovePrev, VP_MoveNext ) ;
ZCLink* VP_StdNext = AR_StdLink .mp_NextLink;
ZCLink* VP_StdPrev = AR_StdLink .mp_PrevLink;
if(AB_After)
{
ZCLink::JoinLink(&AR_StdLink , &AR_MoveLink);
ZCLink::JoinLink(&AR_MoveLink, VP_StdNext );
}
else
{
ZCLink::JoinLink( VP_StdPrev , &AR_MoveLink);
ZCLink::JoinLink(&AR_MoveLink, &AR_StdLink );
}
return *this; /*::::::::::::::::::::::::::::::::*/
}/*
ZtCBaseList& MoveLinkIn(ZCLink& AR_MoveLink, ZCLink& AR_StdLink, bool AB_After)*/
ZtCBaseList& MoveLinkIn(ZCLink& AR_MoveLink, ZCLinkOpt AO_StdOpt, bool AB_After)
{
ZCLink* VP_LinkStd = AO_StdOpt.Raw();
if(VP_LinkStd==0)
{
if(AB_After)
{ VP_LinkStd = mp_HeadLink; AB_After=false; }
else{ VP_LinkStd = mp_TailLink; AB_After=true ; }
}/*
if(VP_LinkStd==0)*/
return MoveLinkIn(AR_MoveLink, *VP_LinkStd, AB_After);
}/*
ZtCBaseList& MoveLinkIn(ZCLink& AR_MoveLink, ZCLinkOpt AO_StdOpt, bool AB_After)*/
ZtCBaseList& MoveLinkAfter (ZCLink& AR_MoveLink, ZCLinkOpt AO_StdOpt)
{ return MoveLinkIn(AR_MoveLink, AO_StdOpt, true ); }
ZtCBaseList& MoveLinkBefore(ZCLink& AR_MoveLink, ZCLinkOpt AO_StdOpt)
{ return MoveLinkIn(AR_MoveLink, AO_StdOpt, false); }
ZtCBaseList& MoveLinkHead(ZCLink& AR_MoveLink)
{ return MoveLinkIn(AR_MoveLink, ZCLinkOpt(0), true ); }
ZtCBaseList& MoveLinkTail(ZCLink& AR_MoveLink)
{ return MoveLinkIn(AR_MoveLink, ZCLinkOpt(0), false); }
ZtCBaseList& MoveRangeIn /*////////////////////////////////////////////*/
(
ZCLink& AR_MoveHead , ZCLink& AR_MoveTail ,
ZCLink& AR_StdLink , bool AB_After
)
/*#####################################################################*/
{
// AR_MoveHead ~ AR_MoveTail 밖에 AR_StdLink 이 있어야 한다.
// AR_MoveHead 이 AR_MoveTail 위에 와서는 안 된다.
if(size() <= 1 ){return *this;}
if(&AR_MoveHead == &AR_StdLink){return *this;}
if(&AR_MoveTail == &AR_StdLink){return *this;}
const bool CB_NeedFakeLink = ////////////////////////////////////
(
&AR_MoveHead==mp_HeadLink || &AR_MoveHead==mp_TailLink ||
&AR_MoveTail==mp_HeadLink || &AR_MoveTail==mp_TailLink ||
&AR_StdLink ==mp_HeadLink || &AR_StdLink ==mp_TailLink
) ;
if(CB_NeedFakeLink) /////////////////////////////////////////////
{
// AR_MoveHead~AR_MoveTail 를 떼어 내고, 그 앞뒤 링크를 연결.
ZCLinkFake VO_FakeHead ;
ZCLinkFake VO_FakeTail ;
ZCLink* VP_FakeHead =
reinterpret_cast<ZCLink*>(&VO_FakeHead ) ;
ZCLink* VP_FakeTail =
reinterpret_cast<ZCLink*>(&VO_FakeTail ) ;
ZCLink::JoinLink( VP_FakeHead, mp_HeadLink ) ;
ZCLink::JoinLink( mp_TailLink, VP_FakeTail ) ;
ZCLink* VP_MoveNext = AR_MoveTail.mp_NextLink;
ZCLink* VP_MovePrev = AR_MoveHead.mp_PrevLink;
ZCLink::JoinLink(VP_MovePrev, VP_MoveNext);
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
AR_MoveHead~AR_MoveTail 떼어 내기 완료.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
ZCLink* VP_StdNext = AR_StdLink .mp_NextLink;
ZCLink* VP_StdPrev = AR_StdLink .mp_PrevLink;
if(AB_After)
{
ZCLink::JoinLink(&AR_StdLink , &AR_MoveHead);
ZCLink::JoinLink(&AR_MoveTail, VP_StdNext );
}
else
{
ZCLink::JoinLink( VP_StdPrev , &AR_MoveHead);
ZCLink::JoinLink(&AR_MoveTail, &AR_StdLink );
}
mp_HeadLink = VP_FakeHead->mp_NextLink;
mp_TailLink = VP_FakeTail->mp_PrevLink;
ZCLink::MakeRing(mp_HeadLink, mp_TailLink);
return *this; /***************************/
}/*
const bool CB_NeedFakeLink = ////////////////////////////////////
(
&AR_MoveHead==mp_HeadLink || &AR_MoveHead==mp_TailLink ||
&AR_MoveTail==mp_HeadLink || &AR_MoveTail==mp_TailLink ||
&AR_StdLink ==mp_HeadLink || &AR_StdLink ==mp_TailLink
) ;
if(CB_NeedFakeLink) ///////////////////////////////////////////*/
if( AB_After && AR_MoveHead.mp_PrevLink==&AR_StdLink)
{ return *this; }
if(!AB_After && AR_MoveTail.mp_NextLink==&AR_StdLink)
{ return *this; }
/*:::::::::::::::::::::::::::::::::::::::::::::::::*/
ZCLink* VP_MoveNext = AR_MoveTail.mp_NextLink;
ZCLink* VP_MovePrev = AR_MoveHead.mp_PrevLink;
ZCLink::JoinLink( VP_MovePrev, VP_MoveNext ) ;
ZCLink* VP_StdNext = AR_StdLink .mp_NextLink;
ZCLink* VP_StdPrev = AR_StdLink .mp_PrevLink;
if(AB_After)
{
ZCLink::JoinLink(&AR_StdLink , &AR_MoveHead);
ZCLink::JoinLink(&AR_MoveTail, VP_StdNext );
}
else
{
ZCLink::JoinLink( VP_StdPrev , &AR_MoveHead);
ZCLink::JoinLink(&AR_MoveTail, &AR_StdLink );
}
return *this; /*::::::::::::::::::::::::::::::::*/
}/*
ZtCBaseList& MoveRangeIn ////////////////////////////////////////////////
(
ZCLink& AR_MoveHead, ZCLink& AR_MoveTail,
ZCLink& AR_StdLink , bool AB_After
)
#######################################################################*/
void SendOutHead(ZCLink& AR_CutLink, TypeThis& rhs) // AP_CutLink 를 잘라서 rhs 의 앞에 연결한다.
{ SendOutAfter (AR_CutLink, rhs, ZCLinkOpt(0)); }
void SendOutTail(ZCLink& AR_CutLink, TypeThis& rhs) // AP_CutLink 를 잘라서 rhs 의 뒤에 연결한다.
{ SendOutBefore(AR_CutLink, rhs, ZCLinkOpt(0)); }
ZtCBaseList& SendRangeOut ///////////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, TypeThis& rhs ,
ZCLinkOpt AO_LinkOpt, bool AB_After
)
/*#####################################################################*/
{
// AR_CutHead 부터 AR_CutTail 까지를 잘라서 rhs 의 AR_StdLink 뒤에 연결한다.
return CutLinkRangeOut /************************/
(
AR_CutHead, AR_CutTail , AI_CutSize,
rhs , AO_LinkOpt.Raw(), AB_After
);
/***********************************************/
}
/*#####################################################################*/
ZtCBaseList& SendRangeOutAfter //////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, TypeThis& rhs , ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
// AR_CutHead 부터 AR_CutTail 까지를 잘라서 rhs 의 AR_StdLink 뒤에 연결한다.
return CutLinkRangeOut /////////////
(
AR_CutHead, AR_CutTail, AI_CutSize, rhs, AO_LinkOpt.Raw(), true
);
////////////////////////////////////
}
ZtCBaseList& SendRangeOutBefore /////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, TypeThis& rhs , ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
// AR_CutHead 부터 AR_CutTail 까지를 잘라서 rhs 의 AR_StdLink 뒤에 연결한다.
return CutLinkRangeOut
(
AR_CutHead, AR_CutTail, AI_CutSize, rhs, AO_LinkOpt.Raw(), false
);
//////////////////////
}
/*#####################################################################*/
ZtCBaseList& SendRangeIn ////////////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, ZCLinkOpt AO_LinkOpt, bool AB_After
)
/*#####################################################################*/
{
// AR_CutHead 부터 AR_CutTail 까지를 잘라서 AR_StdLink 뒤에 연결한다.
if(AI_CutSize < 1 ){return *this;}
if(AI_CutSize >= size()){return *this;}
ZtCBaseList VO_Saver; CutLinkRangeOut /***********/
(
AR_CutHead , AR_CutTail , AI_CutSize,
RR(VO_Saver), AO_LinkOpt.Raw(), AB_After
);
/*************************************************/
if(AB_After)
return JoinAfter (VO_Saver, AO_LinkOpt);
else return JoinBefore(VO_Saver, AO_LinkOpt);
}
/*#####################################################################*/
ZtCBaseList& SendRangeInAfter ///////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
return SendRangeIn
( AR_CutHead, AR_CutTail, AI_CutSize, AO_LinkOpt, true );
}
/*#####################################################################*/
ZtCBaseList& SendRangeInBefore //////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
return SendRangeIn
( AR_CutHead, AR_CutTail, AI_CutSize, AO_LinkOpt, false);
}
/*#####################################################################*/
ZtCBaseList& SendRangeInHead ////////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
return SendRangeIn
( AR_CutHead, AR_CutTail, AI_CutSize, ZCLinkOpt(0), true );
}
/*#####################################################################*/
ZtCBaseList& SendRangeInTail ////////////////////////////////////////////
(
ZCLink& AR_CutHead, ZCLink& AR_CutTail,
TypeSize AI_CutSize, ZCLinkOpt AO_LinkOpt
)
/*#####################################################################*/
{
return SendRangeIn
( AR_CutHead, AR_CutTail, AI_CutSize, ZCLinkOpt(0), false);
}
/*#####################################################################*/
TypeThis& CopyThis(TypeThis& ARR_Rhs) const
{
// *this 를 복사해서, ARR_Rhs 의 끝에 연결한다.
if(size()<1) return ARR_Rhs;
ZCLink* VP_HeadCopy=0;
ZCLink* VP_TailCopy=0;
SendFreeOutCopy ////////////////////////
(
mp_HeadLink , size()-1,
RR(VP_HeadCopy), RR(VP_TailCopy)
);
////////////////////////////////////////
TypeThis VO_TempList;
VO_TempList.mp_HeadLink=VP_HeadCopy ;
VO_TempList.mp_TailLink=VP_TailCopy ;
VO_TempList.ml_LinkSize=size() ;
return ARR_Rhs.JoinTail(VO_TempList);
}/*
TypeThis& CopyThis(TypeThis& ARR_Rhs) const*/
TypeData& GetHeadData(){return mp_HeadLink->mo_DataObjt;}
TypeData& GetTailData(){return mp_TailLink->mo_DataObjt;}
const TypeData& GetHeadData() const{return mp_HeadLink->mo_DataObjt;}
const TypeData& GetTailData() const{return mp_TailLink->mo_DataObjt;}
operator TypeData&() { return AddTail() ; }
ZCDataOpt GetHeadDataOpt()
{
if(mp_HeadLink==0) return ZCDataOpt(0);
return ZCDataOpt(mp_HeadLink->mo_DataObjt);
}
ZCDataOpt GetTailDataOpt()
{
if(mp_TailLink==0) return ZCDataOpt(0);
return ZCDataOpt(mp_TailLink->mo_DataObjt);
}/*
ZCDataOpt GetTailDataOpt()*/
const ZCDataOpt GetHeadDataOpt() const
{
if(mp_HeadLink==0) return ZCDataOpt(0);
return ZCDataOpt(mp_HeadLink->mo_DataObjt);
}
const ZCDataOpt GetTailDataOpt() const
{
if(mp_TailLink==0) return ZCDataOpt(0);
return ZCDataOpt(mp_TailLink->mo_DataObjt);
}/*
const ZCDataOpt GetTailDataOpt()*/
TypeSize size() const{ return ml_LinkSize; }
TypeSize GetSize() const{ return ml_LinkSize; }
_VT_ TypeSize capacity ()
{ if(TTypeCRTP::ZEUseCRTP<1) return 0;
return GetChildObj().capacity ();
}
_VT_ TypeSize size_free()
{ if(TTypeCRTP::ZEUseCRTP<1) return 0;
return GetChildObj().size_free();
}
bool IsEmpty() const{return ml_LinkSize<1;}
bool empty () const{return ml_LinkSize<1;}
void clear(){DeleteAll();}
void push_front(TypeArg AO_ArgData){AddHead(AO_ArgData);}
void push_back (TypeArg AO_ArgData){AddTail(AO_ArgData);}
void pop_front(){DeleteHead();}
void pop_back (){DeleteTail();}
TypeData & front() {return GetHeadData();}
TypeData & back () {return GetTailData();}
TypeDataC& front() const{return GetHeadData();}
TypeDataC& back () const{return GetTailData();}
template<typename TFunctor> void IterElement(TFunctor AO_Functor)
{
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::
GetObjRef(AO_Functor)(VP_LoopLink->mo_DataObjt);
/* 위 코드로 인해서, AO_Functor 이 함수일 때 뿐이 아니라,
operator() 연산자를 가진 object 포인터일 때도 사용할 수
있게 되었다.
이제는 ZftMCP() 템플릿 함수를 사용해도 된다. -- 2025-09-27 00:38
*/
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template<typename TFunctor> void IterElement(TFunctor AO_Functor) */
template<typename TFunctor, typename TTypeHelp>
void IterElement(TFunctor AO_Functor, TTypeHelp AO_TypeHelp)
{
/*/////////////////////////////////////////////////////////////////////////////
■ TTypeHelp 가 class 일 경우, 크기가 커서 참조로 넘어가야 한다면,
IterElement<myFunctor, myClass&>(myFunctor_obj, myClass_Obj);
의 형태로 호출할 게 아니라, ZtCObjectPtr<> 을 사용하여,
myClass myClass_Obj; ZtCObjectPtr<myClass> myCObjPtr(myClass_Obj);
IterElement(myFunctor_obj, ZtCObjectPtr<myClass>(myClass_Obj));
형태를 사용하면 좋을 것 같다. -- 2014-06-16 23:11:00
이제는 ZtCRef 과 ZCCheckRef 클래스 템플릿을 사용하면 된다. -- 2021-03-11 11:00
다시 말하면 ZftMCP() 템플릿 함수를 사용하면 된다. -- 2025-09-27 01:01
/////////////////////////////////////////////////////////////////////////////*/
typedef ZNsMain::
ZtCCheckRef<TTypeHelp> ZCCheckRef;
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
**VP_LoopLink, ZCCheckRef::PassData(AO_TypeHelp)
);
////////////////////////////////////////////
/* 위 코드로 인해서, AO_Functor 이 함수일 때 뿐이 아니라, operator()
연산자를 가진 object 포인터일 때도 사용할 수 있게 되었다. */
/* ZtCRef 클래스를 사용하는 ZCCheckRef::PassData() 으로 인해, 인수를
참조로 넘길 수 있게 되었다. -- 2021-03-10 16:56 */
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template<typename TFunctor, typename TTypeHelp>
void IterElement(TFunctor AO_Functor, TTypeHelp AO_TypeHelp) */
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElement
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
/*#############################################################################*/
{
typedef ZNsMain::ZtCCheckRef<TTypeHelp1> ZCCheckRef1;
typedef ZNsMain::ZtCCheckRef<TTypeHelp2> ZCCheckRef2;
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
VP_LoopLink->mo_DataObjt
, ZCCheckRef1::PassData(AO_TypeHelp1)
, ZCCheckRef2::PassData(AO_TypeHelp2)
);
////////////////////////////////////////////
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElement
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
###############################################################################*/
template<typename TFunctor> void IterElemRev(TFunctor AO_Functor)
{
ZCLink* VP_LoopLink=mp_TailLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::
GetObjRef(AO_Functor)(**VP_LoopLink);
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template<typename TFunctor> void IterElemRev(TFunctor AO_Functor) */
template<typename TFunctor, typename TTypeHelp>
void IterElemRev(TFunctor AO_Functor, TTypeHelp AO_TypeHelp)
{
typedef ZNsMain::
ZtCCheckRef<TTypeHelp> ZCCheckRef;
ZCLink* VP_LoopLink = mp_TailLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
**VP_LoopLink, ZCCheckRef::PassData(AO_TypeHelp)
);
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template<typename TFunctor, typename TTypeHelp>
void IterElemRev(TFunctor AO_Functor, TTypeHelp AO_TypeHelp) */
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemRev
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
/*#############################################################################*/
{
typedef ZNsMain::ZtCCheckRef<TTypeHelp1> ZCCheckRef1;
typedef ZNsMain::ZtCCheckRef<TTypeHelp2> ZCCheckRef2;
ZCLink* VP_LoopLink = mp_TailLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
VP_LoopLink->mo_DataObjt
, ZCCheckRef1::PassData(AO_TypeHelp1)
, ZCCheckRef2::PassData(AO_TypeHelp2)
);
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_Size)*/
}/*
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemRev
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
###############################################################################*/
template<typename TFunctor> void IterElemLink(TFunctor AO_Functor)
{
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::
GetObjRef(AO_Functor)( *VP_LoopLink );
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template<typename TFunctor> void IterElemLink(TFunctor AO_Functor) */
template<typename TFunctor, typename TTypeHelp>
void IterElemLink(TFunctor AO_Functor, TTypeHelp AO_TypeHelp)
{
typedef ZNsMain::
ZtCCheckRef<TTypeHelp> ZCCheckRef;
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
*VP_LoopLink, ZCCheckRef::PassData(AO_TypeHelp)
);
////////////////////////////////////////////
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template<typename TFunctor, typename TTypeHelp>
void IterElemLink(TFunctor AO_Functor, TTypeHelp AO_TypeHelp) */
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemLink
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
/*#############################################################################*/
{
typedef ZNsMain::ZtCCheckRef<TTypeHelp1> ZCCheckRef1;
typedef ZNsMain::ZtCCheckRef<TTypeHelp2> ZCCheckRef2;
ZCLink* VP_LoopLink=mp_HeadLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
*VP_LoopLink
, ZCCheckRef1::PassData(AO_TypeHelp1)
, ZCCheckRef2::PassData(AO_TypeHelp2)
);
////////////////////////////////////////////
VP_LoopLink = VP_LoopLink->mp_NextLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemLink
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
###############################################################################*/
template<typename TFunctor> void IterElemLinkRev(TFunctor AO_Functor)
{
ZCLink* VP_LoopLink = mp_TailLink ;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::
GetObjRef(AO_Functor)( *VP_LoopLink );
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template<typename TFunctor> void IterElemLinkRev(TFunctor AO_Functor) */
template<typename TFunctor, typename TTypeHelp>
void IterElemLinkRev(TFunctor AO_Functor, TTypeHelp AO_TypeHelp)
{
typedef ZNsMain::
ZtCCheckRef<TTypeHelp> ZCCheckRef;
ZCLink* VP_LoopLink=mp_TailLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
*VP_LoopLink, ZCCheckRef::PassData(AO_TypeHelp)
);
////////////////////////////////////////////
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template<typename TFunctor, typename TTypeHelp>
void IterElemLinkRev(TFunctor AO_Functor, TTypeHelp AO_TypeHelp) */
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemLinkRev
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
/*#############################################################################*/
{
typedef ZNsMain::ZtCCheckRef<TTypeHelp1> ZCCheckRef1;
typedef ZNsMain::ZtCCheckRef<TTypeHelp2> ZCCheckRef2;
ZCLink* VP_LoopLink=mp_TailLink;
__for0(TypeSize, i, ml_LinkSize)
{
ZtCTypeData<TFunctor>::GetObjRef(AO_Functor)
(
*VP_LoopLink
, ZCCheckRef1::PassData(AO_TypeHelp1)
, ZCCheckRef2::PassData(AO_TypeHelp2)
);
////////////////////////////////////////////
VP_LoopLink = VP_LoopLink->mp_PrevLink ;
}/*
__for0(TypeSize, i, ml_LinkSize)*/
}/*
template
< typename TFunctor , typename TTypeHelp1 , typename TTypeHelp2 >
void IterElemLinkRev
( TFunctor AO_Functor, TTypeHelp1 AO_TypeHelp1, TTypeHelp2 AO_TypeHelp2 )
###############################################################################*/
ZCLink * GetHeadLinkPtr() {return mp_HeadLink;}
ZCLink * GetTailLinkPtr() {return mp_TailLink;}
ZCLinkC* GetHeadLinkPtr() const{return mp_HeadLink;}
ZCLinkC* GetTailLinkPtr() const{return mp_TailLink;}
ZCLink * GetLinkPtr(TypeSize AI_Index) {return mp_HeadLink->GetNextPrevPtr(AI_Index-1);}
ZCLinkC* GetLinkPtr(TypeSize AI_Index) const{return mp_HeadLink->GetNextPrevPtr(AI_Index-1);}
ZCLink & GetHeadLink(TypeSize AI_Distance) {return (*mp_HeadLink)+AI_Distance;}
ZCLink & GetTailLink(TypeSize AI_Distance) {return (*mp_TailLink)-AI_Distance;}
ZCLinkC& GetHeadLink(TypeSize AI_Distance) const{return (*mp_HeadLink)+AI_Distance;}
ZCLinkC& GetTailLink(TypeSize AI_Distance) const{return (*mp_TailLink)-AI_Distance;}
ZCLink & GetNode(TypeSize AI_Index) {return (*mp_HeadLink)+(AI_Index-1);}
ZCLinkC& GetNode(TypeSize AI_Index) const{return (*mp_HeadLink)+(AI_Index-1);}
ZCLink * HeadPtr() {return mp_HeadLink;}
ZCLink * TailPtr() {return mp_TailLink;}
ZCLinkC* HeadPtr() const{return mp_HeadLink;}
ZCLinkC* TailPtr() const{return mp_TailLink;}
ZCLink * HeadPtr(TypeSize AI_Distance) {return &((*mp_HeadLink)+AI_Distance);}
ZCLink * TailPtr(TypeSize AI_Distance) {return &((*mp_TailLink)-AI_Distance);}
ZCLinkC* HeadPtr(TypeSize AI_Distance) const{return &((*mp_HeadLink)+AI_Distance);}
ZCLinkC* TailPtr(TypeSize AI_Distance) const{return &((*mp_TailLink)-AI_Distance);}
ZCLink & HeadRef() {return *mp_HeadLink;}
ZCLink & TailRef() {return *mp_TailLink;}
ZCLinkC& HeadRef() const{return *mp_HeadLink;}
ZCLinkC& TailRef() const{return *mp_TailLink;}
ZCLink & HeadRef(TypeSize AI_Distance) {return (*mp_HeadLink)+AI_Distance;}
ZCLink & TailRef(TypeSize AI_Distance) {return (*mp_TailLink)-AI_Distance;}
ZCLinkC& HeadRef(TypeSize AI_Distance) const{return (*mp_HeadLink)+AI_Distance;}
ZCLinkC& TailRef(TypeSize AI_Distance) const{return (*mp_TailLink)-AI_Distance;}
ZCLinkOpt HeadOpt() {return ZCLinkOpt(mp_HeadLink);}
ZCLinkOpt TailOpt() {return ZCLinkOpt(mp_TailLink);}
ZCLinkOptC HeadOpt() const{return ZCLinkOpt(mp_HeadLink);}
ZCLinkOptC TailOpt() const{return ZCLinkOpt(mp_TailLink);}
ZCLinkOpt HeadOpt(TypeSize AI_Distance)
{if(mp_HeadLink==0){return ZCLinkOpt(0);} return ZCLinkOpt((*mp_HeadLink)+AI_Distance);}
ZCLinkOpt TailOpt(TypeSize AI_Distance)
{if(mp_TailLink==0){return ZCLinkOpt(0);} return ZCLinkOpt((*mp_TailLink)-AI_Distance);}
ZCLinkOptC HeadOpt(TypeSize AI_Distance) const
{if(mp_HeadLink==0){return ZCLinkOpt(0);} return ZCLinkOpt((*mp_HeadLink)+AI_Distance);}
ZCLinkOptC TailOpt(TypeSize AI_Distance) const
{if(mp_TailLink==0){return ZCLinkOpt(0);} return ZCLinkOpt((*mp_TailLink)-AI_Distance);}
ZCLink & _1() {return HeadRef();}
ZCLink & _0() {return TailRef();}
ZCLinkC& _1() const{return HeadRef();}
ZCLinkC& _0() const{return TailRef();}
ZCLink & _1(TypeSize AI_Distance) {return HeadRef(AI_Distance);}
ZCLink & _0(TypeSize AI_Distance) {return TailRef(AI_Distance);}
ZCLinkC& _1(TypeSize AI_Distance) const{return HeadRef(AI_Distance);}
ZCLinkC& _0(TypeSize AI_Distance) const{return TailRef(AI_Distance);}
ZCDataOpt GetDataOpt(TypeSize AI_Index) // 1부터 시작.
{ return DataOpt(AI_Index-1); }
ZCDataOptC GetDataOpt(TypeSize AI_Index) const
{ return DataOpt(AI_Index-1); }
ZCDataOpt DataOpt(TypeSize AI_Index) // 1부터
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**HeadPtr(AI_Index-1));
}
ZCDataOptC DataOpt(TypeSize AI_Index) const
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**HeadPtr(AI_Index-1));
}/*
ZCDataOptC DataOpt(TypeSize AI_Index) const*/
ZCDataOpt DataOptHead(TypeSize AI_Distance=0)
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**HeadPtr(AI_Distance));
}
ZCDataOpt DataOptTail(TypeSize AI_Distance=0)
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**TailPtr(AI_Distance));
}/*
ZCDataOpt DataOptTail(TypeSize AI_Distance=0)*/
ZCDataOptC DataOptHead(TypeSize AI_Distance=0) const
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**HeadPtr(AI_Distance));
}
ZCDataOptC DataOptTail(TypeSize AI_Distance=0) const
{ if(mp_HeadLink==0){return ZCDataOpt(0);}
return ZCDataOpt(**TailPtr(AI_Distance));
}/*
ZCDataOptC DataOptTail(TypeSize AI_Distance=0) const*/
ZCLinkOpt GetLinkOpt(TypeSize AI_Index)
{ if(mp_HeadLink==0) return ZCLinkOpt(0); return ZCLinkOpt(GetLinkPtr(AI_Index)); }
ZCLinkOptC GetLinkOpt(TypeSize AI_Index) const
{ if(mp_HeadLink==0) return ZCLinkOpt(0); return ZCLinkOpt(GetLinkPtr(AI_Index)); }
IterEasy GetHeadIterEasy () {return GetHeadLinkPtr();}
IterEasy GetTailIterEasy () {return GetTailLinkPtr();}
IterEasyID GetHeadIterEasyID () {return (IterEasyID )GetHeadLinkPtr();}
IterEasyID GetTailIterEasyID () {return (IterEasyID )GetTailLinkPtr();}
IterEasy GetHeadIterEasy () const{return GetHeadLinkPtr();}
IterEasy GetTailIterEasy () const{return GetTailLinkPtr();}
IterEasyIDc GetHeadIterEasyID () const{return (IterEasyIDc)GetHeadLinkPtr();}
IterEasyIDc GetTailIterEasyID () const{return (IterEasyIDc)GetTailLinkPtr();}
IterEasyIDc GetHeadIterEasyIDc() const{return (IterEasyIDc)GetHeadLinkPtr();}
IterEasyIDc GetTailIterEasyIDc() const{return (IterEasyIDc)GetTailLinkPtr();}
void MoveNextIter(ZCLink* & APR_CLink ) const
{ APR_CLink=APR_CLink->GetNextPtr(); }
void MoveNextIter(IterEasyID & ARRI_IterEasyID ) const
{ MoveNextIter((ZCLink*&)(ARRI_IterEasyID)); }
void MoveNextIter(TypeLinkC* & APR_CLink ) const
{ APR_CLink=APR_CLink->GetNextPtr(); }
void MoveNextIter(IterEasyIDc& ARRI_IterEasyID ) const
{ MoveNextIter((TypeLinkC*&)(ARRI_IterEasyID)); }
void MoveNextIter(iterator & ARR_Iterator ) const{++ARR_Iterator;}
void MoveNextIter(iteratorN & ARR_Iterator ) const{++ARR_Iterator;}
void MovePrevIter(ZCLink* & APR_CLink ) const
{ APR_CLink=APR_CLink->GetPrevPtr(); }
void MovePrevIter(IterEasyID & ARRI_IterEasyID ) const
{ MovePrevIter((ZCLink*&)(ARRI_IterEasyID)); }
void MovePrevIter(TypeLinkC* & APR_CLink ) const
{ APR_CLink=APR_CLink->GetPrevPtr(); }
void MovePrevIter(IterEasyIDc& ARRI_IterEasyID ) const
{ MovePrevIter((TypeLinkC*&)(ARRI_IterEasyID)); }
void MovePrevIter(iterator & ARR_Iterator ) const{--ARR_Iterator;}
void MovePrevIter(iteratorN & ARR_Iterator ) const{--ARR_Iterator;}
iterator begin () { return ZCNodePoint (*this); }
iteratorN begin () const{ return ZCNodePointN(*this); }
iterator end () { return ZCNodePoint ::MakeTailPoint(*this); }
iteratorN end () const{ return ZCNodePointN::MakeTailPoint(*this); }
iteratorN cbegin () const{ return ZCNodePointN(*this); }
iteratorN cend () const{ return ZCNodePointN::MakeTailPoint(*this); }
IterEasy ItHEasy() {return GetHeadIterEasy ();}
IterEasy ItTEasy() {return GetTailIterEasy ();}
IterEasyID ItHID () {return GetHeadIterEasyID ();}
IterEasyID ItTID () {return GetTailIterEasyID ();}
IterEasyC ItHEasy() const{return GetHeadIterEasy ();}
IterEasyC ItTEasy() const{return GetTailIterEasy ();}
IterEasyIDc ItHID () const{return GetHeadIterEasyIDc();}
IterEasyIDc ItTID () const{return GetTailIterEasyIDc();}
IterEasyIDc ItHIDc () const{return GetHeadIterEasyIDc();}
IterEasyIDc ItTIDc () const{return GetTailIterEasyIDc();}
void ItNext(ZCLink * & APR_CLink ) const{ APR_CLink=APR_CLink->GetNextPtr() ;}
void ItNext(IterEasyID & ARRI_IterEasyID) const{ItNext((ZCLink*&)(ARRI_IterEasyID));}
void ItNext(TypeLinkC* & APR_CLink ) const{ APR_CLink=APR_CLink->GetNextPtr() ;}
void ItNext(iterator & ARR_Iterator ) const{++ARR_Iterator;}
void ItNext(iteratorN & ARR_Iterator ) const{++ARR_Iterator;}
void ItNext(IterEasyIDc & ARRI_IterEasyID) const
{ ItNext((TypeLinkC*&) (ARRI_IterEasyID)); }
void ItPrev(ZCLink * & APR_CLink ) const{ APR_CLink=APR_CLink->GetPrevPtr() ;}
void ItPrev(IterEasyID & ARRI_IterEasyID) const{ItPrev((ZCLink*&)(ARRI_IterEasyID));}
void ItPrev(TypeLinkC* & APR_CLink ) const{ APR_CLink=APR_CLink->GetPrevPtr() ;}
void ItPrev(iterator & ARR_Iterator ) const{--ARR_Iterator;}
void ItPrev(iteratorN & ARR_Iterator ) const{--ARR_Iterator;}
void ItPrev(IterEasyIDc & ARRI_IterEasyID) const
{ ItPrev((TypeLinkC*&) (ARRI_IterEasyID)); }
/*//////////////////////////////////////////////////////////////////
ItPrev(IterEasyIDc&) 와 ItNext(IterEasyIDc&) 에서
(TypeLinkC*&)
라는 형변환 코드가 있는데,
(TypeLinkC*&) 형변환과 (TypeLinkC*) 형변환
은 다름에 주의. 따라서 ItNext(IterEasyID&) ItPrev(IterEasyID&) 에서
(TypeLink *&) 형변환과 (TypeLink *) 형변환
도 서로 다른 것이다. -- 2025-10-15 16:19
//////////////////////////////////////////////////////////////////*/
TypeData & ItD(ZCLink * AP_CLink ){return **AP_CLink ;}
TypeData & ItD(iterator & ARR_Iterator ){return *ARR_Iterator;}
TypeData & ItD(IterEasyID AH_IterEasyID )
{ return ItD((TypeLink* )AH_IterEasyID);}
TypeDataC& ItD(TypeLinkC * AP_CLink ) const{ return **AP_CLink ;}
TypeDataC& ItD(iteratorN & ARR_Iterator ) const{ return *ARR_Iterator ;}
TypeDataC& ItD(IterEasyIDc AH_IterEasyID ) const
{ return ItD((TypeLinkC*)AH_IterEasyID);}
TypeData & ItD( TypeLink * AP_CLink , TypeSize AI_FarNum)
{return **(AP_CLink->GetNextPrevPtr(AI_FarNum)) ; }
TypeData & ItD( IterEasyID AH_IterEasyID, TypeSize AI_FarNum)
{ return ItD((ZCLink *)AH_IterEasyID , AI_FarNum); }
TypeData & ItD( iterator & ARR_Iterator , TypeSize AI_FarNum)
{ return ItD((ZCLink *)ARR_Iterator , AI_FarNum); }
TypeDataC& ItD( TypeLinkC * AP_CLink , TypeSize AI_FarNum) const
{return **(AP_CLink->GetNextPrePtr(AI_FarNum)) ; }
TypeDataC& ItD( IterEasyIDc AH_IterEasyID, TypeSize AI_FarNum) const
{ return ItD((ZCLinkC*)AH_IterEasyID , AI_FarNum); }
TypeDataC& ItD( iteratorN & ARR_Iterator , TypeSize AI_FarNum) const
{ return ItD((ZCLinkC*)ARR_Iterator , AI_FarNum); }
public :
};/*
template //////////////////////////////////////////////////////////////////
<
typename TType ,
typename TTypArgu = const TType& ,
typename TTypeAlloc = ZCAllocator ,
typename TTypSize = ZTypLong ,
typename TMoveObj = ZNsMain::
ZtCMoveObj<TType, TTypArgu, true> ,
typename TTypeCRTP = ZNsType::ZtCTypeCRTP<ZCEmpty, false>
>
class ZtCBaseList #######################################################*/
namespace ZNsChars
{
template<typename TTypeChars> class ZtCMainChars;
}/*
namespace ZNsChars*/
template< typename TTypeChar, typename TTypeLength=ZTypLength
>
class ZtCChars /**#########################################*/
{
public :
template<typename TTypeChars>
friend class ZNsChars::ZtCMainChars ;
public :
typedef TTypeChar TypeChar ;
typedef TTypeLength TypeLength ;
typedef TTypeLength TypeSize ;
public:
typedef const TTypeChar TypeCharC ;
typedef const TTypeChar* TypeCharCP ;
private:
TypeChar* mp_TypeChar ;
TypeSize ml_TypeSize ;
public :
ZtCChars()
{
mp_TypeChar = 0;
ml_TypeSize = 0;
}/*
ZtCChars()*/
explicit ZtCChars(TypeCharC* APC_TypeChar)
{
mp_TypeChar =
const_cast<TypeChar*> (APC_TypeChar);
ml_TypeSize = ZftLengthType
<TypeSize, TypeChar > (mp_TypeChar );
}/*
explicit ZtCChars(TypeCharC* APC_TypeChar)*/
ZtCChars(TypeCharC* APC_TypeChar, TypeSize AL_Length)
{
mp_TypeChar = const_cast
<TypeChar*>(APC_TypeChar);
ml_TypeSize = AL_Length ;
}/*
ZtCChars(TypeCharC* APC_TypeChar, TypeSize AL_Length)*/
ZtCChars(const ZtCChars& rhs)
{
mp_TypeChar = const_cast
<TypeChar*>( rhs.mp_TypeChar ) ;
ml_TypeSize = rhs.ml_TypeSize ;
}/*
ZtCChars(const ZtCChars& rhs)*/
ZtCChars(ZtCChars& rhs)
{
mp_TypeChar = rhs.mp_TypeChar ;
ml_TypeSize = rhs.ml_TypeSize ;
}/*
ZtCChars(ZtCChars& rhs)*/
ZtCChars& operator=(const ZtCChars& rhs)
{
mp_TypeChar = const_cast<ZtCChars&>(rhs).mp_TypeChar ;
ml_TypeSize = const_cast<ZtCChars&>(rhs).ml_TypeSize ;
return *this;
}/*
ZtCChars& operator=(const ZtCChars& rhs)*/
ZtCChars& operator=(ZtCChars& rhs)
{
mp_TypeChar = rhs.mp_TypeChar ;
ml_TypeSize = rhs.ml_TypeSize ;
return *this;
}/*
ZtCChars& operator=(ZtCChars& rhs)*/
void Init()
{
mp_TypeChar = 0;
ml_TypeSize = 0;
}/*
void Init()*/
void Init(TypeCharC* APC_TypeChar)
{
mp_TypeChar =
const_cast<TypeChar*>(APC_TypeChar);
ml_TypeSize = ZftGetLength(mp_TypeChar);
}/*
void Init(TypeCharC* APC_TypeChar)*/
void Init(TypeCharC* APC_TypeChar, TypeLength AL_Length)
{
mp_TypeChar = const_cast
<TypeChar*>(APC_TypeChar) ;
ml_TypeSize = AL_Length ;
}/*
void Init(TypeCharC* APC_TypeChar, TypeLength AL_Length)*/
void InitData(TypeCharC* APC_TypeChar)
{
mp_TypeChar=const_cast<TypeChar*>(APC_TypeChar);
}/*
void InitData(TypeCharC* APC_TypeChar)*/
void InitLength(TypeLength AL_Length)
{
ml_TypeSize=AL_Length;
}/*
void InitLength(TypeLength AL_Length)*/
TypeChar* data() {return mp_TypeChar ;}
TypeCharC* data() const{return mp_TypeChar ;}
TypeLength size() const{return ml_TypeSize ;}
ZtCChars& operator+=(TypeLength AI_MovePos)
{
return MoveChar(AI_MovePos);
}/*
ZtCChars& operator+=(TypeLength AI_MovePos)*/
int operator-(const ZtCChars& rhs) const
{
// 두 문자열이 같으면 0
// 왼쪽 문자열이 크면 0 보다 큰 어떤 수
// 오른쪽 문자열이 크면 0 보다 작은 어떤 수를 반환
TypeCharC* VP_Left = mp_TypeChar;
TypeCharC* VP_Right=rhs.mp_TypeChar;
typedef typename ZtCCharInt
<TypeChar>::TypeInt TypeCharInt;
#if(_CODE_OLD_)
TypeChar VC_Minus = 0;
#else
TypeCharInt VI_Minus = 0; // 페이지 하단의 'char 의 int 확장에 따른 문제의 코드' 참고.
#endif
TypeLength VL_Index = 0;
TypeLength VL_Loop = /*:::::::::::::::::::::::::*/
(
ml_TypeSize <= rhs.ml_TypeSize
? this->ml_TypeSize
: rhs. ml_TypeSize
) ;
/*::::::::::::::::::::::::::::::::::::::::::::::::*/
while(VL_Index<VL_Loop)
{
#if(_CODE_OLD_)
if((VC_Minus=*VP_Left++ - *VP_Right++)!=0)
{
return VC_Minus;
}/*
if((VC_Minus=*VP_Left++ - *VP_Right++)!=0)*/
#else
if((VI_Minus=TypeCharInt(*VP_Left++) - TypeCharInt(*VP_Right++))!=0)
{
return VI_Minus; // 페이지 하단의 'char 의 int 확장에 따른 문제의 코드' 참고.
}/*
if((VI_Minus=TypeCharInt(*VP_Left++) - TypeCharInt(*VP_Right++))!=0)*/
#endif
++VL_Index;
}/*
while(VL_Index<VL_Loop)*/
return ml_TypeSize-rhs.ml_TypeSize;
}/*
int operator-(const ZtCChars& rhs) const*/
bool operator==(const ZtCChars& rhs) const{return (*this)-rhs == 0 ;}
bool operator> (const ZtCChars& rhs) const{return (*this)-rhs > 0 ;}
bool operator< (const ZtCChars& rhs) const{return (*this)-rhs < 0 ;}
bool operator>=(const ZtCChars& rhs) const{return (*this)-rhs >= 0 ;}
bool operator<=(const ZtCChars& rhs) const{return (*this)-rhs <= 0 ;}
ZtCChars& MoveChar(TypeLength AI_MovePos)
{
mp_TypeChar += AI_MovePos ;
ml_TypeSize -= AI_MovePos ;
return *this;
}/*
ZtCChars& MoveChar(TypeLength AI_MovePos)*/
ZTypIntI GetInt(bool AB_IsBigEndian=true) const
{
ZTycIntI CI_IntByte = sizeof(ZTypIntI);
ZTycIntI CI_SearchSize =
(ml_TypeSize<CI_IntByte ? ml_TypeSize : CI_IntByte) ;
ZTypIntI VI_Result = 0 ;
ZTypIntI VI_TempInt = 1 ;
if(AB_IsBigEndian)
{
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt *= 256 ;
}/*
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)*/
return VI_Result;
}/*
if(AB_IsBigEndian)*/
for(ZTypIntI i=0; i<CI_SearchSize; ++i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt*= 256 ;
}/*
for(ZTypIntI i=0; i<CI_SearchSize; ++i)*/
return VI_Result;
}/*
ZTypIntI GetInt(bool AB_IsBigEndian=true) const*/
ZTypIntL GetLong(bool AB_IsBigEndian=true) const
{
ZTycIntI CI_IntByte = sizeof(ZTypIntL);
ZTycIntI CI_SearchSize =
(ml_TypeSize<CI_IntByte ? ml_TypeSize : CI_IntByte) ;
ZTypIntL VI_Result = 0 ;
ZTypIntL VI_TempInt = 1 ;
if(AB_IsBigEndian)
{
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt *= 256 ;
}/*
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)*/
return VI_Result;
}/*
if(AB_IsBigEndian)*/
for(ZTypIntI i=0; i<CI_SearchSize; ++i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt *= 256 ;
}/*
for(ZTypIntI i=0; i<CI_SearchSize; ++i)*/
return VI_Result;
}/*
ZTypIntL GetLong(bool AB_IsBigEndian=true) const*/
ZTypIntLL GetLLong(bool AB_IsBigEndian=true) const
{
ZTycIntI CI_IntByte = sizeof(ZTypIntLL);
ZTycIntI CI_SearchSize =
(ml_TypeSize<CI_IntByte ? ml_TypeSize : CI_IntByte) ;
ZTypIntLL VI_Result = 0 ;
ZTypIntLL VI_TempInt = 1 ;
if(AB_IsBigEndian)
{
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt *= 256 ;
}/*
for(ZTypIntI i=CI_SearchSize-1; i>=0; --i)*/
return VI_Result;
}/*
if(AB_IsBigEndian)*/
for(ZTypIntI i=0; i<CI_SearchSize; ++i)
{
VI_Result += (ZTypIntI)(ZTypUChar)(mp_TypeChar[i]) * VI_TempInt ;
VI_TempInt *= 256 ;
}/*
for(ZTypIntI i=0; i<CI_SearchSize; ++i)*/
return VI_Result;
}/*
ZTypIntLL GetLLong(bool AB_IsBigEndian=true) const*/
public:
};/*
template< typename TTypeChar, typename TTypeLength=ZTypLength
>
class ZtCChars ############################################*/
typedef ZtCChars<char > ZCChars ;
typedef ZtCChars<wchar_t> ZCCharsW ;
typedef ZtCChars<char > ZCCharView ; // for string_view in C++17
typedef ZtCChars<wchar_t> ZCCharViewW ;
template<> string& ZftMakeStr(string& ARR_SaveCStr, const ZCCharView& AR_View)
{ ARR_SaveCStr.append(AR_View.data(), AR_View.size()); return ARR_SaveCStr; }
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, const ZCCharViewW& AR_View)
{ ARR_SaveCStr.append(AR_View.data(), AR_View.size()); return ARR_SaveCStr; }
/*//////////////////////////////////////////////////////////////////////////////////////
■ template<typename TTypString> class ZtCCharType
stl 의 string 나 wstring 같은 문자열 클래스를 인자로 받는 템플릿이 있다고 할 때, 해당
자열 클래스가 다루는 문자형이 char 인지 wchar_t 인지 알기가 약간 번거로운데, 이를 쉽
게 하기 위해서, 특히 ZtCStringBase 와 통일적으로 일관성있게 알 수 있도록
template<> class ZtCCharType
cf) typedef ZtCCharType::TypeChar TypeChar;
을 설계한다. 물론
string::traits_type::char_type
string::traits_type::int_type
을 사용하면 관련 자료형을 알 수 있기는 한데, 혹시나 나중에 string 보다 간단한 문자열
클래스가 있을 경우를 대비하는 의미에서라도 이렇게 한 번 해보자.
-- 2025-10-08 21:24
//////////////////////////////////////////////////////////////////////////////////////*/
template<typename TTypString> class ZtCCharType
{
public:
typedef typename TTypString::
traits_type::char_type /*++*/ TypeChar;
typedef TTypString /*++*/ TypeCStr;
typedef typename
ZtCCharInt<TypeChar>::TypeInt TypeInt ;
typedef typename TypeCStr::
size_type /*++*/ TypeSize;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const int CI_ByteSize = sizeof(TypeChar);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef TypeChar char_type ; // for stl string/wstring
typedef TypeInt int_type ; // for stl string/wstring
typedef TypeSize size_type ; // for stl string/wstring
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};/*
template<typename TTypString> class ZtCCharType*/
template<> class ZtCCharType<std::string>
{
public:
typedef std::string /*+++++++*/ TypeCStr;
typedef char /*+++++++*/ TypeChar;
typedef typename TypeCStr::
size_type /*+++++++*/ TypeSize;
typedef typename
ZtCCharInt<char>::TypeInt TypeInt ;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const int CI_ByteSize = sizeof(TypeChar);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef TypeChar char_type ;
typedef TypeInt int_type ;
typedef TypeSize size_type ;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};/*
template<> class ZtCCharType<std::string>*/
template<> class ZtCCharType<std::wstring>
{
public:
typedef std::wstring /*+++++++*/ TypeCStr;
typedef wchar_t /*+++++++*/ TypeChar;
typedef typename
ZtCCharInt<wchar_t>::TypeInt TypeInt ;
typedef typename TypeCStr::
size_type /*+++++++*/ TypeSize;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const int CI_ByteSize = sizeof(TypeChar);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef TypeChar char_type ;
typedef TypeInt int_type ;
typedef TypeSize size_type ;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};/*
template<> class ZtCCharType<std::wstring>*/
template<typename TTypChar, typename TTypLength> class ZtCBoolStr
{
public:
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef ZtCChars<TTypChar, TTypLength> ZCChars;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMarkTrue ()
{ static const ZCChars SO_ZCChars; return SO_ZCChars; }
static const ZCChars& GetMarkFalse()
{ static const ZCChars SO_ZCChars; return SO_ZCChars; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMark(bool AB_Bool)
{
return AB_Bool ? GetMarkTrue() : GetMarkFalse();
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};
/*##############################################################################*/
template<typename TTypLength>
class ZtCBoolStr<char, TTypLength> /*+++++++++++++++++++++++++++++++*/
{
public:
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef ZtCChars<char, TTypLength> ZCChars;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMarkTrue ()
{ static const ZCChars SO_ZCChars("true" ); return SO_ZCChars; }
static const ZCChars& GetMarkFalse()
{ static const ZCChars SO_ZCChars("false"); return SO_ZCChars; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMark(bool AB_Bool)
{
return AB_Bool ? GetMarkTrue() : GetMarkFalse();
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};
//////////////////////////////////////////////////////////////////////////
template<typename TTypLength>
class ZtCBoolStr<wchar_t, TTypLength> /*++++++++++++++++++++++++++++*/
{
public:
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
typedef ZtCChars<wchar_t, TTypLength> ZCChars;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMarkTrue ()
{ static const ZCChars SO_ZCChars(L"true" ); return SO_ZCChars; }
static const ZCChars& GetMarkFalse()
{ static const ZCChars SO_ZCChars(L"false"); return SO_ZCChars; }
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static const ZCChars& GetMark(bool AB_Bool)
{
return AB_Bool ? GetMarkTrue() : GetMarkFalse();
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
public:
};
//////////////////////////////////////////////////////////////////////////
namespace ZNsView
{
class ZCViewLogData
{
public:
virtual void Log(const char* APC_LogData, ZTypLength AI_Length)
{
__for0(ZTypLength, i, AI_Length){std::cout<<APC_LogData[i];}
}/*
virtual void Log(const char* APC_LogData, ZTypLength AI_Length)*/
virtual void Log(const char* APC_LogData)
{ std::cout<<APC_LogData; }
virtual void Log(int AI_LogData){ std::cout<<AI_LogData; }
virtual void Log(long AL_LogData){ std::cout<<AL_LogData; }
virtual void Log(double AD_LogData){ std::cout<<AD_LogData; }
virtual void Log(char AC_LogData){ std::cout<<AC_LogData; }
virtual void Log(bool AB_LogData)
{
cout<<(AB_LogData ? "true" : "false");
}/*
virtual void Log(bool AB_LogData)*/
virtual void LogXmlAtt(const char* APC_LogData, ZTypLength AI_Length)
{
__for0(ZTypLength, i, AI_Length)
{
if(APC_LogData[i]=='&' ){cout<<"&amp;" ; continue;}
if(APC_LogData[i]=='\r'){cout<<"&#xA;" ; continue;}
if(APC_LogData[i]=='\n'){cout<<"&#xD;" ; continue;}
if(APC_LogData[i]=='\t'){cout<<"&#x9;" ; continue;}
if(APC_LogData[i]=='\"'){cout<<"&quot;"; continue;}
if(APC_LogData[i]=='>' ){cout<<"&gt;" ; continue;}
if(APC_LogData[i]=='<' ){cout<<"&lt;" ; continue;}
cout<<APC_LogData[i] ;
}/*
__for0(ZTypLength, i, AI_Length)*/
}/*
virtual void LogXmlAtt(const char* APC_LogData, ZTypLength AI_Length)*/
virtual void LogXmlAtt(const char* APC_LogData)
{
LogXmlAtt(APC_LogData, ZftLength(APC_LogData));
}/*
virtual void LogXmlAtt(const char* APC_LogData)*/
public:
};/*
class ZCViewLogData*/
}/*
namespace ZNsView*/
class ZCSngtLogData
{
public :
typedef ZNsView::ZCViewLogData ZCViewLogData;
private:
ZCViewLogData mo_ZCViewLogData;
ZCViewLogData* mp_ZCViewLogData;
private:
ZCSngtLogData() : mp_ZCViewLogData(&mo_ZCViewLogData){}
public :
static ZCSngtLogData& GetSngtObj()
{
static ZCSngtLogData SO_ZCSngtLogData; return SO_ZCSngtLogData;
}/*
static ZCSngtLogData& GetSngtObj()*/
static ZCViewLogData& GetSngtView()
{
return *GetSngtObj().mp_ZCViewLogData;
}/*
static ZCViewLogData& GetSngtView()*/
static void SetSngtView(ZCViewLogData& AR_ViewObj)
{
GetSngtObj().mp_ZCViewLogData = &AR_ViewObj ;
}/*
static void SetSngtView(ZCViewLogData& AR_ViewObj)*/
public :
static void Log(const char* APC_Log, ZTypLength AI_Length)
{
GetSngtView().Log(APC_Log, AI_Length);
}/*
static void Log(const char* APC_Log, ZTypLength AI_Length)*/
static void Log(const char* APC_LogData)
{
GetSngtView().Log( APC_LogData );
}/*
static void Log(const char* APC_LogData)*/
static void Log(int AI_LogData){ GetSngtView().Log(AI_LogData); }
static void Log(long AL_LogData){ GetSngtView().Log(AL_LogData); }
static void Log(double AD_LogData){ GetSngtView().Log(AD_LogData); }
static void Log(char AC_LogData){ GetSngtView().Log(AC_LogData); }
static void Log(bool AB_LogData){ GetSngtView().Log(AB_LogData); }
static void LogXmlAtt(const char* APC_LogData, ZTypLength AI_Length)
{
GetSngtView().LogXmlAtt(APC_LogData, AI_Length);
}/*
static void LogXmlAtt(const char* APC_LogData, ZTypLength AI_Length)*/
static void LogXmlAtt(const char* APC_LogData)
{
GetSngtView().LogXmlAtt(APC_LogData);
}/*
static void LogXmlAtt(const char* APC_LogData)*/
public :
ZCSngtLogData& operator()(const char* APC_Log, ZTypLength AI_Length)
{
ZCSngtLogData::Log(APC_Log, AI_Length); return *this;
}/*
ZCSngtLogData& operator()(const char* APC_Log, ZTypLength AI_Length)*/
ZCSngtLogData& operator()(const char* APC_LogData)
{
GetSngtView().Log( APC_LogData ); return *this;
}/*
ZCSngtLogData& operator()(const char* APC_LogData)*/
ZCSngtLogData& operator()(const ZCCharView& AR_View)
{
ZCSngtLogData::Log(AR_View.data(), AR_View.size()); return *this;
}/*
ZCSngtLogData& operator()(const ZCCharView& AR_View)*/
ZCSngtLogData& operator()(int AI_LogData){ GetSngtView().Log(AI_LogData); return *this; }
ZCSngtLogData& operator()(long AL_LogData){ GetSngtView().Log(AL_LogData); return *this; }
ZCSngtLogData& operator()(double AD_LogData){ GetSngtView().Log(AD_LogData); return *this; }
ZCSngtLogData& operator()(char AC_LogData){ GetSngtView().Log(AC_LogData); return *this; }
ZCSngtLogData& operator()(bool AB_LogData){ GetSngtView().Log(AB_LogData); return *this; }
ZCSngtLogData& Xa(const char* APC_LogData, ZTypLength AI_Length)
{
GetSngtView().LogXmlAtt(APC_LogData, AI_Length); return *this;
}/*
ZCSngtLogData& Xa(const char* APC_LogData, ZTypLength AI_Length)*/
ZCSngtLogData& Xa(const char* APC_LogData)
{
GetSngtView().LogXmlAtt(APC_LogData); return *this;
}/*
ZCSngtLogData& Xa(const char* APC_LogData)*/
public :
};/*
class ZCSngtLogData*/
}/*
namespace ZNsMain*/
namespace ZNsCPP
{
using ZNsMain::IterEasyID;
/* 이 이름공간에는 ZNsMain 에 있는 라이브러리 보다 좀더 thread-safe
하거나 좀더 최적화된, 아니면 좀 더 gerneric 한 자료구조가 온다.
*/
namespace ZNsIFace
{
}/*
namespace ZNsIFace*/
namespace ZNsType
{
}/*
namespace ZNsType*/
namespace ZNsEnum
{
}/*
namespace ZNsEnum*/
namespace ZNsConst
{
}/*
namespace ZNsConst*/
}/*
namespace ZNsCPP */
/* 함수 안에서 함수를 정의할 필요가 있을 때, struct 를 이용하여 함수를 정의하는 매크로. -- 2015-09-06 05:20:00 */
#define _FUNC_IN_FUNC_START_(ZstClassName) struct ZstClassName{static void Exec
#define _FUNC_IN_FUNC_CLOSE_(ZstClassName) };
#define _FUNC_IN_FUNC_RETURN_START_(ZstClassName, ZTypeReturn) struct ZstClassName{static ZTypeReturn Exec
#define _FUNC_IN_FUNC_RETURN_CLOSE_(ZstClassName, ZTypeReturn) };
#define _FFS_(ZstClassName) _FUNC_IN_FUNC_START_(ZstClassName)
#define _FFC_(ZstClassName) _FUNC_IN_FUNC_CLOSE_(ZstClassName)
#define _FFE_(ZstClassName) }; // E 문자는 END 의 뜻.
#define _FFRS_(ZstClassName, ZTypeReturn) _FUNC_IN_FUNC_RETURN_START_(ZstClassName, ZTypeReturn)
#define _FFRC_(ZstClassName, ZTypeReturn) _FUNC_IN_FUNC_RETURN_CLOSE_(ZstClassName, ZTypeReturn)
#define _FFRE_(ZstClassName) };
#define _FFF_(ZstClassName) ZstClassName::Exec
/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
■ _FUNC_IN_FUNC_START_ 관련 매크로 사용예.
#include<iostream>
using namespace ZNsMain;
int main()
{
_FUNC_IN_FUNC_START_(My)
(IntI ArgiShowCnt)
{
for(int i=0; i<ArgiShowCnt; ++i) cout<<"# Show My() In Func."<<endl;
}
_FUNC_IN_FUNC_CLOSE_(My)
_FUNC_IN_FUNC_RETURN_START_(My2, Int)
(IntI ArgiShowCnt)
{
for(int i=0; i<ArgiShowCnt; ++i) cout<<"# Show My() In Func."<<endl; return ArgiShowCnt;
}
_FUNC_IN_FUNC_RETURN_CLOSE_(My2, int)
_FFS_(My3)
(IntI ArgiShowCnt)
{
for(int i=0; i<ArgiShowCnt; ++i) cout<<"# Show My() In Func."<<endl; return ArgiShowCnt;
}
_FFC_(My3)
My ::Exec(3);
My2::Exec(3);
My3::Exec(3);
return 0;
}
-- 2015-09-06 17:21:00
CNetEx.H 의 HandleEvent 도 참고. -- 2015-09-06 17:43:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
■ 4.1 자동적으로 정의되는 심볼들
여러분은 여러분이 갖고 있는 버전의 gcc 가 -v 옵션을 붙임으로써
어떠한 심볼을 자동적으로 정의하는지 알아낼 수 있다.
예를 들어 본인의 것은 다음과 같다.
$ echo 'main(){printf("hello world\n");}' | gcc -E -v -
Reading specs from /usr/lib/gcc-lib/i486-box-linux/2.7.2/specs
gcc version 2.7.2
/usr/lib/gcc-lib/i486-box-linux/2.7.2/cpp -lang-c -v -undef
-D__GNUC__=2 -D__GNUC_MINOR__=7 -D__ELF__ -Dunix -Di386 -Dlinux
-D__ELF__ -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386
-D__linux -Asystem(unix) -Asystem(posix) -Acpu(i386)
-Amachine(i386) -D__i486__ -
--
현재 위 명령으로는 더 이상 매크로를 알 수 없는데, 아래 명령
echo . | gcc -dM -E -
혹은
gcc -dM -E - < /dev/null
을 이용하면 된다.
ex) gcc -dM -E - < /dev/null | grep 'linux'
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1
ex) echo . | gcc -dM -E - | grep 'unix'
#define __unix 1
#define __unix__ 1
#define unix 1
이것은 ymir 님의 답변이었다. ☞ http://kldp.org/node/121720
-- 2011-03-03 13:21:00
■ 각 OS 별 매크로
리눅스 : #define __linux__ 1
HP : #define __hpux__ 1
sun : #define __sun__ 1
IRIX : #define __mips__ 1
TRUE64 : #define __alpha__ 1
FreeBSD: #define __FreeBSD_cc_version 800001
#define __VERSION__ "4.2.1 20070719 [FreeBSD]"
#define __FreeBSD__ 8
AIX : #define _AIX 1
#define _AIX32 1
#define _AIX41 1
#define _AIX43 1
#define _AIX51 1
#define _AIX52 1
#define _AIX53 1
-- 2011-03-12 16:17:00
■ 만약 여러분의 코드가 리눅스에만 관계되는 코드라면, 다음과 같이 해주는 것이 좋다.
#ifdef __linux__
// ... funky stuff ...
#endif // __linux__
__linux__라는 이름을 사용하라. linux 가 아니다.
후자가 정의되어 있기는 하지만 POSIX 규격에는 맞지 않기 때문이다.
■ 각 OS 별 Shared Library PATH 환경 변수 (2012-04-08 19:25:00)
※ http://cafe335.daum.net/_c21_/bbs_search_read?grpid=TzUN&fldid=DUnV&contentval=0000szzzzzzzzzzzzzzzzzzzzzzzzz&nenc=&fenc=&q=gulim.ttf&nil_profile=cafetop&nil_menu=sch_updw
AIX LIBPATH, LD_LIBRARY_PATH
OS/2 LIBPATH
Windows NT/95 PATH
Solaris/Linux LD_LIBRARY_PATH
HP/UX SHLIB_PATH, LD_LIBRARY_PATH (64 bit only)
ex) export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/userJNI/lib
※ HP-UX 에서 Shared Library 의 확장자는 sl 이다.
□ SUN일 경우 LD_LIBRARY_PATH 를 HP-UX 일 경우 SHLIB_PATH 를, AIX 일 경우 LIBPATH 를 사용합니다.
□ 참고 : HP에서 LD_LIBRARY_PATH 는 64비트 환경에서만 작동함. 확장자 명도 sl 임
□ chatr 명령을 사용하면 SHLIB_PATH가 사용 중인 프로그램에 대해 "사용 불가능" 상태인지 여부를 판별할 수 있습니다.
다음 예는 /opt/mqm/samp/bin/amqsput 프로그램에 사용되는 chatr 명령입니다.
chatr /opt/mqm/samp/bin/amqsput
프로그램이 SHLIB_PATH를 사용하는지 확인하려면 다음 명령을 실행하십시오.
chatr +s enable /opt/mqm/samp/bin/amqsput
SHLIB_PATH 가 환경에 정의되어 있으며 /usr/lib 디렉토리를 포함하는지 확인하십시오(echo $SHLIB_PATH).
경로를 정의하려면 다음을 실행하십시오.
export SHLIB_PATH=$SHLIB_PATH:/usr/lib
□ 다음은 어플리케이션에 대해 SHLIB_PATH 또는 chatr +s 가 조사되어야 함을 지시하는 어플리케이션 오류입니다.
◆ IBM WebSphere MQ 프로그램 runmqsc
runmqsc D11LHP.QM
5724-B41 (C) Copyright IBM Corp. 1994, 2002. ALL RIGHTS RESERVED.
Starting MQSC for queue manager D11LHP.QM.
/usr/lib/dld.sl: Can't find path for shared library: libstream.2
/usr/lib/dld.sl: No such file or directory
AMQ9508: Program cannot connect to the queue manager.
No MQSC commands read.
No commands have a syntax error.
All valid MQSC commands were processed.
◆ IBM WebSphere MQ 샘플 어플리케이션이 권한 부여 오류를 표시함(이유 코드 2217)
amqsput QL_D11LHP_B02KLNX.U1.I D11LHP.QM
Sample AMQSPUT0 start
target queue is QL_D11LHP_B02KLNX.U1.I
MQOPEN ended with reason code 2217
unable to open queue for output
Sample AMQSPUT0 end
◆ --
□ --
■ 'new operator' 와 'operator new' Programming
(2007/04/03 16:20)
http://blog.naver.com/cppis/60036113050
bugmail 에게 More Effective C++을 빌려 보던 중 일반적으로 많이 쓰던 new 와 delete 에 대해
서 소홀하게 넘어갔던 부분을 보고 정리를 하게 되었습니다. 저와 마찬가지로 많은 사람들이
new operator 와 operator new
를 혼동하시는 것 같아서 간단히 정리해봤습니다.
new operator 는 C++ 에서 제공하는 연산으로 두 가지 동작을 수행합니다.
-- 먼저, 요청한 타입 크기의 메모리를 할당하고, 다음으로,
-- 타입 인스턴스의 생성자를 호출하여 초기화를 수행합니다.
C++ 컴파일러는 new operator 를 위의 내용처럼 코드로 만들어냅니다. operator new 란 바로 요
청한 타입 크기의 메모리를 할당하는 동작을 수행하는 Operator 입니다.
따라서 위의 내용을 다시 요약하면, new operator 는
operator new 로 메모리를 할당하고, object 의 생성자를 호출하는 동작을 한다.
라고 할 수 있습니다.
operator new 는 Overload 될 수 있기 때문에 사용자가 자신만의 'operator new'를 정의할 수
있습니다. 또, 항상 void* 를 리턴하고, 첫번째 인자로 size_t 를 받습니다. new operator 의
문법은 다음과 같습니다.
[::] new [placement] new-type-name [new-initializer]
[::] new [placement] ( type-name ) [new-initializer]
- placement
new 를 overload 할 때 추가로 인자를 전달하는 방법을 제공합니다. 예를 들어, 표준 C++ 라이
브러리의 default new는 메모리가 바닥나면 exception 을 throw 합니다. Overload 된 new 는 대
신 NULL 을 리턴하는데, Overload 된 new 는 다음과 같이 정의되어 있습니다.
struct nothrow_t {};
extern const nothrow_t nothrow;
void *operator new throw() (size_t, const nothrow_t& );
그리고 다음과 같이 호출될 수 있습니다
foo *fp = new (nothrow) foo;
if( !fp ) {
// Out of memory를 처리합니다.
}
- type-name
할당할 타입을 명시합니다. type-name 은 built-in 이거나 user-defined 타입일 수 있습니다.
- initializer
초기화할 object 를 위한 값을 제공합니다. initializer 는 object 배열을 할당하기 위해서는
사용될 수 없습니다. new operator 는 default 생성자를 가지고 있는 object 의 배열만을 생성
할 수 있습니다.
new 중에서 Placement-new 는 메모리를 전혀 할당하지 않고, object 의 생성자를 호출하기 위해
서만 사용됩니다. Placement-new 는 일반적으로 다음과 같이 정의되어 있습니다.
inline void *operator new( size_t, void* p )
{
return p;
}
Automatic Variable 을 제외한다면 Placement-new 는 object 의 생성자를 호출할 수 있는 유일
한 방법입니다. new 와 쌍(Pair)인 delete도 이와 비슷합니다.
'delete operator'는 object 의 소멸자를 호출하고,
'operator delete'를 호출하여 메모리를 해제하는 동작을 수행합니다.
reference
- More Effective C++
- MSDN
■ Placement-New Requires Heap-Allocated Buffers
The placement-new operator constructs an object on a pre-allocated buffer. The pre-allocated buffer has to be allocated
on the heap.
char *pbuff = new char[1024]; // heap allocation using plain new
Person *p = new (pbuff) Person; // placement new uses a pre-allocated buffer
You may be tempted to use a buffer allocated on the stack to avoid the need of explicitly freeing it:
char pbuff [1024]; //bad idea: stack allocation instead of heap
Person *p = new ( pbuff ) Person; //undefined behavior
However, the pre-allocated buffer must comply with certain alignment constraints required by C++. Memory allocated
on the heap is guaranteed to comply with these requirements. Stack memory, on the other hand, may not be properly aligned,
and hence using it for that purpose yields undefined behavior
-- heap 에서는 정렬 제한이 정확히 지켜지지만
-- stack 에서는 정렬 제한이 지켜지지 않을 수 있다.
-- (아마도 위에서 버퍼 pbuff[1024] 의 주소 pbuff 이 heap 기준에 어긋나는,
-- 정렬되지 않은 주소일 수도 있다는 뜻인 듯 하다.) 2008-10-26
http://kldp.org/node/76375
http://www.devx.com/tips/Tip/12756
■ 어떤 클래스에 멤버변수를 추가하게 되면 생성자에서 초기화해야 하는지 한 번 더 생각하자. 생
성자에서 초기화를 빠트려서 애먹은 적이 있었다.
■ 클래스가 어떤 주기적인 상태를 가지는 경우, 한 주기가 끝날 때마다 내부 버퍼를 정확하게 초
기화하자. 각 포탈이나 신문사의 검색페이지에서 검색결과를 가져와 해석할 때, 각 검색 페이지
의 각 리스트 항목의 데이타 추출이 끝나면, 다음 리스트 항목을 추출할 때 관련 버퍼를 초기화
해 주어야 했는데 여기에 실수가 있어서, 추출시에 이전 정보가 자꾸 들러 붙었다. 처음에는 이
게 오류인 줄 알았고 들러붙은 것이 이전 정보인지도 몰랐다. 알고보니 다음 항목 추출 전에 관
련 버퍼를 초기화 안한 실수였다.
■ 가상함수를 상속클래스에서 재정의할 때는 기본값 인수 갯수도 동일해야 한다.
virtual CIOCP ::SendPacket(HANDLE SocketID,const char* ApcData=0,int AI_Length=0,CSendBuffList* AP_CSendBuffList=0) // 1) 번코드
virtual CIOCPEx::SendPacket(HANDLE SocketID,const char* ApcData=0,int AI_Length=0) // 2) 번코드
1) 번 코드는 기반클래스의 가상 함수이고
2) 번 코드는 상속클래스의 재정의함수다. 그리고 아래의 코드에서
CIOCPEx VO_CIOCPEx;
CIOCP* VP_CIOCP=&VO_CIOCPEx;
VO_CIOCPEx->SendPacket((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<typename TTypeBase>
class CMy : public TTypeBase
{
public:
void Init();
void Fini();
};
위 클래스 템플릿을 상속해서 CMy2 를 만든다음
clear() 멤버를 추가한다고 하자. 그러면
class CMy2 : public CMy<CBaseClass>
{
public:
void clear();
};
위외 같은 형태가 될텐데, 이때 clear() 멤버를 정의하면서 기반 클래스인 CMy<CBaseClass> 의 멤버변수와 함수를 어떻게
사용하겠는지 한 번쯤 생각을 하게 된다. 그런데 CMy<CBaseClass> 의 기반클래스인 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<TString>
클래스에서 멤버 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<typename TParent>
class A
{
public:
void UseB1(){static_cast<TParent*>(this)->GetObjB1().CallFunc();}
void UseB2(){static_cast<TParent*>(this)->GetObjB2().CallFunc();}
void UseB3(){static_cast<TParent*>(this)->GetObjB3().CallFunc();}
void UseExB1(TParent& ArCParent){static_cast<TParent*>(this)->GetObjB1().CallFunc(ArCParent);}
void UseExB2(TParent& ArCParent){static_cast<TParent*>(this)->GetObjB2().CallFunc(ArCParent);}
void UseExB3(TParent& ArCParent){static_cast<TParent*>(this)->GetObjB3().CallFunc(ArCParent);}
};
class A2 : public A<A2>
{
public:
class B1{public:void CallFunc() {cout<<"Call B1::CallFunc()"<<endl;}
void CallFunc(A2& ArA2){cout<<"Call B1::CallFunc(A2)"<<endl;}};
class B2{public:void CallFunc() {cout<<"Call B2::CallFunc()"<<endl;}
void CallFunc(A2& ArA2){cout<<"Call B2::CallFunc(A2)"<<endl;}};
class B3{public:void CallFunc() {cout<<"Call B3::CallFunc()"<<endl;}
void CallFunc(A2& ArA2){cout<<"Call B3::CallFunc(A2)"<<endl;}};
private:
B1 b1;
B2 b2;
B3 b3;
public:
B1 GetObjB1(){return b1;}
B2 GetObjB2(){return b2;}
B3 GetObjB3(){return b3;}
void UseExB1(){A<A2>::UseExB1(*this);}
void UseExB2(){A<A2>::UseExB2(*this);}
void UseExB3(){A<A2>::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
■ 함수 템플릿의 템플릿 인수가 템플릿인 경우에는 어떻게 전문화하는지, ZtCStringEx.H 의 ZNsMain::ZftMoveFast() 의 ZtCStringBase<>
템플릿 전문화에 그 예가 있다.
-- 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<typename T> struct CShow
{
static void Show(){cout<<"## show : T="<<typeid(T).name()<<endl;}
template<typename T2> static void Show2(T2);
};
template<typename T> template<typename T2>
void CShow<T>::Show2(T2){cout<<"## show : T2="<<typeid(T2).name()<<endl;}
-- 2013-05-06
■ main 함수의 반환값을 확인할 수 있다. 윈도우에서는 커맨드 라인에
echo %ERRORLEVEL%
명령을 입력하면 그 결과를 확인할 수 있고, 리눅스에서는 커맨드 라인에
echo $?
를 입력하면, 그 결과를 확인할 수 있다
☞ http://bcode.tistory.com/5
-- 2011-03-03 22:43:00
■ 아래 my1 과 my2 의 자료형은 서로 다르다.
char my1[]="C++ World1";
const char* my2 ="C++ World2";
cout<<typeid(my1).name()<<endl;
cout<<typeid(my2).name()<<endl;
my1 => char [11]
my2 => char const * __ptr64
-- 2025-08-21 12:42
■ 코드 리뷰 체크 리스트 예. (김익환/전규현 著 '소프트웨어 개발의 모든 것' 167 page)
□ 리뷰자가 리뷰하고 있는 소스 코드를 이해하고 있는가?
□ 소스 코드가 회사의 코딩 표준을 준수하고 있는가?
□ 함수의 모든 인수가 입력용인지 출력용인지 명시되어 있는가?
□ 모든 복잡한 알고리즘에 대하여 설명이 있는가?
□ 주석 처리되어 사용되지 않은 소스 코드에 대하여, 주석 처리를 한 이유가 설명되어 있는가?
□ 정상적인 값이나 범위를 확인하기 위해서, 모든 데이타에 대하여 Assertion 을 사용하고 있는가?
□ 함수에서 리턴으로 나가는 모든 곳에서, 모든 에러를 적절히 처리하고 있는가?
□ 모든 Exception 을 제대로 처리하고 있는가?
□ 할당된 메모리를 모두 해제하고 있는가?
□ 모든 전역 변수가 thread-safe 한가?
□ 동시에 여러 쓰레드에서 액세스되는 모든 object 가 thread-safe 한가?
□ 모든 Lock 은 얻어진 순서대로 해제되고 있는가?
□ 무한 루프가 될만한 소스 코드는 없는가?
□ 소스 코드가 속도, 메모리 사용에 무리는 없는가?
□ 모든 배열의 인덱스가 배열의 크기를 넘어서 참조하지 않는가?
□ 모든 변수는 사용하기 전에 초기화하고 있는가?
□ 이미 존재하는 API 를 사용해서 대체할 수 있는 부분이 있는가?
여기에 멀티 쓰레드에 관련된 항목만 뽑아내고, 몇 가지를 더 추가하자.
□ 모든 전역 변수가 thread-safe 한가?
□ 동시에 여러 쓰레드에서 액세스되는 모든 object 가 thread-safe 한가?
□ 모든 Lock 은 얻어진 순서대로 해제되고 있는가?
□ 무한 루프가 될만한 소스 코드는 없는가?
□ 동기화 영역에서 보호되는 class 의 멤버 변수는, 해당 동기화 object 와 가까운 곳에 선언되어 있는가?
멀리 떨어져서 선언되어 있다면, 아주 골치아픈 문제가 발생할 수 있다. 이것은 아는 사람만 알 것이다.
□ 동기화 영역에서 수행되는 Flow 가 '정밀'하게 정리되어 있는가?
-- 2011-04-16 15:39:00
□ DB 에서 ERD 가 있는 것처럼, 클래스 설계도나 근거 자료가 있는가?
-- 2011-04-17 12:08:00
□ 문자열의 길이와 파일 길이, 소켓 송수신 버퍼 길이를 표현하는 정수가 적절하게 typedef 되어 있고, 일관성있게 사용
되고 있는가?
-- 2011-05-09 21:10:00
□ 소켓 송수신 버퍼 길이를 표현하는 정수의 범위를 넘어서 송수신하는 경우는 없는가.
□ 정수의 overflow 나 underflow 는 없는가.
-- 2011-05-19 09:14:00
□ 소켓 송신 시에 vector 와 관련 자료구조를 적절히 사용하여, 문자열 object 가 송신 버퍼 리스트에 전달될 때, 송신
데이타의 복사가 최소화되도록 하였는가. 가급적 문자열 object 의 문자열 메모리가 송신 버퍼 리스트로 (복사가 아닌)
이동되는 것이 좋으며, 때에 따라 송신 버퍼 리스트의 각 원소를 고정 길이 문자 배열로 구현하는 것도 좋을 수 있다.
-- 2013-06-08 15:25:00
□ 작업 구간이 일부 겹치는 경우, 동적 메모리를 사용하는 멤버 변수에 접근할 때, 적절한 동기화가 되었는가.
-- 2013-06-09 18:34:00
□ 스케줄러 쓰레드에 스케줄이 다중으로 등록되는 일은 없는가. '동해기계항공'에서 장비 모니터링 프로그램을 만들어
줄 때, 스케줄이 점점 다중 등록되어서 시간 주기가 짧아지고 로그도 점점 커지는 경우가 있었다.
또한 ABA 가 문제를 발생시키는 경우에도, 정확히 처리가 되는지 점검해야 한다.
-- 2013-06-21 19:41:00
□ 하나의 object 가 다른 작업 쓰레드에서 접근하고 사용 중일 때, 해당 object 가 다른 요인에 의해서 소멸되지 않도
록 되어 있는가. 이 때, 아래에서 설명하는 '참조 카운팅 종료'가 적용되면 좋다.
-- 2013-06-23 19:30:00
□ new[] 로 생성된 것은 delete[] 로 해제되고 있는가. 이것은 MainHead.H 의 2013-07-09 23:32:00 일자 주석을 참고.
리눅스에서라면 valgrind 로 검사하는 것도 좋다. 여기까지 오는데 참 기나긴 시간이 흐르지 않았는가.
-- 2013-07-09 23:44:00
new 나 new[] 로 생성되는 일이 아예 없어야겠다. 즉 ZtCObjNew<> 나 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
■ 'char 의 int 확장에 따른 문제의 코드'
아래 함수에서
int ZtCMainChars<>::Minus(TypeCharC*, TypeCharC*, TypeLength, TypeLength)
return 문을
return VC_Minus; // VC_Minus 는 *(VP_Left-1)-*(VP_Right-1)
에서
return int(*(VP_Left-1))-int(*(VP_Right-1));
로 고쳤다. 컴파일러에 따라, 음수 char 을 int 로 확장하면 양수(+)가 될 수 있는 것이다. 이
것을 언제 알았냐면, LG CNS 에서 충전기 프로젝트를 할 때다. 그때 ELDK 4.0 tool chain 의
컴파일러를 사용했는데, NsUtility::CLoadSimUrlConfig_T<> 으로 설정 파일을 읽어들일 때, 자
꾸 몇몇 설정값을 인식하지 못하고 있었다. CLoadSimUrlConfig_T<> 은 ns1.cppschool.com 과
ns2.cppschool.com 에서 테스트된 클래스이다. 그런데도 이런 문제가 발생한 것이다. 이전에
Hemose 의 메신저 서버를 만들 때에도 이런 문제가 있었는데, 풀리지 않을 것 같은 문제로 여
기고 매우 긴장하고 있었다. CObjAVL.H 파일의 AddKey() 함수의 비교하는 부분에 cout 으로
출력해 보니까, 항상 '>' 조건이 아닌가. 그래서 ZtCMainChars<>::Minus() 함수까지 파들어가
리턴하는 값을 보니까 항상 양수였다! 이럴수가, 왼쪽이 작으면 음수를 리턴해야 한다. 그런
데 항상 양수라니. 좀 더 조사해 보니까, 해당 컴파일러의, char 의 int 형 확장에 따른 문제
였고 코드를 위처럼 고치게 되었다.
-- 2011-12-29 17:35:00
■ g++ 에서 아래가 컴파일이 안 된다.
#include<iostream>
using namespace std;
int Main(int AI_ArgCnt=0, const char* APP_ArgVal[]=0)
{
cout<<"Call Main()"<<endl; return 0;
}
/////////////////////////////////////////////////////
int main(int AI_ArgCnt, char* APP_ArgVal[])
{
return Main(AI_ArgCnt, APP_ArgVal);
}
///////////////////////////////////////////
□ mingw 컴파일
g++.exe -o g++_test_000.exe g++_test_000.cpp -I../
Administrator@q381-2673 UCRT64 /e/my_CPP/ZCpp/ZCppMainTest
# g++.exe -o g++_test_000.exe g++_test_000.cpp -I../
g++_test_000.cpp: In function 'int main(int, char**)':
g++_test_000.cpp:18:28: error: invalid conversion from 'char**' to 'const cha
r**' [-fpermissive]
18 | return Main(AI_ArgCnt, APP_ArgVal);
| ^~~~~~~~~~
| |
| char**
g++_test_000.cpp:9:39: note: initializing argument 2 of 'int Main(int, cons
t char**)'
9 | int Main(int AI_ArgCnt=0, const char* APP_ArgVal[]=0)
| ~~~~~~~~~~~~^~~~~~~~~~~~~~
Administrator@q381-2673 UCRT64 /e/my_CPP/ZCpp/ZCppMainTest
# g++ --version
g++.exe (Rev2, Built by MSYS2 project) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
□ 해결 방법-1
#include<iostream>
using namespace std;
int Main(int AI_ArgCnt=0, const char* const APP_ArgVal[]=0)
{
cout<<"Call Main()"<<endl; return 0;
}
///////////////////////////////////////////////////////////
int main(int AI_ArgCnt, char* APP_ArgVal[])
{
return Main(AI_ArgCnt, APP_ArgVal);
}
///////////////////////////////////////////
□ 해결 방법-2
#include<iostream>
using namespace std;
int Main(int AI_ArgCnt=0, char* const APP_ArgVal[]=0)
{
cout<<"Call Main()"<<endl; return 0;
}
/////////////////////////////////////////////////////
int main(int AI_ArgCnt, char* APP_ArgVal[])
{
return Main(AI_ArgCnt, (const char**)APP_ArgVal);
}
///////////////////////////////////////////
-- 2025-08-25 00:56
■ 'char 의 int 확장에 따른 문제의 코드'
아래 함수에서
int ZtCMainChars<>::Minus(TypeCharC*, TypeCharC*, TypeLength, TypeLength)
return 문을
return VC_Minus; // VC_Minus 는 *(VP_Left-1)-*(VP_Right-1)
에서
return int(*(VP_Left-1))-int(*(VP_Right-1));
로 고쳤다. 컴파일러에 따라, 음수 char 을 int 로 확장하면 양수(+)가 될 수 있는 것이다. 이
것을 언제 알았냐면, LG CNS 에서 충전기 프로젝트를 할 때다. 그때 ELDK 4.0 tool chain 의
컴파일러를 사용했는데, NsUtility::CLoadSimUrlConfig_T<> 으로 설정 파일을 읽어들일 때, 자
꾸 몇몇 설정값을 인식하지 못하고 있었다. CLoadSimUrlConfig_T<> 은 ns1.cppschool.com 과
ns2.cppschool.com 에서 테스트된 클래스이다. 그런데도 이런 문제가 발생한 것이다. 이전에
Hemose 의 메신저 서버를 만들 때에도 이런 문제가 있었는데, 풀리지 않을 것 같은 문제로 여
기고 매우 긴장하고 있었다. CObjAVL.H 파일의 AddKey() 함수의 비교하는 부분에 cout 으로
출력해 보니까, 항상 '>' 조건이 아닌가. 그래서 ZtCMainChars<>::Minus() 함수까지 파들어가
리턴하는 값을 보니까 항상 양수였다! 이럴수가, 왼쪽이 작으면 음수를 리턴해야 한다. 그런
데 항상 양수라니. 좀 더 조사해 보니까, 해당 컴파일러의, char 의 int 형 확장에 따른 문제
였고 코드를 위처럼 고치게 되었다.
-- 2011-12-29 17:35:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
#endif //__ZCPPMAIIN_ZMAINHEAD_H__