매크로 비법 #1 열거형을 문자열로

#연산자 - 그 뒤에 나오는 인수 주변에 따옴표를 표시할 때 사용한다.

이 방법을 이용하면 열거형 상수들의 이름을 문자열로 변환해서 로그 파일이나 화면에 출력할 수 있다.


다른 방법 하나는 헤더파일 하나에 열거형에 대한 정보를 담아두고, 그것으로부터 열거형과 문자열 이름들의 배열을 자동으로 만들어내는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// data.h
 
DATA(MSG_YouWereHit)
DATA(MSG_GameReset)
DATA(MSG_HealthRestored)
 
// data.cpp
 
#define DATA(x) x,
 
enum GameMessages
{
  #include "data.h"
};
 
#undef DATA
#define DATA(x) #x, // make enums into strings
 
static const char* GameMessageNames[] =
{
  #include "data.h"
};
 
#undef DATA
cs
이 코드만 봐서는 어떻게 동작되는지 잘 모르겠다.


매크로 비법 #2 : 이진수 형태로 된 컴파일 시점 상수

## 연산자 - 두 인수들을 하나로 결합해준다. 

ex)

#define cat(a,b) a ## b

value = cat(1,2);

전처리기에 의해 치환된 결과는 value = 12;

이를 활용하는 한가지 비법은 이진수 형태로 된 컴파일 시점 상수를 만들어내는 것이다.

매크로들이 전적으로 전처리기 안에서 처리되며 실행 시점 코드는 전혀 만들어내지 않는다는 점이다. 나중에 코드를 다시 살펴보자


매크로 비법 #3 : 표준 assert에 의미있는 메시지를 추가

assert 매크로를 메세지도 띄울 수 있도록 만들자?

ex)

#define assertmsg(a,b) assert ( a && b )

assertmsg( time > 0 , "Trigger::Set - The arg time must be > 0") ;


매크로 비법 #4 : 컴파일 시점 assert

빌드과정을 중지시켜야 하는 상황에서 사용된다.

ex) #define casset(expn) typedef char __c_ASSERT__[(expn) ?1:-1]

cassert( sizeof(MyEnum) == sizeof(unsigned int) );

cassert에 거짓인 문장이 주어지면, cassert는 크기가 음인 배열을 정의하고 빌드과정이 즉시 중지된다.


매크로 비법 #5: 배열의 원소 개수 구하기

#define NumEle(array) (sizeof(array) / sizeof((array)[0]))


매크로 비법 #6 __LINE__을 문자열로

__LINE__ // 이것이 있는 곳의 행번호를 의미하는 정수

__FILE__ // 이것이 있는 곳의 파일이름을 담은 문자열

__DATE__ // 컴파일될 때의 날짜를 담은 문자열

__TIME__ // 컴파일될 때의 시간을 담은 문자열


매크로 비법 #7 : 무한 루프 방지하기

1
2
3
4
5
6
7
8
9
10
11
12
static bool while_assert( bool a )
{
  assert( a && "while_limit: exceeded iteration limit" );
  return( a );
}
 
#define UNIQUE_VAR(x) safety_limit ## x
#define _while_limit(a,b,c) \
  assert(b>&& "while_limit: limit is zero or negative");\
  int UNIQUE_VAR(c) = b; \
  while(a && while_assert(--UNIQUE_VAR(c)>=0))
#define while_limit(a,b) _while_limit(a,b,__COUNTER__)
cs
일단은 소스만..

매크로 비법 #8 : 특화된 작은 언어
간단한 스크립트 언어같은 매크로를 만들수 있다
ex)FSM같은 것을 만드는 것도 좋다.
1
2
3
4
5
6
7
8
9
#define BeginStateMachine  if(state < 0){if(0){
#define EndStateMachine    return(true);}}else{assert(0); \
                           return(false);}return(false);
#define State(a)           return(true);}} \
                           else if(a == state){if(0){
#define OnEvent(a)         return(true);}else if(a == event){
#define OnEnter            OnEvent(EVENT_Enter)
#define OnUpdate           OnEvent(EVENT_Update)
#define OnExit             OnEvent(EVENT_Exit)
cs

매크로 비법 #9 : 클래스 인터페이스 단순화
1
2
3
4
5
6
7
8
#define INTERFACE_Creature(terminal)               \
  public:                                          \
    virtual std::string GetName() const ##terminal \
    virtual int GetHitPoints() const ##terminal    \
    virtual float GetMaxVelocity() const ##terminal
 
#define BASE_Creature        INTERFACE_Creature(=0;)
#define DERIVED_Creature    INTERFACE_Creature(;)
cs



posted by 알쿠미