Visual Studio
[C/C++] 가변인자 매크로로 함수 호출시 불필요한 쉼표 생략하는법 본문
C/C++의 매크로는 __VA_ARGS__로 가변 인자를 사용할 수 있는데.
매크로를 사용할 때 가변 인자 위치에 아무 파라미터도 주어지지 않으면 문제가 생긴다.
다음의 예제를 보자.
#define CREATEOBJECT(A, B, ...) \
std::make_shared<A>(B, __VA_ARGS__); \
...
CREATEOBJECT(ObjectType, param1)
// std::make_shared<ObjectType(param1, ); 으로 치환되므로 에러가 남.
이제 이렇게 해보자.
#define CREATEOBJECT(A, B, ...) \
std::make_shared<A>(B, ## __VA_ARGS__); \
...
CREATEOBJECT(ObjectType, param1)
// std::make_shared<ObjectType(param1); 으로 정상적으로 치환된다;;
// 이게 대체 왜 됨 ??????
원래 ##은 다음과 같은 일을 하는 전처리 과정에서만 사용되는, token pasting operator 라고 하는 연산자이다.
#define INTCONCAT(A, B) int A##B
...
INTCONCAT(count, 0);
// int count0; 로 치환된다.
하지만 GCC에선 __VA_ARGS__ 앞에 오는 경우에는 token pasting operator로써가 아닌 이와 같이 가변 인자의 개수가 0일 때 콤마를 지우는 역할을 하도록 되어 있는 듯 하다.
GCC 문서를 뒤져보니 비표준으로 이러한 기능을 제공한다고 한다.
Variadic Macros (Using the GNU Compiler Collection (GCC))
6.21 Macros with a Variable Number of Arguments. In the ISO C standard of 1999, a macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function. Here is an example:
gcc.gnu.org
Clang과 MSVC에서도 이를 지원하고 있다.
추가로 재밌는 사실은, 기존에 비표준이었던 __VA_OPT__가 C++20에서 채택되었기 때문에 C++20부터는 더이상 ## 연산자를 사용하지 않아도 된다!
Recursive macros with C++20 __VA_OPT__
If T is the name of a function-like macro, T’s unavailable bit is clear, and T is followed by (, then T is expanded. Note, however, that if T is called with an invalid number of arguments, then the program is ill-formed.
www.scs.stanford.edu
MSVC 문서에서도 이에 대한 포스트를 발견할 수 있다.
MSVC new preprocessor overview
The MSVC preprocessor is being updated for conformance with C/C++ standards.
docs.microsoft.com
추가로 아래 블로그의 "가변 인자에 대한 모든 것" 포스트에서 가변 인자 매크로에 자세히 설명하고 있으니 관심있는 사람은 읽어보는 것을 추천한다.
가변 인자 매크로의 모든 것 - 개론 | woong.org
이 글은 시리즈 글의 일부입니다. 수정: 마지막 글(가변 인자 매크로의 모든 것 - 보충)이 추가되었습니다. variadic 이라는 단어를 아시나요? (인터넷을 포함해) 가까이 있는 영어 사전을 뒤적여도
blog.woong.org
'Programming Language' 카테고리의 다른 글
memset의 함정 (은근 착각하기 쉬움) (0) | 2022.06.19 |
---|---|
가상함수, RTTI (0) | 2022.06.14 |
C++ 재활 (0) | 2022.04.06 |
Virtual Function in C++ (0) | 2022.03.04 |
C에서 객체지향 프로그래밍을 하는 방법 - GObject (0) | 2021.11.22 |