C/C++ 매크로의 쉼표
이와 같은 매크로가 있다고 가정해 봅시다.
#define FOO(type,name) type name
우리가 사용할 수 있는 것은
FOO(int, int_var);
하지만 항상 그렇게 간단하지는 않습니다.
FOO(std::map<int, int>, map_var); // error: macro "FOO" passed 3 arguments, but takes just 2
물론 다음과 같은 작업을 수행할 수 있습니다.
typedef std::map<int, int> map_int_int_t;
FOO(map_int_int_t, map_var); // OK
인체공학적이지 않은 방법이죠게다가 타입의 비호환성도 취급할 필요가 있습니다.매크로로 해결할 방법을 알고 계십니까?
괄호를 사용할 수 없고 Mike의 SINGLE_ARG 솔루션이 마음에 들지 않으면 쉼표를 정의하기만 하면 됩니다.
#define COMMA ,
FOO(std::map<int COMMA int>, map_var);
또한 다음과 같이 일부 매크로 인수를 문자열화하려는 경우에도 도움이 됩니다.
#include <cstdio>
#include <map>
#include <typeinfo>
#define STRV(...) #__VA_ARGS__
#define COMMA ,
#define FOO(type, bar) bar(STRV(type) \
" has typeid name \"%s\"", typeid(type).name())
int main()
{
FOO(std::map<int COMMA int>, std::printf);
}
인쇄하는 방법std::map<int , int> has typeid name "St3mapIiiSt4lessIiESaISt4pairIKiiEEE"
.
꺾쇠 괄호는 비교 연산자를 나타낼 수도 있기 때문에<
,>
,<=
그리고.>=
, 매크로 확장은 괄호 안에서처럼 괄호 안의 쉼표를 무시할 수 없습니다.(이것은, 대괄호나 대괄호에서도 문제가 됩니다만, 일반적으로 밸런스 페어로서 발생합니다).macro 인수는 괄호로 묶을 수 있습니다.
FOO((std::map<int, int>), map_var);
문제는 매크로 확장 내에서 파라미터가 괄호로 둘러싸인 상태로 유지되기 때문에 대부분의 컨텍스트에서 파라미터가 유형으로 읽히지 않는다는 것입니다.
이 문제를 회피하기 위한 좋은 방법은 C++에서는 함수 유형을 사용하여 괄호 안의 유형 이름에서 유형 이름을 추출할 수 있다는 것입니다.
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
FOO((std::map<int, int>), map_var);
함수 유형을 형성하는 것은 추가 괄호를 무시하기 때문에 이 매크로를 괄호 포함 여부에 관계없이 사용할 수 있습니다.
FOO((int), int_var);
FOO(int, int_var2);
물론 C에서는 유형 이름에 괄호 밖에 쉼표를 포함할 수 없기 때문에 이 작업은 필요하지 않습니다.따라서 언어 간 매크로의 경우 다음과 같이 쓸 수 있습니다.
#ifdef __cplusplus__
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
#else
#define FOO(t,name) t name
#endif
프리프로세서가 가변 매크로를 지원하는 경우:
#define SINGLE_ARG(...) __VA_ARGS__
#define FOO(type,name) type name
FOO(SINGLE_ARG(std::map<int, int>), map_var);
그렇지 않으면 좀 더 지루합니다.
#define SINGLE_ARG2(A,B) A,B
#define SINGLE_ARG3(A,B,C) A,B,C
// as many as you'll need
FOO(SINGLE_ARG2(std::map<int, int>), map_var);
정의만 하면FOO
~하듯이
#define UNPACK( ... ) __VA_ARGS__
#define FOO( type, name ) UNPACK type name
그런 다음 항상 type 인수 주위에 괄호를 사용하여 호출합니다.
FOO( (std::map<int, int>), map_var );
물론 매크로 정의에 대한 코멘트에서 호출을 예시하는 것은 좋은 생각일 수 있다.
간단한 대답은 당신은 할 수 없다는 것이다.이것은 선택으로 인한 부작용이다.<...>
템플릿 인수의 경우;<
그리고.>
또한 불균형한 맥락에서 나타나기 때문에 매크로 메커니즘이 괄호를 처리하는 것처럼 그들을 처리하도록 확장될 수 없었다. (몇몇 위원회 구성원은 다른 토큰을 주장했다, 예를 들어(^...^)
하지만, 그들은 이 프로그램을 사용하여 대부분의 문제를 납득시킬 수는 없었다.<...>
.)
적어도 두 가지 방법이 있습니다.먼저 여러 인수를 사용하는 매크로를 정의할 수 있습니다.
#define FOO2(type1, type2, name) type1, type2, name
이렇게 하면 더 많은 인수를 처리하기 위해 더 많은 매크로를 정의할 수 있습니다.
둘째, 인수 주위에 괄호를 둘 수 있습니다.
#define FOO(type, name) type name
F00((std::map<int, int>) map_var;
이렇게 하면 추가 괄호가 결과의 구문을 망칠 수 있습니다.
이것은, P99 로 가능합니다.
#include "p99/p99.h"
#define FOO(...) P99_ALLBUTLAST(__VA_ARGS__) P99_LAST(__VA_ARGS__)
FOO()
위의 코드는 인수 목록의 마지막 쉼표만 효과적으로 삭제합니다.clang -E
(P99에는 C99 컴파일러가 필요합니다).
언급URL : https://stackoverflow.com/questions/13842468/comma-in-c-c-macro
'source' 카테고리의 다른 글
libcurl 없이 C에서 HTTP get 요구를 작성하려면 어떻게 해야 합니까? (0) | 2022.08.10 |
---|---|
C에 화살표(->) 연산자가 존재하는 이유는 무엇입니까? (0) | 2022.08.10 |
C의 단일 구조 부재 크기 (0) | 2022.08.10 |
Java에서 데몬 스레드란 무엇입니까? (0) | 2022.08.10 |
Java에서 문자열이 정수인지 확인 (0) | 2022.08.10 |