Ну что ж... вот начало решения для макросов с использованием библиотеки препроцессора boost (совместимой с препроцессором C99).
Идея заключалась в том, чтобы предоставить общий синтаксис, который позволяет писать вложенные общие выборки для произвольного количества аргументов. Чтобы сделать его «простым», выражение для выбора одинаково для всех элементов на одном и том же уровне выбора (вы можете определить другой синтаксис, чтобы изменить управляющее выражение для каждого выбора уровня индивидуально...).
Этот пример из ОП
#define plop(a,b) _Generic((a,b), \
(int,long): plopii, \
(double,short int): plopdd)(a,b)
становится
#define plop(a,b) \
MULT_GENERIC((a,b), \
(int, (long, plopii)), \
(double, (short int, plopdd)) \
)(a,b)
Хотя я думаю, что его можно немного изменить, чтобы получить что-то вроде:
#define plop(a,b) \
MULT_GENERIC((a,b), \
(int, long: plopii), \
(double, short int: plopdd) \
)(a,b)
Который может расширяться по трем параметрам до:
#define plop(a,b,c) \
MULT_GENERIC((a,b,c), \
(int, (double, long: plopidl, int: plopidi)), \
(double, (short int, long: plopdsl)) \
)(a,b)
Еще один комментарий: я думаю, что синтаксис OP также можно было бы сделать, но он не такой гибкий, так как вам нужно повторять первый аргумент для каждого возможного второго аргумента, например.
#define plop(a,b) _Generic((a,b), \
(int,long): plopii, \
(int,double): plobid \
(double,short int): plopdd)(a,b)
Пример OP в моем синтаксисе. Обратите внимание, что вы не получите здесь многого, так как вам все равно придется указывать каждый тип отдельно, и в этом случае второй тип несколько раз для разных первых типов.
#define pow(x, y) MULT_GENERIC( \
(x, y), \
(long double complex, (default, cpowl) \
), \
(double complex, (long double complex, cpowl) \
, (default, cpow) \
), \
(float complex, (long double complex, cpowl) \
, (double complex, cpow) \
, (default, cpowf) \
), \
(long double, (long double complex, cpowl) \
, (double complex, cpow) \
, (float complex, cpowf) \
, (default, powl) \
), \
(default, (long double complex, cpowl) \
, (double complex, cpow) \
, (float complex, cpowf) \
, (long double, powl) \
, (default, pow) \
), \
(float, (long double complex, cpowl) \
, (double complex, cpow) \
, (float complex, cpowf) \
, (long double, powl) \
, (float, powf) \
, (default, pow) \
) \
) \
(x, y)
pow(x, y)
Это решается:
_Generic( (x), long double complex : _Generic( (y), default : cpowl ) , double complex : _Generic( (y), long double complex : cpowl , default : cpow ) , float complex : _Generic( (y), long double complex : cpowl , double complex : cpow , default : cpowf ) , long double : _Generic( (y), long double complex : cpowl , double complex : cpow , float complex : cpowf , default : powl ) , default : _Generic( (y), long double complex : cpowl , double complex : cpow , float complex : cpowf , long double : powl , default : pow ) , float : _Generic( (y), long double complex : cpowl , double complex : cpow , float complex : cpowf , long double : powl , float : powf , default : pow ) ) (x, y)
То есть, переформатированный:
_Generic((x),
long double complex: _Generic((y), default: cpowl)
, double complex: _Generic((y),
long double complex: cpowl
, default: cpow)
, float complex: _Generic((y),
long double complex: cpowl
, double complex: cpow
, default: cpowf)
, long double: _Generic((y),
long double complex: cpowl
, double complex: cpow
, float complex: cpowf
, default: powl)
, default: _Generic((y),
long double complex: cpowl
, double complex: cpow
, float complex: cpowf
, long double: powl
, default: pow)
, float: _Generic((y)
, long double complex: cpowl
, double complex: cpow
, float complex: cpowf
, long double: powl
, float : powf
, default: pow)
)
(x, y)
Из-за рекурсивного характера мне пришлось вводить копии макросов; это решение также нуждается в очистке (я немного устал). Макросы:
#include <boost/preprocessor.hpp>
#define MULT_GENERIC_GET_ASSOC_SEQ(DATA_TUPLE) \
BOOST_PP_TUPLE_ELEM(2, DATA_TUPLE)
#define MULT_GENERIC_NTH_ASSOC_TUPLE(N, DATA_TUPLE) \
BOOST_PP_SEQ_ELEM( N, MULT_GENERIC_GET_ASSOC_SEQ(DATA_TUPLE) )
#define MULT_GENERIC_GET_TYPENAME(N, DATA_TUPLE) \
BOOST_PP_TUPLE_ELEM(0, MULT_GENERIC_NTH_ASSOC_TUPLE(N, DATA_TUPLE))
#define MULT_GENERIC_GET_EXPR( N, DATA_TUPLE ) \
BOOST_PP_TUPLE_ELEM(1, MULT_GENERIC_NTH_ASSOC_TUPLE(N, DATA_TUPLE))
#define MULT_GENERIC_LEVEL_REP1(z, N, DATA_TUPLE) \
MULT_GENERIC_GET_TYPENAME( N, DATA_TUPLE ) \
: \
BOOST_PP_TUPLE_ELEM(1, DATA_TUPLE) /*LEVEL_MACRO*/ ( \
BOOST_PP_TUPLE_ELEM(0, DATA_TUPLE) /*SEL_EXPR_SEQ*/ \
, BOOST_PP_SEQ_POP_FRONT( BOOST_PP_TUPLE_TO_SEQ(MULT_GENERIC_NTH_ASSOC_TUPLE(N, DATA_TUPLE)) ) \
)
#define MULT_GENERIC_LEVEL1(SEL_EXPR_SEQ, LEVEL_MACRO, ASSOC_SEQ) \
_Generic( \
(BOOST_PP_SEQ_HEAD(SEL_EXPR_SEQ)), \
BOOST_PP_ENUM( BOOST_PP_SEQ_SIZE(ASSOC_SEQ), MULT_GENERIC_LEVEL_REP1, (BOOST_PP_SEQ_POP_FRONT(SEL_EXPR_SEQ), LEVEL_MACRO, ASSOC_SEQ) ) \
)
#define MULT_GENERIC_LEVEL_REP2(z, N, DATA_TUPLE) \
MULT_GENERIC_GET_TYPENAME( N, DATA_TUPLE ) \
: \
BOOST_PP_TUPLE_ELEM(1, DATA_TUPLE) /*LEVEL_MACRO*/ ( \
BOOST_PP_TUPLE_ELEM(0, DATA_TUPLE) /*SEL_EXPR_SEQ*/ \
, BOOST_PP_SEQ_POP_FRONT( BOOST_PP_TUPLE_TO_SEQ(MULT_GENERIC_NTH_ASSOC_TUPLE(N, DATA_TUPLE)) ) \
)
#define MULT_GENERIC_LEVEL2(SEL_EXPR_SEQ, LEVEL_MACRO, ASSOC_SEQ) \
_Generic( \
(BOOST_PP_SEQ_HEAD(SEL_EXPR_SEQ)), \
BOOST_PP_ENUM( BOOST_PP_SEQ_SIZE(ASSOC_SEQ), MULT_GENERIC_LEVEL_REP2, (BOOST_PP_SEQ_POP_FRONT(SEL_EXPR_SEQ), LEVEL_MACRO, ASSOC_SEQ) ) \
)
#define MULT_GENERIC0(SEL_EXPR_SEQ, ASSOC_SEQ) \
BOOST_PP_SEQ_HEAD(ASSOC_SEQ)
#define MULT_GENERIC1(SEL_EXPR_SEQ, ASSOC_SEQ) \
MULT_GENERIC_LEVEL1( SEL_EXPR_SEQ, MULT_GENERIC0, ASSOC_SEQ )
#define MULT_GENERIC2(SEL_EXPR_SEQ, ASSOC_SEQ) \
MULT_GENERIC_LEVEL2( SEL_EXPR_SEQ, MULT_GENERIC1, ASSOC_SEQ )
#define MULT_GENERIC(SEL_EXPR_TUPLE, ...) \
BOOST_PP_CAT(MULT_GENERIC, BOOST_PP_TUPLE_SIZE(SEL_EXPR_TUPLE)) ( BOOST_PP_TUPLE_TO_SEQ(SEL_EXPR_TUPLE), BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)) )
person
dyp
schedule
26.06.2013
_Generic
являетсяassignment-expression
, тип которого определяет, какой элемент списка выражений (например,cpowl
,cpow
и т. д.) выбран. Таким образом, невозможно использовать одно выделение_Generic
для выбора на основе двух типов/двух выражений. - person dyp   schedule 25.06.2013#define Power2Mask(BitOrder,Bits2Mask) _Generic((BitOrder) ... ) (Bits2Mask)
или#define Power2Mask(BitOrder,Bits2Mask) _Generic((BitOrder,Bits2Mask) ... ) (BitOrder,Bits2Mask)
? Clang вообще не помогает отлаживать это - person MarcusJ   schedule 29.07.2017