2017-12-31 134 views
16

C++ 20에서 전 처리기는 인수의 수가 0보다 큰 경우 variadic 매크로에서 선택적으로 토큰을 확장하는 방법으로 __VA_OPT__을 지원합니다. (이식성이없고 못생긴 해킹 인 ##__VA_ARGS__ GCC 확장이 필요하지 않습니다.)__VA_OPT__ 지원을 이동 가능하게 감지합니까?

Clang SVN이이 기능을 구현했지만 기능 테스트 매크로를 추가하지 않았습니다. 영리한 전처리 기의 해커가 하드 오류 또는 이식성 경고를 일으키지 않고 __VA_OPT__ 지원의 유무를 감지하는 방법을 찾아 낼 수 있습니까? 같은

답변

20

chris's answer에서 영감을 얻었습니다. __VA_OPT__가 지원되면 제 인수 true 그래서

#define PP_THIRD_ARG(a,b,c,...) c 
#define VA_OPT_SUPPORTED_I(...) PP_THIRD_ARG(__VA_OPT__(,),true,false,) 
#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?) 

, VA_OPT_SUPPORTED_I(?)PP_THIRD_ARG(,,true,false,)로 확장; 그렇지 않은 경우 VA_OPT_SUPPORTED_I(?)PP_THIRD_ARG(__VA_OPT__(,),true,false,)으로 확장되고 세 번째 인수는 false이됩니다.

+0

이것은 내가 광산을 개선 할 수 있다고 말했을 때 상상했던 간결함의 종류입니다. 멋진 일 :) – chris

+0

NICE. 고맙습니다. –

5

뭔가 당신이 그것을 향상시킬 수 있습니다 있지만, 다음과 같은 작업을해야합니다 : 연타 트렁크에

#include <boost/preprocessor.hpp> 

#define VA_OPT_SUPPORTED_II_1(_) 0 
#define VA_OPT_SUPPORTED_II_2(_1, _2) 1 

#define VA_OPT_SUPPORTED_I(...) BOOST_PP_OVERLOAD(VA_OPT_SUPPORTED_II_, __VA_OPT__(,))(__VA_OPT__(,)) 

#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?) 

,이 C++ (17) 모드에서 C++ 2A 모드 0에서 1로 평가합니다. GCC 트렁크는 실제로 이것을 C++ 17에서 1로 평가하지만 그 모드에서는 __VA_OPT__도 처리합니다. 이것은 무엇을

인수의 수에 따라 _II_1 또는 _2 버전 중 하나를 호출하는 사용 BOOST_PP_OVERLOAD입니다. __VA_OPT__(,),으로 확장되면 2 개의 빈 인수가 있습니다. 그렇지 않은 경우 빈 인수가 1 개 있습니다. 항상이 매크로를 인수 목록으로 부르기 때문에 __VA_OPT__을 지원하는 컴파일러는 항상 ,으로 확장해야합니다.

당연히 Boost.PP 의존성은 필수 사항이 아닙니다. 간단한 1-or-2-arg OVERLOAD 매크로는 쉽게 교체 할 수 있어야합니다. 일반성을 조금 잃는 것이 더 간단 만들려면 :

#define OVERLOAD2_I(_1, _2, NAME, ...) NAME 
#define OVERLOAD2(NAME1, NAME2, ...) OVERLOAD2_I(__VA_ARGS__, NAME2, NAME1) 

#define VA_OPT_SUPPORTED_I(...) OVERLOAD2(VA_OPT_SUPPORTED_II_1, VA_OPT_SUPPORTED_II_2, __VA_OPT__(,))(__VA_OPT__(,)) 

연타에서 경고 한 휴대있다 :

경고 : 가변 인자 매크로는 C++ 98 [-WC++ 98 -와 호환되지 않는 compat-pedantic]

C++ 11 가변 매크로 지원없이이 탐지가 가능할 지 모르겠습니다. __cplusplus 값이 C++ 11보다 낮다고 가정 할 수도 있지만 Clang은 이러한 검사를 래핑해도 경고를 표시합니다.

+0

내가이 답변을 받아 싶지만, 내가 종속성을 필요로하지 않으며, 내가이 없습니다 PP 기술은'OVERLOAD'를 구현합니다. Boost.PP 의존성을 제거하는 치료? –

+0

@EricNiebler, 예. 그동안 [이 중 하나] (https://stackoverflow.com/questions/11761703/overloading-macro-on-number-of-arguments)를 비롯한 여러 가지 질문이 있습니다. – chris

2

다른 답변에서 언급했듯이 OVERLOAD 매크로를 작성할 수 있습니다. BOOST_PP_OVERLOADBOOST_PP_CATBOOST_PP_VARIADIC_SIZE의 두 부분으로 구성됩니다. 그러나, 부스트와 달리, 당신은 단지 약 2 args 신경.그래서 :

#define CAT(a, b) KITTY((a, b)) 
#define KITTY(par) MEOW ## par 
#define MEOW(a, b) a ## b 

그리고 VARIADIC :

#define OVERLOAD(prefix, ...) CAT(prefix, VARIADIC(__VA_ARGS__)) 

CAT는 모양을

#define VARIADIC(...) _VARIADIC_(__VA_ARGS__, 2, 1,) 
#define _VARIADIC_(e0, e1, size, ...) size