> 백엔드 개발 > C++ > 본문

MSVC 가변 매크로 확장이 GCC와 다른 이유는 무엇이며 이러한 불일치를 어떻게 극복할 수 있습니까?

Barbara Streisand
풀어 주다: 2024-11-06 09:10:02
원래의
795명이 탐색했습니다.

Why does MSVC   variadic macro expansion differ from GCC, and how can we overcome this discrepancy?

MSVC Variadic 매크로 확장

Variadic 매크로는 다양한 확장 기능을 제공하므로 매크로 내에서 여러 인수를 처리할 수 있습니다. 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>
로그인 후 복사

MSVC 확장 동작

그러나 Microsoft의 C 컴파일러(MSVC)에서는 매크로 확장이 다르게 동작합니다. . 각 인수를 개별적으로 확장하는 대신 MSVC는 모든 인수를 단일 표현식으로 연결합니다.

struct MyStructure<br>{<br> void Foo()<br> {</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">EXPAND_THESE(Property1, Property2, Property3, Property4)
로그인 후 복사

}

기본 * 상위;
};

GCC 확장:

{<br> void Foo()<br> {</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">parent->GetProperty<Property1>(); parent->GetProperty<Property2>(); parent->GetProperty<Property3>(); parent->GetProperty<Property4>();</p> <p>}</p> <p>Base * parent;<br>}<br>

MSVC 확장:

struct MyStructure<br>{<br> void Foo()<br> {</p>
<pre class="brush:php;toolbar:false">parent->GetProperty<Property1, Property2, Property3, Property4>();
로그인 후 복사

}

Base * parent;
}

해결책:

Jeff Walden은 다음을 사용하여 해결 방법을 제안했습니다. 다음 패턴:

<code class="cpp">#define ERRORn(...) ERROR_CHOOSE_HELPERn(COUNT_ARGS_MAX5(__VA_ARGS__), __VA_ARGS__)
#define ERROR_CHOOSE_HELPER1(count) ERROR1
#define ERROR_CHOOSE_HELPER2(count) ERROR2
#define ERROR_CHOOSE_HELPER(count) ERROR_CHOOSE_HELPER##count</code>
로그인 후 복사

이 접근 방식을 사용하려면 원하는 각 가변 매크로 수(예: ERROR1, ERROR2 등)에 대해 CHOOSE_HELPER 매크로를 정의해야 합니다. 그러나 가변 매크로 정의 범위 내에서 각 CHOOSE_HELPER 매크로를 선언하는 것이 중요합니다.

더 간결하고 이식 가능한 솔루션은 다음 기술을 활용하는 것입니다.

<code class="cpp">#define GLUE(x, y) x y

#define RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, count, ...) count
#define EXPAND_ARGS(args) RETURN_ARG_COUNT args
#define COUNT_ARGS_MAX5(...) EXPAND_ARGS((__VA_ARGS__, 5, 4, 3, 2, 1, 0))

#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__))</code>
로그인 후 복사

이 설정을 사용하면 , 매크로는 다음과 같이 정의할 수 있습니다.

<code class="cpp">#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>
로그인 후 복사

OVERLOAD_MACRO 계층 구조를 사용하면 CHOOSE_HELPER 매크로 정의를 피할 수 있습니다.

위 내용은 MSVC 가변 매크로 확장이 GCC와 다른 이유는 무엇이며 이러한 불일치를 어떻게 극복할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
이전 기사:Qt를 사용하여 사용자 정의 클래스를 어떻게 직렬화할 수 있습니까? 다음 기사:문자열 리터럴 내에 큰따옴표를 포함하는 방법은 무엇입니까?
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
최신 이슈
관련 주제
더>
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!