تلقائيا - كيفية عمل ماكرو في excel 2013




الزائد ماكرو على عدد من الحجج (6)

بسيطة على النحو التالي:

#define GET_MACRO(_1,_2,_3,NAME,...) NAME
#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2)(__VA_ARGS__)

لذلك إذا كان لديك وحدات الماكرو هذه:

FOO(World, !)         # expands to FOO2(World, !)
FOO(foo,bar,baz)      # expands to FOO3(foo,bar,baz)

إذا كنت تريد رابعًا:

#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define FOO(...) GET_MACRO(__VA_ARGS__, FOO4, FOO3, FOO2)(__VA_ARGS__)

FOO(a,b,c,d)          # expeands to FOO4(a,b,c,d)

وبطبيعة الحال ، إذا قمت بتعريف FOO2 و FOO3 و FOO4 ، فسيتم استبدال المخرجات بوحدات الماكرو المحددة.

لدي اثنين من وحدات الماكرو FOO2 و FOO3 :

#define FOO2(x,y) ...
#define FOO3(x,y,z) ...

أريد تعريف ماكرو جديد FOO كالتالي:

#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)

ولكن هذا لا يعمل لأن وحدات الماكرو لا تفرط في عدد من الحجج.

بدون تعديل FOO2 و FOO3 ، هل هناك طريقة لتعريف FOO ماكرو (باستخدام __VA_ARGS__ أو غير ذلك) للحصول على نفس التأثير لإرسال FOO(x,y) إلى FOO2 و FOO(x,y,z) إلى FOO3 ؟


ربما يمكنك استخدام هذا الماكرو لحساب عدد الوسائط .

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5,4,3,2,1)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N

كنت مجرد بحث هذا بنفسي ، ووجدت هذا here . وأضاف المؤلف دعم الوسيطة الافتراضية لوظائف C عبر وحدات الماكرو.

سأحاول تلخيص المقالة باختصار. بشكل أساسي ، تحتاج إلى تعريف ماكرو يمكنه حساب الوسائط. سيعود هذا الماكرو 2 أو 1 أو 0 أو أي نطاق من الوسيطات التي يمكنه دعمها. على سبيل المثال:

#define _ARG2(_0, _1, _2, ...) _2
#define NARG2(...) _ARG2(__VA_ARGS__, 2, 1, 0)

مع هذا ، تحتاج إلى إنشاء ماكرو آخر يأخذ عدد متغير من الوسيطات ، يحسب الوسائط ، ويستدعي الماكرو المناسب. لقد أخذت مثالك الكلي ودمجته مع مثال المقالة. لدي وظيفة استدعاء FOO1 a () ووظيفة استدعاء FOO2 a مع الوسيطة b (من الواضح أنني أفترض C ++ هنا ، ولكن يمكنك تغيير الماكرو إلى أي شيء).

#define FOO1(a) a();
#define FOO2(a,b) a(b);

#define _ARG2(_0, _1, _2, ...) _2
#define NARG2(...) _ARG2(__VA_ARGS__, 2, 1, 0)

#define _ONE_OR_TWO_ARGS_1(a) FOO1(a)
#define _ONE_OR_TWO_ARGS_2(a, b) FOO2(a,b)

#define __ONE_OR_TWO_ARGS(N, ...) _ONE_OR_TWO_ARGS_ ## N (__VA_ARGS__)
#define _ONE_OR_TWO_ARGS(N, ...) __ONE_OR_TWO_ARGS(N, __VA_ARGS__)

#define FOO(...) _ONE_OR_TWO_ARGS(NARG2(__VA_ARGS__), __VA_ARGS__)

لذلك إذا كان لديك

FOO(a)
FOO(a,b)

يوسع المعالج الأولي ذلك

a();
a(b);

كنت أقرأ بالتأكيد المقالة التي ربطتها. إنه مفيد للغاية ويذكر أن NARG2 لن يعمل على الحجج الفارغة. يتابع هذا here .


لإضافة إلى share ، يمكنك فعل ذلك بالفعل باستخدام ماكرو 0-argument ، بمساعدة ملحق GCC ##__VA_ARGS__ :

#define GET_MACRO(_0, _1, _2, NAME, ...) NAME
#define FOO(...) GET_MACRO(_0, ##__VA_ARGS__, FOO2, FOO1, FOO0)(__VA_ARGS__)

هنا هو حل أكثر عمومية:

// get number of arguments with __NARG__
#define __NARG__(...)  __NARG_I_(__VA_ARGS__,__RSEQ_N())
#define __NARG_I_(...) __ARG_N(__VA_ARGS__)
#define __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 __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

// general definition for any function name
#define _VFUNC_(name, n) name##n
#define _VFUNC(name, n) _VFUNC_(name, n)
#define VFUNC(func, ...) _VFUNC(func, __NARG__(__VA_ARGS__)) (__VA_ARGS__)

// definition for FOO
#define FOO(...) VFUNC(FOO, __VA_ARGS__)

حدد وظائفك:

#define FOO2(x, y) ((x) + (y))
#define FOO3(x, y, z) ((x) + (y) + (z))

// it also works with C functions:
int FOO4(int a, int b, int c, int d) { return a + b + c + d; }

يمكنك الآن استخدام FOO مع الوسيطتين 2 و 3 و 4:

FOO(42, 42) // will use makro function FOO2
FOO(42, 42, 42) // will use makro function FOO3
FOO(42, 42, 42, 42) // will call FOO4 function

محددات

  • فقط ما يصل إلى 63 من الحجج (ولكن قابلة للتوسيع)
  • وظيفة لأي حجة فقط في دول مجلس التعاون الخليجي ممكن

أفكار

استخدمه للوسائط الافتراضية:

#define func(...) VFUNC(func, __VA_ARGS__)
#define func2(a, b) func4(a, b, NULL, NULL)
#define func3(a, b, c) func4(a, b, c, NULL)

// real function:
int func4(int a, int b, void* c, void* d) { /* ... */ }

استخدامه لوظائف ذات عدد ممكن من الوسائط غير محدود:

#define SUM(...) VFUNC(SUM, __VA_ARGS__)
#define SUM2(a, b) ((a) + (b))
#define SUM3(a, b, c) ((a) + (b) + (c))
#define SUM4(a, b, c) ((a) + (b) + (c) + (d))
// ...

ملاحظة: يتم نسخ __NARG__ من: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1


يبدو أن هذا يعمل بشكل جيد على دول مجلس التعاون الخليجي ، كلانج و MSVC. إنها نسخة منقحة من بعض الإجابات هنا

#define __BUGFX(x) x

#define __NARG2(...) __BUGFX(__NARG1(__VA_ARGS__,__RSEQN()))
#define __NARG1(...) __BUGFX(__ARGSN(__VA_ARGS__))
#define __ARGSN(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
#define __RSEQN() 10,9,8,7,6,5,4,3,2,1,0

#define __FUNC2(name,n) name ## n
#define __FUNC1(name,n) __FUNC2(name,n)
#define GET_MACRO(func,...) __FUNC1(func,__BUGFX(__NARG2(__VA_ARGS__))) (__VA_ARGS__)




c-preprocessor