在MACRO(X)(Y)中翻转X和Y的顺序

时间:2019-02-12 20:08:10

标签: c++ c-preprocessor

我有一个基于C ++宏的DSL,它定义了这样的宏:

#define RETURNS(...) \
    enable_if_t<__VA_ARGS__ WHEN

#define WHEN(...) \
    , EAT_ ## __VA_ARGS__ >

#define EAT_requires

这是用于以下用途:

template<class T>
auto some_function(T t) ->
    RETURNS(int)
        (requires SomeConcept<T>)

其中扩展到:

template<class T>
auto some_function(T t) ->
    enable_if_t<int, SomeConcept<T>>

(启用C ++ 20概念后,它将扩展为真实的requires子句。)

我希望将参数的顺序翻转。也就是说,我希望它生成此:

template<class T>
auto some_function(T t) ->
    enable_if_t<SomeConcept<T>, int>

我认为这是不可能的。某些聪明的PP黑客能证明我错了吗?

4 个答案:

答案 0 :(得分:4)

如果可以忽略开放的括号,则可以这样实现:

#define UNWRAP(...) __VA_ARGS__

#define RETURNS(...) \
    WHEN ((__VA_ARGS__),

#define WHEN(x, ...) \
    enable_if_t<EAT_ ## __VA_ARGS__, UNWRAP x>

#define EAT_requires

template<class T>
auto some_function(T t) ->
    RETURNS(pair<int, int>)
        requires SomeConcept<T, int>)

输入:

template<class T>
auto some_function(T t) ->
    RETURNS(pair<int, int>)
        requires SomeConcept<T, int>)

输出:

template<class T>
auto some_function(T t) ->
    enable_if_t< SomeConcept<T, int>, pair<int, int> >

答案 1 :(得分:2)

为什么你不只是使用类似的东西

template<class T,bool B>
using reverse_enable_if_t=enable_if_t<B,T>;

答案 2 :(得分:0)

对此的另一种看法是:

#define RETURNS(...) REVERSE_ENABLE_IF_T((__VA_ARGS__))
#define REQUIRES ),(
#define UNWRAP(...) __VA_ARGS__        
#define REVERSE_ENABLE_IF_T(PT,PB) enable_if_t<UNWRAP PB,UNWRAP PT>

允许以下parens-balanced语法:

template<class T>
auto some_function(T t) ->
  RETURNS(pair<int, int> REQUIRES SomeConcept<T, int>);

答案 3 :(得分:0)

这里的解决方案不需要括号不匹配,但是需要在整个对象周围添加一个EVAL宏:

#define EVAL( ... )  EVAL1( __VA_ARGS__ )
#define EVAL1( ... ) EVAL0( EVAL0( EVAL0( __VA_ARGS__ ) ) )
#define EVAL0( ... ) __VA_ARGS__

#define EMPTY()
#define DEFER( ... ) __VA_ARGS__ EMPTY()

#define EAT_requires
#define SWAP( X, Y )   enable_if_t<EAT_##Y, X>
#define RETURNS( X )   DEFER( SWAP )( X, ADD_PAREN
#define ADD_PAREN( Y ) Y )

然后您可以编写以下内容:

EVAL(
  template<class T>
  auto some_function(T t) ->
    RETURNS(int)
      (requires SomeConcept<T>)
)

它会产生:

template<class T>
auto some_function( T t ) ->
  enable_if_t<SomeConcept<T>, int>