diff --git a/m-funcobj.h b/m-funcobj.h index 2653121c..f557c31c 100644 --- a/m-funcobj.h +++ b/m-funcobj.h @@ -83,7 +83,6 @@ * FIXME: How to factorize reasonnably well between the definitions? */ - /* Specialization of the OPLIST in function if there is at least one member or not */ #define FUNC_OBJ_INS_NO_ATTR_OPLIST(name, ...) \ (NAME(name), TYPE(M_C(name, _t)), \ @@ -195,8 +194,39 @@ /* Specialization of the definition a function object instance of name 'name' * with mandatory member attribute. + * First inject oplist in member attributes. */ #define FUNC_OBJ_INS_ATTR_DEF(name, base_name, param_list, callback_core, ...) \ + FUNCOBJI_INS_ATTR_DEF_P2(name, base_name, param_list, callback_core, FUNCOBJI_INJECT_GLOBAL(__VA_ARGS__) ) + +/* Inject the oplist within the list of arguments */ +#define FUNCOBJI_INJECT_GLOBAL(...) \ + M_MAP_C(FUNCOBJI_INJECT_OPLIST_A, __VA_ARGS__) +/* Transform (x, type) into (x, type, oplist) if there is global registered oplist + or (x, type, M_DEFAULT_OPLIST) if there is no global one, + or keep (x, type, oplist) if oplist was already present */ +#define FUNCOBJI_INJECT_OPLIST_A( duo_or_trio ) \ + FUNCOBJI_INJECT_OPLIST_B duo_or_trio +#define FUNCOBJI_INJECT_OPLIST_B( f, ... ) \ + M_IF_NARGS_EQ1(__VA_ARGS__)( (f, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)()), (f, __VA_ARGS__) ) + +// Test if all third argument of all arguments is an oplist +#define FUNCOBJI_IF_ALL_OPLIST(...) \ + M_IF(M_REDUCE(FUNCOBJI_IS_OPLIST_P, M_AND, __VA_ARGS__)) +// Test if the third argument is an oplist +#define FUNCOBJI_IS_OPLIST_P(a) \ + M_OPLIST_P(M_RET_ARG3 a) + +/* Validate the oplist before going further */ +#define FUNCOBJI_INS_ATTR_DEF_P2(name, base_name, param_list, callback_core, ...) \ + FUNCOBJI_IF_ALL_OPLIST(__VA_ARGS__)(FUNCOBJI_INS_ATTR_DEF_P3, FUNCOBJI_INS_ATTR_DEF_FAILURE)(name, base_name, param_list, callback_core, __VA_ARGS__) + +/* Stop processing with a compilation failure */ +#define FUNCOBJI_INS_ATTR_DEF_FAILURE(name, base_name, param_list, callback_core, ...) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(FUNC_OBJ_INS_DEF): at least one of the given argument is not a valid oplist: " #__VA_ARGS__) + +/* Expand the Function Object with members */ +#define FUNCOBJI_INS_ATTR_DEF_P3(name, base_name, param_list, callback_core, ...) \ typedef struct M_C(name, _s) { \ M_C(base_name, _callback_t) callback; \ M_MAP(FUNC_OBJ_INS_ATTR_STRUCT, __VA_ARGS__) \ @@ -245,6 +275,7 @@ , /* END OF INIT METHOD */ ) \ + /* Helper macros */ #define FUNC_OBJ_BASE_TYPE(name, num, type) \ typedef type M_C4(name, _param_, num, _t); diff --git a/m-tuple.h b/m-tuple.h index 9cc0af89..be709dbf 100644 --- a/m-tuple.h +++ b/m-tuple.h @@ -35,6 +35,7 @@ #define TUPLE_DEF2(name, ...) \ TUPLEI_DEF2_P1( (name, TUPLEI_INJECT_GLOBAL(__VA_ARGS__)) ) + /* Define the oplist of a tuple. USAGE: TUPLE_OPLIST(name[, oplist of the first type, ...]) */ #define TUPLE_OPLIST(...) \ @@ -42,7 +43,8 @@ (TUPLEI_OPLIST_P1((__VA_ARGS__, M_DEFAULT_OPLIST )), \ TUPLEI_OPLIST_P1((__VA_ARGS__ ))) -/* Return an array suitable for the _cmp_order function. + +/* Return an array suitable for the WIP _cmp_order function. As compound literals are not supported in C++, provide a separate definition for C++ using initializer_list (shall be constexpr, but only supported in C++14). @@ -71,9 +73,13 @@ namespace m_tuple { /********************************** INTERNAL ************************************/ +/* Inject the oplist within the list of arguments */ #define TUPLEI_INJECT_GLOBAL(...) \ M_MAP_C(TUPLEI_INJECT_OPLIST_A, __VA_ARGS__) +/* Transform (x, type) into (x, type, oplist) if there is global registered oplist + or (x, type, M_DEFAULT_OPLIST) if there is no global one, + or keep (x, type, oplist) if oplist was already present */ #define TUPLEI_INJECT_OPLIST_A( duo_or_trio ) \ TUPLEI_INJECT_OPLIST_B duo_or_trio @@ -83,7 +89,23 @@ namespace m_tuple { // Deferred evaluation #define TUPLEI_DEF2_P1(...) TUPLEI_DEF2_P2 __VA_ARGS__ -#define TUPLEI_DEF2_P2(name, ...) \ +// Test if all third argument of all arguments is an oplist +#define TUPLEI_IF_ALL_OPLIST(...) \ + M_IF(M_REDUCE(TUPLEI_IS_OPLIST_P, M_AND, __VA_ARGS__)) +// Test if the third argument is an oplist +#define TUPLEI_IS_OPLIST_P(a) \ + M_OPLIST_P(M_RET_ARG3 a) + +/* Validate the oplist before going further */ +#define TUPLEI_DEF2_P2(name, ...) \ + TUPLEI_IF_ALL_OPLIST(__VA_ARGS__)(TUPLEI_DEF2_P3, TUPLEI_DEF2_FAILURE)(name, __VA_ARGS__) + +/* Stop processing with a compilation failure */ +#define TUPLEI_DEF2_FAILURE(name, ...) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(TUPLE_DEF2): at least one of the given argument is not a valid oplist: " #__VA_ARGS__) + +/* Define the tuple */ +#define TUPLEI_DEF2_P3(name, ...) \ TUPLE_DEFINE_TYPE(name, __VA_ARGS__) \ TUPLE_DEFINE_ENUM(name, __VA_ARGS__) \ TUPLEI_IF_ALL(INIT, __VA_ARGS__) \ diff --git a/m-variant.h b/m-variant.h index 59133432..be45ca52 100644 --- a/m-variant.h +++ b/m-variant.h @@ -36,6 +36,7 @@ #define VARIANT_DEF2(name, ...) \ VARIANTI_DEF2_P1( (name, VARIANTI_INJECT_GLOBAL(__VA_ARGS__)) ) + /* Define the oplist of a variant. USAGE: VARIANT_OPLIST(name[, oplist of the first type, ...]) */ #define VARIANT_OPLIST(...) \ @@ -46,9 +47,13 @@ /********************************** INTERNAL ************************************/ +/* Inject the oplist within the list of arguments */ #define VARIANTI_INJECT_GLOBAL(...) \ M_MAP_C(VARIANTI_INJECT_OPLIST_A, __VA_ARGS__) +/* Transform (x, type) into (x, type, oplist) if there is global registered oplist + or (x, type, M_DEFAULT_OPLIST) if there is no global one, + or keep (x, type, oplist) if oplist was already present */ #define VARIANTI_INJECT_OPLIST_A( duo_or_trio ) \ VARIANTI_INJECT_OPLIST_B duo_or_trio @@ -58,7 +63,23 @@ // Deferred evaluation #define VARIANTI_DEF2_P1(...) VARIANTI_DEF2_P2 __VA_ARGS__ -#define VARIANTI_DEF2_P2(name, ...) \ +// Test if all third argument of all arguments is an oplist +#define VARIANTI_IF_ALL_OPLIST(...) \ + M_IF(M_REDUCE(VARIANTI_IS_OPLIST_P, M_AND, __VA_ARGS__)) +// Test if the third argument is an oplist +#define VARIANTI_IS_OPLIST_P(a) \ + M_OPLIST_P(M_RET_ARG3 a) + +/* Validate the oplist before going further */ +#define VARIANTI_DEF2_P2(name, ...) \ + VARIANTI_IF_ALL_OPLIST(__VA_ARGS__)(VARIANTI_DEF2_P3, VARIANTI_DEF2_FAILURE)(name, __VA_ARGS__) + +/* Stop processing with a compilation failure */ +#define VARIANTI_DEF2_FAILURE(name, ...) \ + M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(VARIANT_DEF2): at least one of the given argument is not a valid oplist: " #__VA_ARGS__) + +/* Define the variant */ +#define VARIANTI_DEF2_P3(name, ...) \ VARIANTI_DEFINE_TYPE(name, __VA_ARGS__) \ VARIANTI_DEFINE_INIT(name, __VA_ARGS__) \ VARIANTI_DEFINE_CLEAR(name, __VA_ARGS__) \