Отразите порядок X и Y в MACRO (X) (Y) - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть DSL на основе макросов C ++, который определяет макрос следующим образом:

#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 голосов
/ 17 августа 2019

Вот решение, которое не требует непревзойденных скобок, но требует добавления макроса 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>
0 голосов
/ 13 февраля 2019

Почему бы вам просто не использовать что-то вроде

template<class T,bool B>
using reverse_enable_if_t=enable_if_t<B,T>;
0 голосов
/ 15 февраля 2019

Это еще один вариант:

#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>

, который допускает следующий синтаксис, сбалансированный по паренсу:

template<class T>
auto some_function(T t) ->
  RETURNS(pair<int, int> REQUIRES SomeConcept<T, int>);
0 голосов
/ 13 февраля 2019

Если допустимо опускать открытого парена, вы можете добиться этого следующим образом:

#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> >
...