有一个库,它接受在编译时定义行格式的结构。不同的用户具有不同的结构变体。
一个例子:
typedef struct { INT16U a, INT32S b } logrow_t;
在运行时,我想迭代这个结构并打印每个元素及其类型。
首先想到的解决方案是构建一个表:
typedef struct { char var_name[16], char var_type[16], int bytelen } logrow_desc_t;
logrow_desc_t descriptions[] = { { "a", "INT16U", 2 }, { "b", "INT32S", 4 } };
是否有更好的解决方案允许库的任何用户指定不同的行结构?有没有办法利用预处理器/编译器在编译时构建描述表?
答案 0 :(得分:0)
有没有办法利用预处理器/编译器来构建 编译时的描述表?
如果您和您的用户不介意在宏中指定行格式(让我们说LOGROW
)而不是直接在logrow_t
的定义中指定行格式,请参阅此ppnarg.h
中描述的方法的变体可以使用{3}}
我将通用的,可重用的部分放在文件/*
* The PP_NARG macro evaluates to the number of arguments that have been
* passed to it.
* Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
*/
#define PP_NARG(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
/* need extra level to force extra eval */
#define Paste(a,b) a ## b
#define XPASTE(a,b) Paste(a,b)
/* APPLYXn variadic X-Macro by M Joshua Ryan */
/* Free for all uses. Don't be a jerk. */
/* I got bored after typing 15 of these. */
/* You could keep going upto 64 (PPNARG's limit). */
#define APPLYX1(a) X(a)
#define APPLYX2(a,b) X(a) X(b)
#define APPLYX3(a,b,c) X(a) X(b) X(c)
#define APPLYX4(a,b,c,d) X(a) X(b) X(c) X(d)
#define APPLYX5(a,b,c,d,e) X(a) X(b) X(c) X(d) X(e)
#define APPLYX6(a,b,c,d,e,f) X(a) X(b) X(c) X(d) X(e) X(f)
#define APPLYX7(a,b,c,d,e,f,g) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g)
#define APPLYX8(a,b,c,d,e,f,g,h) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h)
#define APPLYX9(a,b,c,d,e,f,g,h,i) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i)
#define APPLYX10(a,b,c,d,e,f,g,h,i,j) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j)
#define APPLYX11(a,b,c,d,e,f,g,h,i,j,k) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k)
#define APPLYX12(a,b,c,d,e,f,g,h,i,j,k,l) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l)
#define APPLYX13(a,b,c,d,e,f,g,h,i,j,k,l,m) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m)
#define APPLYX14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n)
#define APPLYX15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n) X(o)
#define APPLYX_(M, ...) M(__VA_ARGS__)
#define APPLYXn(...) APPLYX_(XPASTE(APPLYX, PP_NARG(__VA_ARGS__)), __VA_ARGS__)
//#define ZIP2(a,b) /* to be defined by application */
#define ZIP4(a,b,c,d) ZIP2(a,b) ZIP2(c,d)
#define ZIP6(a,b,c,d,e,f) ZIP4(a,b,c,d) ZIP2(e,f)
#define ZIP8(a,b,c,d,e,f,g,h) ZIP6(a,b,c,d,e,f) ZIP2(g,h)
#define ZIP10(a,b,c,d,e,f,g,h,i,j) ZIP8(a,b,c,d,e,f,g,h) ZIP2(i,j)
#define ZIP12(a,b,c,d,e,f,g,h,i,j,k,l) ZIP10(a,b,c,d,e,f,g,h,i,j) ZIP2(k,l)
// define more of those ZIPxx() if more arguments are needed
#define ZIP(...) APPLYX_(XPASTE(ZIP, PP_NARG(__VA_ARGS__)), __VA_ARGS__)
中:
// only this line is to be defined by the users:
#define LOGROW INT16U, a, INT32S, b
// the following defines `logrow_t` and `descriptions` according to the above:
#include <stddef.h>
#include "ppnarg.h"
#define ZIP2(a, b) a b;
typedef struct { ZIP(LOGROW) } logrow_t;
#undef ZIP2
typedef struct { char *name, *type; size_t size; } logrow_desc_t;
#define ZIP2(a, b) { #b, #a, sizeof (a) },
logrow_desc_t descriptions[] = { ZIP(LOGROW) };
#undef ZIP2
在您的应用程序中,可以这样使用:
SELECT p.id,p.title
FROM product_products p
LEFT JOIN product_attribute_values v ON v.product_id = p.id
LEFT JOIN product_attribute_options o ON o.id = v.option_id
WHERE (p.id = 82 OR p.parent_id = 82)
AND (o.id IN (25, 3))
GROUP BY p.id,p.title
HAVING COUNT(DISTINCT o.id) = 2