我有一个基于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黑客能证明我错了吗?
答案 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>