2016-01-11 8 views
5

Ecco una macro in grado di calcolare il conteggio degli argomenti. e il codice come:qual è il significato di questa macro C?

#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args 
#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0 

#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n 

#define MPL_ARGS_SIZE(...) Y_TUPLE_SIZE_II((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX,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)) 

// the running result --------------------------------------- 

MPL_ARGS_SIZE(a,b,c,d,e,f,g)==7 

MPL_ARGS_SIZE(a,b,c,d)==4 

come capire

#define Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0 

e

Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX 

?

BTW, so di ## (libbra, sterlina) l'utilizzo e il meccanismo di #define Y_TUPLE_SIZE_I

+1

Questo è un set di macro piuttosto pazzo ... – immibis

+0

Stai solo formando un gruppo di argomenti vuoti da passare (e 0). Dopo averli concatenati, ottieni un elenco di argomenti. Tuttavia, sembra leggermente più del necessario per una macro counter counter. Immagino che la macro che stai chiedendo probabilmente gestisca il caso di 'MPL_ARGS_SIZE()' per dare 0 invece di 1. – chris

+0

@chris no, gli argomenti vuoti entrano in gioco solo se non vengono forniti argomenti. È un caso speciale. Nel caso normale, non ci sono argomenti vuoti. –

risposta

2

il prefisso e Postfix macro hanno lo scopo di rendere più dare 0 quando sono date senza argomenti, vale a dire MPL_ARGS_SIZE(). In questo caso, Y_TUPLE_SIZE_PREFIX_ e _Y_TUPLE_SIZE_POSTFIX sono concatenati per produrre Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX, che costringe il risultato a 0.

Nel caso generale, __VA_ARGS__ è non-vuoto, così la concatenazione solo espande per lo stesso numero di argomenti che sono stati dati. Seguito da 32, ... 0.

In entrambi i casi, gli argomenti sono racchiusi tra parentesi. Y_TUPLE_SIZE_II elimina queste parentesi e passa gli argomenti a Y_TUPLE_SIZE_I. Y_TUPLE_SIZE_I si espande appena al suo 33esimo argomento, scartando il resto.

Quindi se gli assegni 32 argomenti, quelli 32 verranno saltati e il numero che li segue, 32, sarà il risultato, come desiderato. Se gli assegni 31 argomenti, salterà quelli 31 e il primo numero che segue, cioè 32, e il risultato sarà il numero successivo, 31, sempre come desiderato.

Se si dà un unico argomento, si salta tale argomento e il 31 che lo seguono, e il risultato sarà 1.

Se si dà alcun argomento, il caso particolare di Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX entrerà in play, che è 32 argomenti vuoti seguiti da 0. I 32 argomenti vuoti verranno saltati, e il risultato sarà 0.

Il motivo per il caso speciale per nessun argomento è che senza di esso, si comporterebbe come il caso a un argomento. Quanto segue potrebbe aiutare a capire meglio:

#define Y_TUPLE_SIZE_II(__args) Y_TUPLE_SIZE_I __args 
#define Y_TUPLE_SIZE_I(__p0,__p1,__p2,__p3,__p4,__p5,__p6,__p7,__p8,__p9,__p10,__p11,__p12,__p13,__p14,__p15,__p16,__p17,__p18,__p19,__p20,__p21,__p22,__p23,__p24,__p25,__p26,__p27,__p28,__p29,__p30,__p31,__n,...) __n 

#define MPL_ARGS_SIZE(...) Y_TUPLE_SIZE_II((__VA_ARGS__,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)) 

Questa è la serie originale di macro, ma con tutto il trattamento per zero argomenti rimossi special-case. Funziona per tutto tranne il caso zero-argument, che restituisce 1 invece di 0.

Per gestire argomenti zero, inserisce l'elenco degli argomenti tra le macro prefisso e postfix. Se il risultato si espande a Y_TUPLE_SIZE_PREFIX__Y_TUPLE_SIZE_POSTFIX, l'elenco degli argomenti è vuoto e il caso speciale entra in gioco.

+0

beh, il metodo 'Y_TUPLE_SIZE_II ((__ VA_ARGS __, 32 ... 0))' era capire meglio. Ma torna a '#define MPL_ARGS_SIZE (...) Y_TUPLE_SIZE_II ((Y_TUPLE_SIZE_PREFIX_ ## __VA_ARGS__ ## _Y_TUPLE_SIZE_POSTFIX, ...)' per esempio, se gli argomenti erano a, b, c, che dire della situazione quando espanso ' MPL_ARGS_SIZE (a, b, c) '? Sembra' Y_TUPLE_SIZE_II ((Y_TUPLE_SIZE_PREFIX_a, b, c_Y_TUPLE_SIZE_POSTFIX, ... 0)) ', naturalmente si tratta di affermazioni errate, come comprenderlo? –

+0

A destra, nel caso di uno o più argomenti, il primo e l'ultimo argomento sono alterati dalle stringhe prefisso e suffisso, ma non ha importanza dal momento che l'unico scopo degli argomenti è di occupare una posizione di argomento, che vengono tutti scartati nel risultato finale –

+0

oooops , Mi sono perso prima ... 'Y_TUPLE_SIZE_II ((Y_TUPLE_SIZE_PREFIX_a, b, c_Y_TUPLE_SIZE_POSTFIX, ... 0)' sarà espanso come 'Y_TUPLE_SIZE_I (Y_TUPLE_SIZE_PREFIX_a, b, c_Y_TUPLE_SIZE_POSTFIX, ... 0)', il PREFIX_a, b, c_POSTFIX sia come parametro della macro 'Y_TUPLE_SIZE_I'. tks. –