전처리기 매크로 (Preprocessor Macros)¶
특히 헤더에서는 매크로를 정의하지 마세요. 인라인 함수, 열거형 및 const 변수를 선호합니다. 프로젝트별 접두사를 사용하여 매크로 이름을 지정하세요. C++ API의 일부를 정의하기 위해 매크로를 사용하지 마세요.
매크로는 사용자가 보는 코드가 컴파일러가 보는 코드와 동일하지 않음을 의미합니다. 특히 매크로에는 전역 범위가 있으므로 이로 인해 예기치 않은 동작이 발생할 수 있습니다.
매크로로 인해 발생하는 문제는 매크로가 C++ API의 일부를 정의하는 데 사용될 때 특히 심각하며, 공개 API의 경우에는 더욱 그렇습니다. 개발자가 해당 인터페이스를 잘못 사용할 때 발생하는 컴파일러의 모든 오류 메시지는 이제 매크로가 인터페이스를 형성한 방식을 설명해야 합니다. 리팩토링 및 분석 도구는 인터페이스를 업데이트하는 데 훨씬 더 어려움을 겪습니다. 결과적으로 우리는 이러한 방식으로 매크로를 사용하는 것을 특별히 허용하지 않습니다. 예를 들어 다음과 같은 패턴은 피하세요.
class WOMBAT_TYPE(Foo) {
// ...
public:
EXPAND_PUBLIC_WOMBAT_API(Foo)
EXPAND_WOMBAT_COMPARISONS(Foo, ==, <)
};
다행히 C++에서는 매크로가 C에서만큼 필요하지 않습니다. 성능이 중요한 코드를 인라인하기 위해 매크로를 사용하는 대신 인라인 함수를 사용하세요. 매크로를 사용하여 상수를 저장하는 대신 const 변수를 사용하세요. 긴 변수 이름을 "축약"하기 위해 매크로를 사용하는 대신 참조를 사용하십시오. 코드를 조건부로 컴파일하기 위해 매크로를 사용하는 대신... 음, 전혀 그렇게 하지 마세요(물론 헤더 파일의 이중 포함을 방지하는 #define 가드를 제외하고). 테스트가 훨씬 더 어려워집니다.
매크로는 다른 기술이 할 수 없는 작업을 수행할 수 있으며 코드베이스, 특히 하위 수준 라이브러리에서 볼 수 있습니다. 그리고 일부 특수 기능(문자열화, 연결 등)은 해당 언어를 통해 사용할 수 없습니다. 그러나 매크로를 사용하기 전에 동일한 결과를 얻을 수 있는 매크로가 아닌 방법이 있는지 신중하게 고려하십시오. 인터페이스를 정의하기 위해 매크로를 사용해야 하는 경우 프로젝트 책임자에게 연락하여 이 규칙에 대한 면제를 요청하세요.
다음 사용 패턴은 매크로와 관련된 많은 문제를 방지합니다. 매크로를 사용하는 경우 가능하면 이를 따르십시오.
.h파일에 매크로를 정의하지 마세요.- 매크로는 사용하기 직전에
#define하고 사용 직후에#undef하세요. - 기존 매크로를 자신의 매크로로 바꾸려고
#undef하지 마세요. 대신 고유한 이름을 선택하세요. - 짝이 맞지 않는(unbalanced) C++ 구문으로 확장되는 매크로는 쓰지 말거나, 최소한 그 동작을 잘 문서화하세요.
- 함수/클래스/변수 이름을 생성하는 데
##을 쓰지 않는 것이 좋습니다.
헤더에서 매크로를 내보내는 것(즉, 헤더가 끝나기 전에 #undef하지 않고 헤더에서 매크로를 정의하는 것)은 매우 권장되지 않습니다. 헤더에서 매크로를 내보내는 경우 전역적으로 고유한 이름이 있어야 합니다. 이를 위해서는 프로젝트의 네임스페이스 이름(대문자)으로 구성된 접두사를 붙여 이름을 지정해야 합니다.
이해하기 쉽게 설명하기¶
핵심: 매크로를 (특히 헤더에서) 정의하지 마라¶
매크로는 "사람이 보는 코드 ≠ 컴파일러가 보는 코드"를 만들고 전역 범위를 가져 예기치 않은 동작을 일으킵니다. 대부분의 경우 더 나은 대안이 있습니다.
| 매크로의 용도 | 대신 |
|---|---|
| 성능을 위한 인라인 | 인라인 함수 |
| 상수 저장 | const/constexpr 변수 |
| 긴 이름 축약 | 참조 |
| 조건부 컴파일 | (하지 마세요 — #define 가드 제외) |
특히 금지: 매크로로 API 정의¶
WOMBAT_TYPE(Foo)처럼 매크로로 인터페이스를 만들면 오류 메시지가 난해해지고 리팩토링 도구가 망가집니다. 꼭 필요하면 프로젝트 리드에게 예외를 요청하세요.
꼭 써야 한다면¶
.h파일에 매크로를 정의하지 마세요(헤더에서 내보내려면 프로젝트 네임스페이스 대문자 접두사로 전역 고유 이름을).- 매크로는 사용 직전에
#define, 직후에#undef. - 남의 매크로를
#undef하지 말고 고유한 이름을 고르세요. - 함수/클래스/변수 이름을
##로 생성하지 마세요.