> 백엔드 개발 > C++ > MSVC와 GCC 사이에서 Variadic 매크로 확장이 다른 이유는 무엇입니까?

MSVC와 GCC 사이에서 Variadic 매크로 확장이 다른 이유는 무엇입니까?

Patricia Arquette
풀어 주다: 2024-11-05 08:36:02
원래의
1160명이 탐색했습니다.

Why Does Variadic Macro Expansion Differ Between MSVC   and GCC?

MSVC의 가변 매크로 확장

MSVC의 가변 매크로 메커니즘은 GCC의 메커니즘과 다르게 동작하므로 매크로를 확장하는 데 어려움이 있습니다. 여러 인수. 다음 매크로를 고려하세요.

<code class="cpp">#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)

#define FULLY_EXPANDED(count, ...) \
  MAC ## count (__VA_ARGS__)

#define SEMI_EXPANDED(count, ...) FULLY_EXPANDED(count, __VA_ARGS__)

#define EXPAND_THESE(...) SEMI_EXPANDED(VA_NARGS(__VA_ARGS__), __VA_ARGS__)

#define ACTUAL_MACRO(x) parent->GetProperty<x>();
#define MAC1(a) ACTUAL_MACRO(a)
#define MAC2(a,b) MAC1(a) ACTUAL_MACRO(b)
#define MAC3(a,b,c) MAC2(a,b) ACTUAL_MACRO(c)
#define MAC4(a,b,c,d) MAC3(a,b,c) ACTUAL_MACRO(d)
#define MAC5(a,b,c,d,e) MAC4(a,b,c,d) ACTUAL_MACRO(e)</code>
로그인 후 복사

GCC에서 이 매크로는 다음으로 확장됩니다.

<code class="cpp">struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1>(); 
    parent->GetProperty<Property2>(); 
    parent->GetProperty<Property3>(); 
    parent->GetProperty<Property4>();
  }

  Base * parent;
}</code>
로그인 후 복사

그러나 MSVC에서는 다음으로 확장됩니다.

<code class="cpp">struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1, Property2, Property3, Property4>();
  }

  Base * parent;
}</code>
로그인 후 복사

설명

MSVC는 매크로 확장을 레벨별로 적용하는 반면 GCC는 매크로를 한 번에 완전히 확장하기 때문에 문제가 발생합니다. 매크로 호출을 고려해보세요:

<code class="cpp">EXPAND_THESE(Property1, Property2, Property3, Property4)</code>
로그인 후 복사
  • MSVC :

    1. VA_NARGS(Property1, Property2, Property3, Property4) -> 4
    2. SEMI_EXPANDED(4, Property1, Property2, Property3, Property4) -> MAC4(속성1, 속성2, 속성3, 속성4)
    3. EXPAND_THESE(MAC4(속성1, 속성2, 속성3, 속성4)) -> MAC4(속성1, 속성2, 속성3, 속성4)
  • GCC:

    1. VA_NARGS(속성1, 속성2, 속성3, 재산4) -> 4
    2. SEMI_EXPANDED(4, Property1, Property2, Property3, Property4) -> MAC4(속성1, 속성2, 속성3, 속성4)
    3. EXPAND_THESE(MAC4(속성1, 속성2, 속성3, 속성4)) -> MAC4(속성1, 속성2, 속성3, 속성4)
      --> MAC4 매크로를 더욱 펼칩니다
      --> 여러 줄의 ACTUAL_MACRO 호출과 동일

해결 방법

GCC와 유사한 동작을 달성하려면 Jeff Walden의 접근 방식을 사용할 수 있습니다. 추가 매크로 도우미를 만들고 COUNT_ARGS_MAX5 매크로를 사용하여 인수 수를 결정합니다.

<code class="cpp">#define FOO_CHOOSE_HELPER1(count) FOO##count
#define FOO_CHOOSE_HELPER2(count) FOO_CHOOSE_HELPER1(count)
#define FOO_CHOOSE_HELPER(count) FOO_CHOOSE_HELPER2(count)

#define ERROR(...) GLUE(FOO_CHOOSE_HELPER(COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__))

#define ASSERT1(expr) singleArgumentExpansion(expr)
#define ASSERT2(expr, explain) twoArgumentExpansion(expr, explain)
#define ASSERT(...) GLUE(FOO_CHOOSE_HELPER(COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__))</code>
로그인 후 복사

또는 "GLUE" 매크로에서 제공하는 추상화를 사용하여 해결 방법을 단순화할 수 있습니다.

<code class="cpp">#define OVERLOAD_MACRO2(name, count) name##count
#define OVERLOAD_MACRO1(name, count) OVERLOAD_MACRO2(name, count)
#define OVERLOAD_MACRO(name, count) OVERLOAD_MACRO1(name, count)

#define CALL_OVERLOAD(name, ...) GLUE(OVERLOAD_MACRO(name, COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__))

#define ERROR1(title) printf("Error: %s\n", title);
#define ERROR2(title, message) \
    ERROR1(title); \
    printf("Message: %s\n", message);
#define ERROR(...) CALL_OVERLOAD(ERROR, __VA_ARGS__);

#define ASSERT1(expr) singleArgumentExpansion(expr)
#define ASSERT2(expr, explain) twoArgumentExpansion(expr, explain)
#define ASSERT(...) CALL_OVERLOAD(ASSERT, __VA_ARGS__);</code>
로그인 후 복사

위 내용은 MSVC와 GCC 사이에서 Variadic 매크로 확장이 다른 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿