2011-05-10 3 views
10

내 생각에이 질문에 대한 대답은 아니오입니다. 그러나 방법이 있다면 정말 좋을 것입니다. 명확히하기 위해, 나는 다음과 같은 매크로가 있다고 가정 :가변 매크로 인수에 C++ 전 처리기 문자열을 사용하는 방법이 있습니까?

#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition 

내가 뭘하고 싶은 것은 가변 인자 함수에 전달하기 전에 X의 모든 변수에 문자열 화 (stringification)을 수행 어떻게 든; 여기에있는 키워드는 이전입니다. 매크로 정의 내에서 개별 인수에 실제로 액세스 할 수있는 방법이 없다는 것을 알고 있지만, 다음 인수와 같은 모든 인수를 문자열로 변환하는 방법이 있습니까?

#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X) 

답변

8

좋아, 나는 여기에 내 자신의 질문에 대한 대답을 의미하지는 않았지만 나는 마크 윌킨스 대답과 내가 질문에서 준 예를 조합 한 다소 괜찮은 해결책을 제시했다.

문자열에 구분 쉼표가 포함 된 전체 집합 가변 배열을 문자열로 지정할 수 있습니다. 다음은 간단한 예입니다.

위의 매크로를 사용하면 매크로에 전달 된 전체 인수 집합이 문자열 화됩니다.

그런 다음 당신이 다음 가변 인자 매크로를 사용하여하여 토큰 화 된 문자열의 집합을 얻기의 단락 문자 쉼표를 사용하여 이러한 인수를 토큰 화하는 기능을 정의 할 수 있습니다 :

#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X) 

그런 다음 더 이상 실제로있는의 의존성이 없다 variadic 매크로는 가변 함수를 호출하고 va_arg를 반복하지 않고 상수 C 문자열의 배열을 멋지게 반복 할 수 있습니다. 편집에서

* 새로운 물건이 여기 *

당 팀의 의견을 따릅니다 솔루션의 세부 사항입니다. 서둘러 완료되었으므로 오류를 용서해주십시오. 그리고 제가 작업중인 것을 포팅해야했습니다. 또한 POC를 설명하기 위해 인수의 문자열을 출력하기 때문에 복사/붙여 넣기 솔루션이 아니지만 기능을 충분히 설명 할 수 있어야합니다.

비록이 솔루션이 약간의 런타임 계산을 필요로하지만 가변 매크로는 종종 가변적 인 함수를 호출하고 va_args를 통해 반복해야하기 때문에 약간의 성능이 희생 될지라도 반복은 토큰을 찾는 과정에서 발생합니다.

#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY) 

void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments) 
{ 
    strcpy(converted_arguments, _stringified_arguments); 

    for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ",")) 
     std::cout << token << std::endl; 
} 
+0

또 다른 멋진 기능은 목록의 인수가 끝나는 위치를 결정하기 위해 매크로를 통해 전달되는 정보 유형을 보유하지 않고도 인수의 수를 쉽게 찾을 수 있다는 것입니다. – Hazok

+0

흥미 롭습니다. 그러나 이것을 해결책으로 표시하기 전에이를 해결 한 실제 코드를 게시하십시오. 나는 그것이 다른 사람들에게 유용 할 것이라고 확신한다. – Tim

+0

@Tim Will은 이미 간단한 사례를 테스트했으며 더 좋은 예를 만들 것입니다 ... 마감일을 지키고 내일 (2011/11/05) 또는 다음 날 중 하나에 게시합니다. – Hazok

2

이 아마도 당신이 원하는 무엇을 매우 가까이 아니라, 다음과 같은 무언가가 당신을 얻을 수 있습니다 :

#define MY_VARIADIC_MACRO(X) printf("%s\n", #X) 

다음처럼 사용합니다. 매크로에 하나의 매개 변수로 나타나도록 매개 변수를 괄호로 묶습니다.

MY_VARIADIC_MACRO ((var1, var2, "string")));

그런 다음 매크로를 호출하여 바깥 쪽 괄호를 제거하거나 주어진 문자열을 구문 분석 할 수 있습니다.

+0

그는 괄호를 묶을 필요가있다. 놈의 반환은 빠른 주석을 추가하고, shift-return을 기억할 필요가있다. 위의 내용이 내가 해결하려는 솔루션에 매우 가깝다고 생각합니다. 나는이 답변이 거의 다 왔기 때문에 투표 할 것이지만 요구 사항을 완전히 만족시키지 못하기 때문에 주된 대답으로 표시 할 수는 없습니다. – Hazok

+0

@Zach : 나는 많이 추측했다. 나는 그것이 어떻게 이루어질 수 있는지보고 싶다. 내 이해는 불가능하다는 것이지만 다르게 보여주고 싶습니다. –

+0

나는 내가 가야 할 위의 대답을 게시했는데, 그것에 대해 꽤 놀랐다. 나는 직면했던 많은 문제를 해결했다. – Hazok

18

당신은 가변 인자 매크로와 함께 일을하기 위해 다양한 재귀 매크로 기술을 사용할 수 있습니다 그러나, 유지 보수, 다양성, 구현의 용이성을 위해,이 순간에 최선의 선택이 될 것으로 보인다. 예를 들어, 당신은 가변 인자 매크로 인수의 수를 세는 NUM_ARGS 매크로를 정의 할 수 있습니다 : 다음과

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...) N 

#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 

을, 당신은리스트의 각 요소에 대해 다른 매크로를 확장되는 FOREACH 매크로를 작성할 수 있습니다

#define EXPAND(X)  X 
#define FIRSTARG(X, ...) (X) 
#define RESTARGS(X, ...) (__VA_ARGS__) 
#define FOREACH(MACRO, LIST) FOREACH_(NUM_ARGS LIST, MACRO, LIST) 
#define FOREACH_(N, M, LIST) FOREACH__(N, M, LIST) 
#define FOREACH__(N, M, LIST) FOREACH_##N(M, LIST) 
#define FOREACH_1(M, LIST) M LIST 
#define FOREACH_2(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST) 
#define FOREACH_3(M, LIST) EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST) 
     : 

차례로 당신이 인수의 각을 stringifies 매크로를 정의 할 수 있도록한다 : 거의 다, 그러나 아이디어는 t을 완화입니다

#define STRINGIFY(X) #X 
#define MY_VARIADIC_MACRO(...) FOREACH(STRINGIFY, (__VA_ARGS__)) 
+0

저는 이러한 재귀 적 기법을 알고 있습니다 만, 위에서 보았 듯이 지루하고 또한 컴파일 타임에 고려해야 할 인자의 수에 제한이 있다는 불행한 제한이 있습니다. 구현하기가 지루하지 않고 유지 보수가 쉬운 미리 정의 된 max에 국한되지 않는 솔루션의 세부 정보로 곧 내 대답을 업데이트 할 것입니다. 그것은 모든 경우에 가장 적합한 해결책 일지 모르지만, 내가 필요한 것은 위의 것보다 더 좋은 대답입니다. 입력에 감사드립니다! – Hazok