11271 lines
418 KiB
C++
11271 lines
418 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(MainObj, IterVar, SizeVar) \
|
|
{ \
|
|
typedef ZTypLength IterTypeSize ; \
|
|
ZNsMain::IterEasyID IterVar = MainObj.ItHID(); \
|
|
\
|
|
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
|
|
|
|
#define _FOR_ITER_EASY_CLOSE0(MainObj, IterVar, SizeVar) \
|
|
MainObj.ItNext(IterVar); } \
|
|
}
|
|
|
|
#define _FOR_ITER_EASY_START0_C(MainObj, IterVar, SizeVar) \
|
|
{ \
|
|
typedef ZTypLength IterTypeSize ; \
|
|
ZNsMain::IterEasyIDc IterVar = MainObj.ItHIDc(); \
|
|
\
|
|
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
|
|
|
|
#define _FOR_ITER_EASY_CLOSE0_C(MainObj, IterVar, SizeVar) \
|
|
MainObj.ItNext(IterVar); } \
|
|
}
|
|
|
|
|
|
#define _FOR_ITER_EASY_START0_R(MainObj, IterVar, SizeVar) \
|
|
{ \
|
|
typedef ZTypLength IterTypeSize ; \
|
|
ZNsMain::IterEasyID IterVar = MainObj.ItTID(); \
|
|
\
|
|
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
|
|
|
|
#define _FOR_ITER_EASY_CLOSE0_R(MainObj, IterVar, SizeVar) \
|
|
MainObj.ItPrev(IterVar); } \
|
|
}
|
|
|
|
#define _FOR_ITER_EASY_START0_RC(MainObj, IterVar, SizeVar) \
|
|
{ \
|
|
typedef ZTypLength IterTypeSize ; \
|
|
ZNsMain::IterEasyIDc IterVar = MainObj.ItTIDc(); \
|
|
\
|
|
for(IterTypeSize SizeVar=0; SizeVar<MainObj.size(); ++SizeVar){
|
|
|
|
#define _FOR_ITER_EASY_CLOSE0_RC(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 (myList, VH_NowIter, i)
|
|
{
|
|
cout<<"# list : "<<myList.ItD(VH_NowIter)<<endl;
|
|
}
|
|
_FOR_ITER_EASY_CLOSE0 (myList, VH_NowIter, i)
|
|
|
|
_FOR_ITER_EASY_START0_RC(myList, VH_NowIter, i)
|
|
{
|
|
cout<<"# list rev const: "<<myList.ItD(VH_NowIter)<<endl;
|
|
}
|
|
_FOR_ITER_EASY_CLOSE0_RC(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 #################################################*/
|
|
|
|
|
|
/* 참조 전문화 */
|
|
template<typename TType>
|
|
class ZtCCheckRef<TType&> /*#######################################*/
|
|
{
|
|
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<TType&> #########################################*/
|
|
|
|
|
|
/* 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> ////////////////////*/
|
|
|
|
|
|
|
|
template< typename TTypeNow, typename TTypeNextChain
|
|
>
|
|
class ZtCTypeChain ///////////////////////////////////
|
|
{
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
typedef ZtCTypeChain TypeChainNow ;
|
|
typedef TTypeNextChain TypeChainNext ;
|
|
/************************************************************/
|
|
typedef typename TypeChainNext::TypeData TypeNext ;
|
|
/************************************************************/
|
|
enum{ZETypeNo = TypeChainNext::ZETypeNo+1};
|
|
enum{ZEBoolNext = 1 };
|
|
public:
|
|
static ZTypIntE Size(){return ZETypeNo;}
|
|
static ZTypIntE size(){return ZETypeNo;}
|
|
public:
|
|
|
|
/*//////////////////////////////////////////////
|
|
|
|
■ static 함수는 template 이 될 수 없으므로,
|
|
내포 class template 으로 해결한다.
|
|
|
|
-- 2025-10-17 22:09
|
|
|
|
//////////////////////////////////////////////*/
|
|
|
|
template<typename TViewChain> class ZtCIterChain
|
|
{
|
|
public:
|
|
static void IterHead(TViewChain AO_CView)
|
|
{
|
|
AO_CView.template OnMeetType<TypeChainNow>();
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template
|
|
ZtCIterChain<TViewChain>::IterHead(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
static void IterHead(TViewChain AO_CView)*/
|
|
static void IterTail(TViewChain AO_CView)
|
|
{
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template
|
|
ZtCIterChain<TViewChain>::IterTail(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
|
|
AO_CView.template OnMeetType<TypeChainNow>();
|
|
}/*
|
|
static void IterTail(TViewChain AO_CView)*/
|
|
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetType<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/*************************************************/
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template ZtCIterChain<TViewChain>::
|
|
template IterHead<TTypeHelp>(AO_CView, AO_TypeHelp) ;
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template ZtCIterChain<TViewChain>::
|
|
template IterTail<TTypeHelp>(AO_CView, AO_TypeHelp) ;
|
|
}
|
|
AO_CView.template OnMeetType<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/*************************************************/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
public:
|
|
};/*
|
|
template<typename TViewChain> class ZtCIterChain*/
|
|
|
|
public:
|
|
};/*
|
|
template< typename TTypeNow, typename TTypeNextChain
|
|
>
|
|
class ZtCTypeChain /////////////////////////////////*/
|
|
|
|
|
|
template<typename TTypeNow> class ZtCTypeChain<TTypeNow, ZCEmpty>
|
|
{
|
|
public :
|
|
/************************************************************/
|
|
typedef ZtCTypeChain <TTypeNow, ZCEmpty> ZCTypeChain;
|
|
/************************************************************/
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
public :
|
|
typedef ZCTypeChain TypeChainNow ;
|
|
typedef ZCTypeChain TypeChainNext;
|
|
typedef ZCEmpty TypeNext ;
|
|
public :
|
|
enum{ZETypeNo = 1};
|
|
enum{ZEBoolNext = 0};
|
|
public:
|
|
static ZTypIntE Size(){return ZETypeNo;}
|
|
static ZTypIntE size(){return ZETypeNo;}
|
|
public:
|
|
|
|
template<typename TViewChain> class ZtCIterChain
|
|
{
|
|
public:
|
|
static void IterHead(TViewChain AO_CView)
|
|
{ AO_CView.template OnMeetType<TypeChainNow>(); }
|
|
static void IterTail(TViewChain AO_CView)
|
|
{ AO_CView.template OnMeetType<TypeChainNow>(); }
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
// AO_CView 은 AO_TypeHelp 와 달리 ZtCCheckRef 를
|
|
// 적용하지 않는다. 외부에서 ZtCIterChain<SomeView>
|
|
// 처럼 접근하면서, SomeView 의 자료형을 지정하고 있다.
|
|
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetType<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) );
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
/*****************************************************************/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetType<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
public:
|
|
};/*
|
|
template<typename TViewChain> class ZtCIterChain*/
|
|
};/*
|
|
template<typename TTypeNow> class ZtCTypeChain<TTypeNow, ZCEmpty>*/
|
|
|
|
|
|
template<typename TTmplChain, typename TTypeView>
|
|
void ZftIterTypeChainHead(TTypeView AO_CView)
|
|
{
|
|
AO_CView.template OnMeetType<TTmplChain>();
|
|
|
|
if(TTmplChain::ZEBoolNext>0)
|
|
{
|
|
typedef typename
|
|
TTmplChain::TypeChainNext TypeChainNext;
|
|
|
|
ZftIterTypeChainHead<TypeChainNext, TTypeView>(AO_CView);
|
|
}/*
|
|
if(TTmplChain::ZEBoolNext>0)*/
|
|
}/*
|
|
template<typename TTmplChain, typename TTypeView>
|
|
void ZftIterTypeChainHead(TTypeView AO_CView)
|
|
*/
|
|
template<typename TTmplChain, typename TTypeView>
|
|
void ZftIterTypeChainTail(TTypeView AO_CView)
|
|
{
|
|
if(TTmplChain::ZEBoolNext>0)
|
|
{
|
|
typedef typename
|
|
TTmplChain::TypeChainNext TypeChainNext;
|
|
|
|
ZftIterTypeChainTail<TypeChainNext, TTypeView>(AO_CView);
|
|
}/*
|
|
if(TTmplChain::ZEBoolNext>0)*/
|
|
|
|
AO_CView.template OnMeetType<TTmplChain>();
|
|
}/*
|
|
template<typename TTmplChain, typename TTypeView>
|
|
void ZftIterTypeChainTail(TTypeView AO_CView)
|
|
*/
|
|
|
|
|
|
template
|
|
<typename TTmplChain, typename TTypeView, typename TTypeHelp>
|
|
void ZftIterTypeChainHead
|
|
(TTypeView AO_CView, TTypeHelp AO_TypeHelp)
|
|
/*#############################################################*/
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetType<TTmplChain, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) );
|
|
|
|
if(TTmplChain::ZEBoolNext>0)
|
|
{
|
|
typedef typename
|
|
TTmplChain::TypeChainNext TypeChainNext;
|
|
|
|
ZftIterTypeChainHead
|
|
<TypeChainNext, TTypeView, TTypeHelp>
|
|
(AO_CView, AO_TypeHelp);
|
|
}/*
|
|
if(TTmplChain::ZEBoolNext>0)*/
|
|
}/*
|
|
template
|
|
<typename TTmplChain, typename TTypeView, typename TTypeHelp>
|
|
void ZftIterTypeChainHead
|
|
(TTypeView AO_CView, TTypeHelp AO_TypeHelp)
|
|
###############################################################*/
|
|
|
|
|
|
template
|
|
<typename TTmplChain, typename TTypeView, typename TTypeHelp>
|
|
void ZftIterTypeChainTail
|
|
(TTypeView AO_CView, TTypeHelp AO_TypeHelp)
|
|
/*#############################################################*/
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
if(TTmplChain::ZEBoolNext>0)
|
|
{
|
|
typedef typename
|
|
TTmplChain::TypeChainNext TypeChainNext;
|
|
|
|
ZftIterTypeChainTail
|
|
<TypeChainNext, TTypeView, TTypeHelp>
|
|
(AO_CView, AO_TypeHelp);
|
|
}/*
|
|
if(TTmplChain::ZEBoolNext>0)*/
|
|
|
|
AO_CView.template OnMeetType<TTmplChain, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) );
|
|
}/*
|
|
template
|
|
<typename TTmplChain, typename TTypeView, typename TTypeHelp>
|
|
void ZftIterTypeChainTail
|
|
(TTypeView AO_CView, TTypeHelp AO_TypeHelp)
|
|
###############################################################*/
|
|
|
|
|
|
|
|
/*////////////////////////////////////////////////////////////////
|
|
|
|
■ ZtCTypeChain 예제.
|
|
|
|
|
|
using namespace ZNsMain;
|
|
|
|
|
|
class ZCTypeView
|
|
{
|
|
public:
|
|
|
|
template<typename TTypChain> void OnMeetType()
|
|
{
|
|
cout<<TTypChain::ZETypeNo<<" : "<<typeid(typename TTypChain::TypeData).name()<<endl;
|
|
}
|
|
template<typename TTypChain, typename TTypHelp> void OnMeetType(int& AR_CallNo)
|
|
{
|
|
cout<<"* Call No="<<++AR_CallNo<<" : "<<TTypChain::ZETypeNo<<" : "<<typeid(typename TTypChain::TypeData).name()<<endl;
|
|
}
|
|
// 위 함수에서 형식적으로 template parameter 를, TTypChain 와 TTypHelp
|
|
// 2 개를 받고 있음에 주의. 물론 TTypHelp 를 이용한 아래 선언도 가능하지만
|
|
// OnMeetType(TTypHelp& AR_CallNo)
|
|
// 아래가 더 명시적이다.
|
|
// OnMeetType(int& AR_CallNo)
|
|
};
|
|
|
|
int main()
|
|
{
|
|
typedef ZtCTypeChain
|
|
<
|
|
double , ZtCTypeChain<
|
|
int , ZtCTypeChain<
|
|
wchar_t, ZtCTypeChain<
|
|
char ,
|
|
|
|
ZCEmpty > > >
|
|
> ZCTypeChain; ZCTypeView VO_ZCTypeView;
|
|
|
|
int VI_CallNo = 0;
|
|
|
|
cout<<"tmpl chain size = "<<ZCTypeChain::Size()<<endl;
|
|
|
|
ZftIterTypeChainTail<ZCTypeChain, ZCTypeView&>(VO_ZCTypeView);
|
|
|
|
cout<<"************************************"<<endl;
|
|
//ZCTypeChain::ZtCIterChain<ZCTypeView >::IterHead(VO_ZCTypeView);
|
|
ZCTypeChain::ZtCIterChain<ZCTypeView&>::IterHead(VO_ZCTypeView);
|
|
cout<<"************************************"<<endl;
|
|
//ZCTypeChain::ZtCIterChain<ZCTypeView >::IterTail(VO_ZCTypeView);
|
|
ZCTypeChain::ZtCIterChain<ZCTypeView&>::IterTail(VO_ZCTypeView);
|
|
|
|
ZftIterTypeChainHead<ZCTypeChain, ZCTypeView&, int&>
|
|
( VO_ZCTypeView, (VI_CallNo = 0) );
|
|
cout<<"************************************"<<endl;
|
|
ZftIterTypeChainTail<ZCTypeChain, ZCTypeView&, int&>
|
|
( VO_ZCTypeView, (VI_CallNo = 0) );
|
|
|
|
cout<<"************************************"<<endl;
|
|
ZCTypeChain::ZtCIterChain<ZCTypeView>::
|
|
IterHead(VO_ZCTypeView, ZftMCP(VI_CallNo=0));
|
|
cout<<"************************************"<<endl;
|
|
ZCTypeChain::ZtCIterChain<ZCTypeView>::
|
|
IterTail(VO_ZCTypeView, ZftMCP(VI_CallNo=0));
|
|
|
|
return 0;
|
|
}
|
|
|
|
-- 2025-10-17 16:42
|
|
|
|
////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
/*///////////////////////////////////////////////////////////////////
|
|
|
|
■ class ZtCObjtChain<>
|
|
|
|
각 객체에 어떻게 쉽게 접근하는지가 관건이다. -- 2025-10-18 01:41
|
|
|
|
///////////////////////////////////////////////////////////////////*/
|
|
|
|
template /*########################################################*/
|
|
<
|
|
typename TTypeNow, typename TTypeNextChain
|
|
>
|
|
class ZtCObjtChain : public TTypeNextChain //////////////////////////
|
|
{
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
typedef ZtCObjtChain TypeChainNow ;
|
|
typedef TTypeNextChain TypeChainNext ;
|
|
/************************************************************/
|
|
typedef const TypeChainNow TypeChainNowC ;
|
|
typedef const TypeChainNext TypeChainNextC;
|
|
/************************************************************/
|
|
typedef const TypeData TypeDataC ;
|
|
/************************************************************/
|
|
typedef typename TypeChainNext::TypeData TypeNext ;
|
|
/************************************************************/
|
|
enum{ZETypeNo = TypeChainNext::ZETypeNo+1};
|
|
enum{ZEBoolNext = 1 };
|
|
public :
|
|
static ZTypIntE Size (){return ZETypeNo;}
|
|
static ZTypIntE size (){return ZETypeNo;}
|
|
static ZTypIntE GetNo(){return ZETypeNo;}
|
|
private:
|
|
TypeData mo_TypeVar;
|
|
public :
|
|
ZtCObjtChain(){}
|
|
public :
|
|
TypeData & GetData() {return mo_TypeVar;}
|
|
TypeDataC& GetData() const{return mo_TypeVar;}
|
|
/************************************************************/
|
|
TypeChainNext & GetChainNext()
|
|
{ return static_cast<TypeChainNext&>(*this); }
|
|
TypeChainNextC& GetChainNext() const
|
|
{ return static_cast<TypeChainNext&>(*this); }
|
|
/************************************************************/
|
|
|
|
template<typename TViewChain> void IterHead(TViewChain AO_CView)
|
|
{
|
|
ZtCTypeData<TViewChain>::
|
|
GetObjRef(AO_CView).OnMeetData(*this);
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
static_cast<TypeChainNext&>(*this).IterHead(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
template<typename TViewChain> void IterHead(TViewChain AO_CView)*/
|
|
template<typename TViewChain> void IterTail(TViewChain AO_CView)
|
|
{
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
static_cast<TypeChainNext&>(*this).IterTail(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
|
|
ZtCTypeData<TViewChain>::
|
|
GetObjRef(AO_CView).OnMeetData(*this);
|
|
}/*
|
|
template<typename TViewChain> void IterTail(TViewChain AO_CView)*/
|
|
|
|
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
|
|
ZtCTypeData<TViewChain>::GetObjRef(AO_CView).
|
|
OnMeetData(*this, ZCCheckRef::PassData(AO_TypeHelp));
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
static_cast<TypeChainNext&>(*this).
|
|
IterHead( AO_CView, AO_TypeHelp ) ;
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
static_cast<TypeChainNext&>(*this).
|
|
IterTail( AO_CView, AO_TypeHelp ) ;
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
|
|
ZtCTypeData<TViewChain>::GetObjRef(AO_CView).
|
|
OnMeetData(*this, ZCCheckRef::PassData(AO_TypeHelp));
|
|
}/*
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
*/
|
|
public:
|
|
};/*
|
|
template ############################################################
|
|
<
|
|
typename TTypeNow, typename TTypeNextChain
|
|
>
|
|
class ZtCObjtChain : public TTypeNextChain ////////////////////////*/
|
|
|
|
|
|
template /*########################################################*/
|
|
< typename TTypeNow >
|
|
class ZtCObjtChain<TTypeNow, ZCEmpty> ///////////////////////////////
|
|
{
|
|
public :
|
|
typedef ZtCObjtChain<TTypeNow, ZCEmpty> ZCObjtChain;
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
typedef ZCObjtChain TypeChainNow ;
|
|
typedef ZCObjtChain TypeChainNext ;
|
|
/************************************************************/
|
|
typedef ZCEmpty TypeNext ;
|
|
/************************************************************/
|
|
typedef const TypeData TypeDataC ;
|
|
/************************************************************/
|
|
typedef const TypeChainNow TypeChainNowC ;
|
|
typedef const TypeChainNow TypeChainNextC;
|
|
/************************************************************/
|
|
enum{ZETypeNo = 1 };
|
|
enum{ZEBoolNext = 0 };
|
|
public :
|
|
static ZTypIntE Size (){return ZETypeNo;}
|
|
static ZTypIntE size (){return ZETypeNo;}
|
|
static ZTypIntE GetNo(){return ZETypeNo;}
|
|
private:
|
|
TypeData mo_TypeVar;
|
|
public :
|
|
ZtCObjtChain(){}
|
|
public :
|
|
TypeData & GetData() {return mo_TypeVar;}
|
|
TypeDataC& GetData() const{return mo_TypeVar;}
|
|
/************************************************************/
|
|
TypeChainNext & GetChainNext() { return (*this); }
|
|
TypeChainNextC& GetChainNext() const{ return (*this); }
|
|
/************************************************************/
|
|
|
|
template<typename TViewChain> void IterHead(TViewChain AO_CView)
|
|
{
|
|
ZtCTypeData<TViewChain>::
|
|
GetObjRef(AO_CView).OnMeetData(*this);
|
|
}/*
|
|
template<typename TViewChain> void IterHead(TViewChain AO_CView)*/
|
|
template<typename TViewChain> void IterTail(TViewChain AO_CView)
|
|
{
|
|
ZtCTypeData<TViewChain>::
|
|
GetObjRef(AO_CView).OnMeetData(*this);
|
|
}/*
|
|
template<typename TViewChain> void IterTail(TViewChain AO_CView)*/
|
|
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
|
|
ZtCTypeData<TViewChain>::GetObjRef(AO_CView).
|
|
OnMeetData(*this, ZCCheckRef::PassData(AO_TypeHelp));
|
|
}
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
|
|
ZtCTypeData<TViewChain>::GetObjRef(AO_CView).
|
|
OnMeetData(*this, ZCCheckRef::PassData(AO_TypeHelp));
|
|
}/*
|
|
template<typename TViewChain, typename TTypeHelp>
|
|
void IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
*/
|
|
public:
|
|
};/*
|
|
template ############################################################
|
|
< typename TTypeNow >
|
|
class ZtCObjtChain<TTypeNow, ZCEmpty> /////////////////////////////*/
|
|
|
|
|
|
|
|
/*///////////////////////////////////////////////////////////////////
|
|
|
|
■ class ZtCMiniValChain<>
|
|
|
|
자료형 TTypeNow 에 대하여, 기본값 TTypeVar 으로 자동 초기화하려는
|
|
목적으로 만들었으나, 기본 자료형 즉 int, long, char 에 대해서만 동
|
|
작하고 class 에서는 동작하지 않는다. 리눅스에서는 double 형에 대해
|
|
서도 동작하지 않는다. -- 2025-10-18 00:17
|
|
|
|
그래서 ZtCObjtChainEx 라는 이름을 ZtCMiniValChain 으로 바꾸었다.
|
|
|
|
-- 2025-10-18 10:26
|
|
|
|
■ class ZtCMiniValChain<> 사용 예.
|
|
|
|
typedef ZtCMiniValChain
|
|
<
|
|
char , 'a' , ZtCMiniValChain<
|
|
long , 1567 , ZtCMiniValChain<
|
|
char , 'a' , ZtCMiniValChain<
|
|
char , 'a' , ZtCMiniValChain<
|
|
char , 'c' , ZtCMiniValChain<
|
|
char , 'd' , ZtCMiniValChain<
|
|
char , 'f' , ZtCMiniValChain<
|
|
int , 19 ,
|
|
ZCEmpty > > > > > > >
|
|
> ZtCMiniValChain ;
|
|
|
|
잘하면 char 형의 조합으로, 문자열 비슷하게 사용할 수도 있겠다.
|
|
|
|
-- 2025-10-18 02:10
|
|
|
|
실제로 ZtCMiniArrByChain 를 설계해, 주로 기본 자료형의 배열을 만
|
|
들수 있게 했다.
|
|
|
|
-- 2025-10-18 16:23
|
|
|
|
///////////////////////////////////////////////////////////////////*/
|
|
|
|
template /*########################################################*/
|
|
<
|
|
typename TTypeNow, TTypeNow TTypeVar, typename TTypeNextChain
|
|
>
|
|
class ZtCMiniValChain ///////////////////////////////////////////////
|
|
{
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
typedef ZtCMiniValChain TypeChainNow ;
|
|
typedef TTypeNextChain TypeChainNext ;
|
|
/************************************************************/
|
|
typedef typename TypeChainNext::TypeData TypeNext ;
|
|
/************************************************************/
|
|
typedef const TypeData TypeDataC ;
|
|
/************************************************************/
|
|
enum{ZETypeNo = TypeChainNext::ZETypeNo+1};
|
|
enum{ZEBoolNext = 1 };
|
|
public :
|
|
static ZTypIntE Size (){return ZETypeNo;}
|
|
static ZTypIntE size (){return ZETypeNo;}
|
|
static ZTypIntE GetNo (){return ZETypeNo;}
|
|
static TypeData GetData(){return TTypeVar;}
|
|
public :
|
|
|
|
template<typename TViewChain> class ZtCIterChain
|
|
{
|
|
public:
|
|
|
|
static void IterHead(TViewChain AO_CView)
|
|
{
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow>();
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template
|
|
ZtCIterChain<TViewChain>::IterHead(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
static void IterHead(TViewChain AO_CView)*/
|
|
static void IterTail(TViewChain AO_CView)
|
|
{
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template
|
|
ZtCIterChain<TViewChain>::IterTail(AO_CView);
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow>();
|
|
}/*
|
|
static void IterTail(TViewChain AO_CView)*/
|
|
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/****************************************************/
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template ZtCIterChain<TViewChain>::
|
|
template IterHead<TTypeHelp>(AO_CView, AO_TypeHelp) ;
|
|
}/*
|
|
if(TypeChainNow::ZEBoolNext>0)*/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
if(TypeChainNow::ZEBoolNext>0)
|
|
{
|
|
TypeChainNext::template ZtCIterChain<TViewChain>::
|
|
template IterTail<TTypeHelp>(AO_CView, AO_TypeHelp) ;
|
|
}
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/****************************************************/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
public:
|
|
};/*
|
|
template<typename TViewChain> class ZtCIterChain*/
|
|
|
|
public:
|
|
};/*
|
|
template ############################################################
|
|
<
|
|
typename TTypeNow, TTypeNow TTypeVar, typename TTypeNextChain
|
|
>
|
|
class ZtCMiniValChain : public TTypeNextChain /////////////////////*/
|
|
|
|
|
|
template /*########################################################*/
|
|
<
|
|
typename TTypeNow, TTypeNow TTypeVar
|
|
>
|
|
class ZtCMiniValChain<TTypeNow, TTypeVar, ZCEmpty> //////////////////
|
|
{
|
|
public :
|
|
typedef ZtCMiniValChain<TTypeNow, TTypeVar, ZCEmpty> ZCObjtChain;
|
|
public :
|
|
typedef TTypeNow TypeData ;
|
|
typedef ZCObjtChain TypeChainNow ;
|
|
typedef ZCObjtChain TypeChainNext ;
|
|
/************************************************************/
|
|
typedef ZCEmpty TypeNext ;
|
|
/************************************************************/
|
|
typedef const TypeData TypeDataC ;
|
|
/************************************************************/
|
|
enum{ZETypeNo = 1 };
|
|
enum{ZEBoolNext = 0 };
|
|
public :
|
|
static ZTypIntE Size (){return ZETypeNo;}
|
|
static ZTypIntE size (){return ZETypeNo;}
|
|
static ZTypIntE GetNo (){return ZETypeNo;}
|
|
static TypeData GetData(){return TTypeVar;}
|
|
public :
|
|
|
|
template<typename TViewChain> class ZtCIterChain
|
|
{
|
|
public:
|
|
|
|
static void IterHead(TViewChain AO_CView)
|
|
{
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow>();
|
|
}/*
|
|
static void IterHead(TViewChain AO_CView)*/
|
|
static void IterTail(TViewChain AO_CView)
|
|
{
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow>();
|
|
}/*
|
|
static void IterTail(TViewChain AO_CView)*/
|
|
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/****************************************************/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterHead(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)
|
|
{
|
|
typedef ZNsMain::ZtCCheckRef<TTypeHelp> ZCCheckRef;
|
|
typedef typename ZCCheckRef::TypeRaw TypeRaw ;
|
|
|
|
AO_CView.template OnMeetTypeVal<TypeChainNow, TypeRaw>
|
|
( ZCCheckRef::PassData(AO_TypeHelp) ) ;
|
|
/****************************************************/
|
|
}/*
|
|
template<typename TTypeHelp> static void
|
|
IterTail(TViewChain AO_CView, TTypeHelp AO_TypeHelp)*/
|
|
|
|
public:
|
|
};/*
|
|
template<typename TViewChain> class ZtCIterChain*/
|
|
|
|
public:
|
|
};/*
|
|
template ############################################################
|
|
<
|
|
typename TTypeNow, TTypeNow TTypeVar
|
|
>
|
|
class ZtCMiniValChain<TTypeNow, TTypeVar, ZCEmpty> ////////////////*/
|
|
|
|
|
|
|
|
/*///////////////////////////////////////////////////////////////////
|
|
|
|
■ class ZtCMiniValChain<>
|
|
|
|
ZtCMiniValChain 을 이용해 주로 기본 자료형에 대해 배열을 만들고
|
|
초기화한다. 단, 당장은 크게 쓸모있어 보이지는 않는다.
|
|
|
|
-- 2025-10-18 16:25
|
|
|
|
■ class ZtCMiniValChain<> 사용 예.
|
|
|
|
typedef ZtCMiniValChain
|
|
<
|
|
char , 'a' , ZtCMiniValChain<
|
|
char , 'b' , ZtCMiniValChain<
|
|
char , 'c' , ZtCMiniValChain<
|
|
char , 'd' , ZtCMiniValChain<
|
|
char , 'e' , ZtCMiniValChain<
|
|
char , 'f' , ZtCMiniValChain<
|
|
char , 'g' , ZtCMiniValChain<
|
|
char , 'h' ,
|
|
ZCEmpty > > > > > > >
|
|
> ZCCharValChain ;
|
|
|
|
typedef ZtCMiniArrByChain
|
|
<char, ZCCharValChain> ZCMiniArrByChain;
|
|
|
|
ZCMiniArrByChain VO_CMiniArrByChain;
|
|
|
|
cout<<"# VO_CMiniArrByChain.size()="<<VO_CMiniArrByChain.size()<<endl;
|
|
cout<<"# VO_CMiniArrByChain.data()="<<VO_CMiniArrByChain.data()<<endl;
|
|
|
|
-- 2025-10-18 16:26
|
|
|
|
///////////////////////////////////////////////////////////////////*/
|
|
|
|
template /*########################################################*/
|
|
<
|
|
typename TTypData, typename TCMiniValChain
|
|
>
|
|
class ZtCMiniArrByChain /////////////////////////////////////////////
|
|
{
|
|
public :
|
|
typedef TTypData TypeData ;
|
|
typedef TCMiniValChain TypeChain ;
|
|
public :
|
|
typedef const TTypData TypeDataC ;
|
|
public :
|
|
enum{ZESize = TCMiniValChain::ZETypeNo};
|
|
public :
|
|
typedef TTypData TypeArrr[ZESize+1];
|
|
/*******************************************************************/
|
|
TypeArrr mo_TypeArr;
|
|
public :
|
|
static ZTypIntE Size (){return ZESize;}
|
|
static ZTypIntE size (){return ZESize;}
|
|
public :
|
|
TypeData * GetArray() {return mo_TypeArr;}
|
|
TypeDataC* GetArray() const{return mo_TypeArr;}
|
|
TypeData * data () {return mo_TypeArr;}
|
|
TypeDataC* data () const{return mo_TypeArr;}
|
|
private:
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
|
|
class ZCTypeView
|
|
{
|
|
private:
|
|
ZTypIntE mi_CallNo;
|
|
public :
|
|
ZCTypeView(){mi_CallNo=0;}
|
|
public :
|
|
|
|
template
|
|
<typename TTypChain, typename THelpArray>
|
|
void OnMeetTypeVal(TypeData* mp_Array)
|
|
{
|
|
mp_Array[mi_CallNo++] = TTypChain::GetData() ;
|
|
}
|
|
public :
|
|
};/*
|
|
class ZCTypeView*/
|
|
|
|
private:
|
|
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
|
|
public :
|
|
|
|
ZtCMiniArrByChain()
|
|
{
|
|
ZCTypeView VO_ZCTypeView; mo_TypeArr[ZESize]=0;
|
|
|
|
TypeChain::template ZtCIterChain<ZCTypeView&>::
|
|
IterHead( VO_ZCTypeView, mo_TypeArr );
|
|
/*********************************************/
|
|
}/*
|
|
ZtCMiniArrByChain()*/
|
|
|
|
public:
|
|
};/*
|
|
template /*##########################################################
|
|
<
|
|
typename TTypData, typename TCMiniValChain
|
|
>
|
|
class ZtCMiniArrByChain ///////////////////////////////////////////*/
|
|
|
|
|
|
|
|
namespace ZNsTmplChain
|
|
{
|
|
/*////////////////////////////////////////////////////////////
|
|
|
|
■ ZtCTmplChain<> 와 유사한 인터페이스를 이용하여, 마치 chain
|
|
처럼 호출하는 구조를 갖는 클래스를 여기에 둔다.
|
|
|
|
-- 2011-08-05 21:16:00
|
|
|
|
사용례는 CMainChars.H 의
|
|
|
|
TTypeLength CSearchCursor_T<>::GetLengthByTmplChain(~)
|
|
|
|
함수를 참고한다.
|
|
|
|
-- 2011-08-06 23:51:00
|
|
|
|
////////////////////////////////////////////////////////////*/
|
|
}/*
|
|
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("&" ,"&" ). Replace("<" ,"<" ).
|
|
Replace(">" ,">" ). Replace(" " ," ").
|
|
Replace("\n","<br />" );
|
|
}/*
|
|
template<typename TStringData> TStringData& ConvertXhtml(TStringData& ARRoCString) */
|
|
|
|
|
|
template<typename TStringData> TStringData& ZftMakeXmlAttEnc(TStringData& ARRoCStringData)
|
|
{
|
|
return ARRoCStringData.
|
|
Replace("&" , "&" ).Replace("\r", "
" ).
|
|
Replace("\n", "
" ).Replace("\t", "	" ).
|
|
Replace("\"", """).Replace(">" , ">" ).Replace("<", "<");
|
|
}/*
|
|
template<typename TStringData> TStringData& ZftMakeXmlAttEnc(TStringData& ARRoCStringData)*/
|
|
|
|
template<typename TStringData> TStringData& ZftMakeXmlAttDec(TStringData& ARRoCStringData)
|
|
{
|
|
return ARRoCStringData.
|
|
Replace("
" ,"\r" ). Replace("
" ,"\n").
|
|
Replace("	" ,"\t" ). Replace(""","\"").
|
|
Replace(">" ,">" ). Replace("<" ,"<" ). Replace("&" ,"&" );
|
|
}/*
|
|
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>& AO_View);
|
|
template<> wstring& ZftMakeStr
|
|
(wstring& ARR_SaveCStr, const ZtCChars<wchar_t, ZTypLength>& AO_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(TypeIterC& 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(TypeIterC& 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() 과 MoveRangeIn() 에서 사용한다. -- 2025-10-15 23:44
|
|
|
|
■ class ZCLinkFake 를 설계하고 보니까, MoveRangeIn() 가 어떻게
|
|
이렇게 깨끗하게 구현이 될 수 있을까...
|
|
|
|
-- 2025-10-16 13:56
|
|
|
|
///////////////////////////////////////////////////////////////*/
|
|
|
|
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) /////////////////////////////////////////////
|
|
{
|
|
if ( &AR_MoveLink == mp_HeadLink &&
|
|
mp_HeadLink->mp_NextLink== &AR_StdLink && !AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_MoveLink == mp_TailLink &&
|
|
mp_TailLink->mp_PrevLink== &AR_StdLink && AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_StdLink == mp_HeadLink &&
|
|
mp_HeadLink->mp_NextLink== &AR_MoveLink && AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_StdLink == mp_TailLink &&
|
|
mp_TailLink->mp_PrevLink== &AR_MoveLink && !AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
|
|
|
|
// 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) /////////////////////////////////////////////
|
|
{
|
|
if ( &AR_MoveHead == mp_HeadLink &&
|
|
AR_MoveTail.mp_NextLink== &AR_StdLink && !AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_MoveTail == mp_TailLink &&
|
|
AR_MoveHead.mp_PrevLink== &AR_StdLink && AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_StdLink == mp_HeadLink &&
|
|
AR_StdLink.mp_NextLink == &AR_MoveHead && AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
if ( &AR_StdLink == mp_TailLink &&
|
|
AR_StdLink.mp_PrevLink == &AR_MoveTail && !AB_After
|
|
)
|
|
{ return *this; } /*****************************************/
|
|
|
|
|
|
// 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
|
|
)
|
|
#######################################################################*/
|
|
|
|
|
|
ZtCBaseList& MoveRangeIn ////////////////////////////////////////////////
|
|
(
|
|
ZCLink& AR_MoveHead, ZCLink& AR_MoveTail,
|
|
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 MoveRangeIn(AR_MoveHead, AR_MoveTail, *VP_LinkStd, AB_After);
|
|
}
|
|
/*#####################################################################*/
|
|
|
|
ZtCBaseList& MoveRangeInAfter
|
|
( ZCLink& AR_MoveHead, ZCLink& AR_MoveTail, ZCLinkOpt AO_StdOpt)
|
|
{ return MoveRangeIn(AR_MoveHead, AR_MoveTail, AO_StdOpt, true ); }
|
|
ZtCBaseList& MoveRangeInBefore
|
|
( ZCLink& AR_MoveHead, ZCLink& AR_MoveTail, ZCLinkOpt AO_StdOpt)
|
|
{ return MoveRangeIn(AR_MoveHead, AR_MoveTail, AO_StdOpt, false); }
|
|
/***********************************************************************/
|
|
ZtCBaseList& MoveRangeInHead(ZCLink& AR_MoveHead, ZCLink& AR_MoveTail)
|
|
{ return MoveRangeIn(AR_MoveHead, AR_MoveTail, ZCLinkOpt(0), true ); }
|
|
ZtCBaseList& MoveRangeInTail(ZCLink& AR_MoveHead, ZCLink& AR_MoveTail)
|
|
{ return MoveRangeIn(AR_MoveHead, AR_MoveTail, ZCLinkOpt(0), false); }
|
|
|
|
|
|
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
|
|
);
|
|
//////////////////////
|
|
}
|
|
/*#####################################################################*/
|
|
|
|
|
|
|
|
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& AO_View)
|
|
{ ARR_SaveCStr.append(AO_View.data(), AO_View.size()); return ARR_SaveCStr; }
|
|
template<> wstring& ZftMakeStr(wstring& ARR_SaveCStr, const ZCCharViewW& AO_View)
|
|
{ ARR_SaveCStr.append(AO_View.data(), AO_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<<"&" ; continue;}
|
|
if(APC_LogData[i]=='\r'){cout<<"
" ; continue;}
|
|
if(APC_LogData[i]=='\n'){cout<<"
" ; continue;}
|
|
if(APC_LogData[i]=='\t'){cout<<"	" ; continue;}
|
|
if(APC_LogData[i]=='\"'){cout<<"""; continue;}
|
|
if(APC_LogData[i]=='>' ){cout<<">" ; continue;}
|
|
if(APC_LogData[i]=='<' ){cout<<"<" ; 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& AO_View)
|
|
{
|
|
ZCSngtLogData::Log(AO_View.data(), AO_View.size()); return *this;
|
|
}/*
|
|
ZCSngtLogData& operator()(const ZCCharView& AO_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__
|