2013-05-04 8 views
3

각 args에 대한 정적 함수를 호출하는 매크로가 있습니다. 예를 들어__VA_ARGS__를 추출하는 방법은 무엇입니까?

:

#define FOO(X) X::do(); 
#define FOO_1(X,Y) X::do(); Y::do(); 

내 질문은 내가 인수의 변수 번호 foo는 사용할 필요가있다, 그것은 __VA_ARGS__를 사용할 수 있습니까? 아래 라인처럼

:

#define FOO(...) __VA_ARGS__::do() ? 

감사

+3

미래에는 질문의 미리보기를보기 위해 5 초 정도 걸리면 형식이 완전히 엉망이되었음을 깨달은 다음 정리를 시도하면 사람이 쉽게 찾을 수 있습니다. 대답. :) SO * *는 코드 형식 지정 기능을 제공합니다. 코드를 선택하고 버튼을 눌러야합니다. – jalf

+0

'C++ 11'을 사용할 수 있습니까? – StoryTeller

+0

대신 variadic 템플릿을 사용하십시오 ... –

답변

5

매크로 확장은 가변 인자 템플릿 인수 팩 확장처럼 작동하지 않습니다. 당신이 희망으로

X::do(); Y::do(); 

X,Y::do(); 

그리고하지 : 당신은에 확장됩니다 무엇을 가지고. 하지만 C++ 11에서는 가변성 템플릿을 사용할 수 있습니다. 예를 들어, 당신은 당신이 이런 식으로 원하는 것을 할 수 있습니다 : 여기

namespace detail 
{ 
    template<typename... Ts> 
    struct do_foo; 

    template<typename T, typename... Ts> 
    struct do_foo<T, Ts...> 
    { 
     static void call() 
     { 
      T::foo(); 
      do_foo<Ts...>::call(); 
     } 
    }; 

    template<typename T> 
    struct do_foo<T> 
    { 
     static void call() 
     { 
      T::foo(); 
     } 
    }; 
} 

template<typename... Ts> 
void do_foo() 
{ 
    detail::do_foo<Ts...>::call(); 
} 

live example입니다 : 당신이 필요로하는 모든이 (비교적 간단한) 기계입니다

#include <iostream> 

struct X { static void foo() { std::cout << "X::foo()" << std::endl; }; }; 
struct Y { static void foo() { std::cout << "Y::foo()" << std::endl; }; }; 
struct Z { static void foo() { std::cout << "Z::foo()" << std::endl; }; }; 

int main() 
{ 
    do_foo<X, Y, Z>(); 
} 

.

+0

그것은 효과. 고맙습니다. – Kennir

+0

@Kennir : 프로젝트에 도움이 되었기 때문에 기꺼이 도와 드리겠습니다. –

+0

btw : 다른 템플릿 인수가있는 세 가지 기능이 필요한 이유는 무엇입니까? – Kennir

1

직접 할 수는 없지만 항상 __VA_ARGS__은 모든 매개 변수가 쉼표로 구분 된 단일 단위로 처리됩니다. 전처리 기는 매개 변수의 수를 찾고, 매개 변수의 수를 찾고, 매개 변수의 수를 찾거나 매개 변수의 루프를 반복 할 수있는 내장 된 방법을 제공하지 않습니다.

This answer 유사한 질문에 대한 전 문답은 전처리기를 사용하는 기본 해결 방법을 보여줍니다. 인수 목록에있는 항목 수를 확인하고 정확한 양의 매개 변수를 사용하는 매크로에 전달합니다.

나는 이것을하지 말고 대신 Andy Prowls C++11 solution을 사용하거나 코드를 재구성하여 전혀 필요가 없도록하는 것이 좋습니다.

1

사실 부분적으로이 문제를 해결할 수 있습니다.
__VA_ARGS__과 C++ 11의 가변 템플릿 모두를 직접 자유롭게 추출 할 수 있습니다. 그러나 당신은 첫 번째 요소를 가질 수 있습니다. 예를 들어 OUT(...)이라는 매크로가 있고 std :: cout을 생성한다고 가정 해 봅시다. C : < < A < B < < C ... 여기서 A, B, C는 매크로의 가변 인수입니다. 이것을 시도하십시오 :

#include <iostream> 

#define SEPERATOR << 
#define GET_1_OF(element1, ...) element1 
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__) 
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__) 
#define BAR(...) GET_3_OF(__VA_ARGS__) 
int main() 
{ 
    std::cout << BAR(1,2,3,4,5); 
    return 0; 
} 

물론 이것은 해결책이 아닙니다. 그러나 원하는 것을하기 위해 GET_N_OF의 숫자를 늘릴 수 있습니다. SEPERATOR<<이므로 MACRO는 1 << 2 << 3 등으로 쓸 수 있습니다.
이제이 코드에 문제가 있습니다. BAR(1,2,3,4,5)BAR(1)으로 변경하십시오. 오류가 발생하는 것을 확인할 수 있습니다. 이것은 우리가 여분의 SEPERATOR을 가지고 있기 때문에 더 많은 논쟁 (variadic이기 때문에)이 문제가 아니지만 3 개의 인자를 기대했기 때문입니다.(당신이 인수의 수를 알고 있기 때문에) 그래서이 문제를 해결하기 위해 대신 BAR(...) 사용 GET_N_OF(...) 사용에 :

#include <iostream> 

#define SEPERATOR << 
#define GET_1_OF(element1, ...) element1 
#define GET_2_OF(element1, ...) element1 SEPERATOR GET_1_OF(__VA_ARGS__) 
#define GET_3_OF(element1, ...) element1 SEPERATOR GET_2_OF(__VA_ARGS__) 
#define GET_4_OF(element1, ...) element1 SEPERATOR GET_3_OF(__VA_ARGS__) 
#define GET_5_OF(element1, ...) element1 SEPERATOR GET_4_OF(__VA_ARGS__) 

int main() 
{ 
    std::cout << GET_5_OF(1,2,3,4,5); 
    std::cout << GET_1_OF(1); 
    return 0; 
} 

당신이 전혀 매크로를 사용하지 않는을 무엇을하고 있는지 모르는 경우주의하시기 바랍니다 ! 내 답변은 당신에게 유익 할 MACRO 코드를 공유하는 것이 었습니다. 나는 그들이 대단히 필요할 때까지 MACRO의 사용을 항상 꺼린다.

관련 문제