#define의 대체제

확실히 #define은 다른 걸로 대체 가능할 때는 가능한 한 안 쓰는 게 좋을 것 같다.
C++은 용도별로 다음과 같은 다양한 대체제를 제공한다.

1. 매크로 함수의 대체제: 인라인 함수로 대체 가능하며, 템플릿까지 동원하면 매크로 함수 만만찮은 유연한 메타프로그래밍이 가능하다.
또한 한 함수 안에서만 지엽적으로 반복되는 루틴을 정리하려면 C++0x부터는 람다 함수를 쓸 수도 있다.

2. 매크로 상수의 대체제: 정수의 경우 enum을 쓰면 같은 성격의 여러 심벌들을 한데 묶어 놓을 수도 있어서 좋다.
그리고 문자열은 그냥 const char/WCHAR 형태의 전역/클래스 static 변수로 처리함. 선언과 정의가 따로 존재해야 해서 불편할 수 있으나, 이것은 선언부에다 값을 다 집어넣고 확장 문법인 __declspec(selectany) extern const 를 지정해서 해결할 수도 있다.

아무 통제도 없이 너무 일방적으로 효력이 나타나는 #define보다는 저런 대체제들이 type-safety와 엄격한 scope 검증이 보장되기 때문에 "훨씬 더" 깔끔하다. 가능한 한 전처리기보다는 컴파일러에게 일을 맡기는 게 바람직하다.
내가 만든 명칭이 매크로로 이미 존재하여 딴 걸로 치환되고 있는 줄도 모르고 컴파일러가 자꾸 이상한 난독증을 보이며 에러를 뱉는 것 때문에 빡친 경험이 있는 사람.. 주변에 의외로 많다. ㅎㅎ

단, 그럼에도 불구하고 대체제가 존재하지 않아서 #define을 불가피하게 써야만 하는 경우는 아마도 다음과 같을 것이다.

1. #if #elif #endif 같은 조건부 컴파일 변수 지정

2. 함수 형태를 갖추기조차 민망할 정도로 너무 간단한 로직. 디버그 빌드에서도 독립된 함수 호출이 아니라 언제나 인라이닝이 반드시 보장되기를 바라는 부분

3. 호출하는 함수나 지정하는 변수 이름을 말 그대로 간단히 치환만 시키기를 원하는 경우

4. 대체제의 문법적 한도를 넘는 과격한 구문 치환을 해야 하는 경우. 특히 #나 ## 같은 연산자를 동원해서 완전히 새로운 토큰을 만들어 내야 할 때

5. __LINE__, __FILE__, __TIME__ 같은 빌드/디버그 정보를 그때 그때 삽입하고 싶을 때

6. 정수와는 달리 부동소숫점과 문자열은 여전히 #define이 유용한 경우가 있다.
부동소숫점은 enum이 지원되지 않고 static const 멤버도 클래스 선언부에서 바로 값 지정이 되지 않기 때문이다. (이걸 지원하는 컴파일러도 있긴 하나, 일단은 비표준임)
문자열은 매크로 상수의 경우, concatenate(연결)되는 문자열의 일부가 되는 게 가능하다. const 상수는 그렇지 않다.

#include와 #define이 너무 지저분하고 컴파일 시간을 증가시키는 요인이라며 없애자니.. 위와 같은 용도까지 부정하는 건 현실적으로 무리이긴 하다.

여담으로..
근래엔 남이 만든 코드를 읽다가 IID_PPV_ARGS라는 매크로를 보고 감탄하여 내가 짠 기존 코드에다가도 다 리팩터링을 해서 적용해 놨다.

CoCreateInstance와 IUknown::QueryInterface 때 꼴도 보기 싫던 void ** 형변환을 없애 주는 매우 편리하고 유용한 물건이다. COM이 등장한 건 무려 20년이 넘었고 C++에 템플릿이 추가된 것도 만만찮게 오래 됐을 텐데 이 매크로는 무려 Windows 7의 플랫폼 SDK에서야 정식 등장했다는 게 놀랍다.
매개변수 2개를 하나로 줄이는 역할까지 하니 이 정도라면 컴파일러가 아니라 전처리기 매크로밖에 선택의 여지가 없긴 하다.

Posted by 사무엘

2014/04/01 19:20 2014/04/01 19:20
,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/947

Trackback URL : http://moogi.new21.org/tc/trackback/947

Comments List

  1. 김재주 2014/04/02 20:01 # M/D Reply Permalink

    사실 매크로가 꼬여서 생기는 문제는 C++으로 뭔가 만들어보려 한 사람들은 대부분 겪어보는 일이죠

    함수 이름으로는 카멜케이스나 언더라인을 사용하지만, 매크로는 반드시 대문자로만 작성한다던지, 이름 앞에 매크로라는 걸 알 수 있는 키워드를 붙이도록 하는 것도 그래서 생긴 관습이고요.


    debug 모드에서도 인라이닝되는 걸 원하실 때는 __forceinline을 사용하는 것도 고려해봄직합니다.

    1. 사무엘 2014/04/02 22:57 # M/D Permalink

      C/C++이 명칭에 대소문자 구분을 하는 언어가 아니었다면 큰일 났을 거예요.
      아니면 매크로는 무조건 _로 시작한다거나 하는 그런 눈에 띄는 제약이라도 있어야 했을 겁니다.
      글을 쓰고 나서 보니, 매크로도 무슨 goto처럼 제한적으로만 쓰여야 하는 물건 취급을 받는 듯하군요.

Leave a comment
« Previous : 1 : ... 1375 : 1376 : 1377 : 1378 : 1379 : 1380 : 1381 : 1382 : 1383 : ... 2204 : Next »

블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/11   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Site Stats

Total hits:
2987491
Today:
528
Yesterday:
2516