2012-11-02 11 views
10

Rozważ poniższy kod.W jaki sposób makroBOOST_BINARY analizuje spacje?

int value1 = BOOST_BINARY(100 111000 01 1 110); 

Czy ktoś może wyjaśnić, w jaki sposób BOOST_BINARY oblicza tam wartość int?

+1

Holy crap. Przyjrzawszy się źródłu, zaczynam podejrzewać, że odpowiedź na twoje pytanie brzmi "nie" ... – Thomas

+4

Niektóre rzeczy są lepiej pozostawione nieznane. –

Odpowiedz

3

To bardzo, bardzo skomplikowane. Ta biblioteka BOOST wykorzystuje makra zbudowane przez inne makra.

mam zamiar przedstawić ci trochę uproszczony przykład programowania preprocesora:

Uproszczony pytanie:

Jak zrobić makro dodanie 0 lub 1 na początku reszta - jak w tym przykłady:

CAT (0 1) --> 01 
CAT (1 100) --> 1100 

Tak - w jakiś sposób , należy umieścić między nimi oba argumenty po kolei. Dobrze zrobiłem tak:

// start point - this is our desired format 
#define CATS(a,b) a##b 
// helper macro to invoke preprocessor on result of a 
#define CALLP(a) a 
// some helper symbols to build CATS() 
#define CATB (
#define CATE) 
#define CATSN CATS 
// I use that only 0 or 1 is expected at the beginning: 
// CATS (0, 
#define CAT_B0 CATSN CATB 0, 
// CATS (1, 
#define CAT_B1 CATSN CATB 1, 

// the final macro: 
// Example: 
// CAT(0 XXX) --> CALLP(CAT_B ## 0 XXX )) 
// --> CALLP(CAT_B0 XXX) --> CALLP(CATSN (0, XXX)) 
// --> CALLP(CATS(0, XXX)) --> CATS(0,XXX) --> 0##XXX -> 0XXX 
#define CAT(tt) CALLP (CAT_B ## tt CATE) 

to naprawdę działa (przynajmniej na gcc): http://ideone.com/EKlTGt

Teraz wyobraź sobie, jak skomplikowana jest praca wykonywana przez ludzi impuls w swojej bibliotece? Tak, jest to bardzo skomplikowane - ale wykorzystuję takie preprocesorowe sztuczki, które przedstawiłem, a może i wiele innych - dziś po raz pierwszy spojrzałem na źródło tej biblioteki BOOST http://www.boost.org/doc/libs/1_46_1/boost/utility/binary.hpp (uwierz lub nie).

4

Użyj źródła, Luke!

The following code works by converting the input bit pattern into a 
Boost.Preprocessor sequence, then converting groupings of 3 bits each into 
the corresponding octal digit, and finally concatenating all of the digits 
together along with a leading zero. This yields a standard octal literal 
with the desired value as specified in bits. 

To całkiem proste. Musimy tylko zdefiniować kilka makr. Trzymaj się mocno.

#define BOOST_BINARY(bit_groupings)           \ 
    BOOST_BINARY_LITERAL_D(BOOST_PP_DEDUCE_D(), bit_groupings) 

// ... 

#define BOOST_BINARY_LITERAL_D(d, bit_groupings)        \ 
    BOOST_PP_SEQ_CAT                \ 
    ((0) BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE(d, bit_groupings) \ 
) 

#define BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE(d, bit_groupings) \ 
    BOOST_PP_SEQ_TRANSFORM              \ 
    (BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION          \ 
    , BOOST_PP_NIL                \ 
    , BOOST_PP_IDENTITY(BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE)()\ 
    (BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE         \ 
     (                  \ 
     d                  \ 
     , BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE(d, bit_groupings) \ 
    )                  \ 
    )                   \ 
) 

#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE(bit_sequence) \ 
    BOOST_PP_CAT                 \ 
    (BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1 bit_sequence  \ 
    , END_BIT                 \ 
) 

#define BOOST_DETAIL_BITS_PER_OCTIT 3 

#define BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE(d, incomplete_nibble_sequence) \ 
    BOOST_PP_CAT                 \ 
    (BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_       \ 
    , BOOST_PP_MOD_D(d               \ 
        , BOOST_PP_SEQ_SIZE(incomplete_nibble_sequence)   \ 
        , BOOST_DETAIL_BITS_PER_OCTIT        \ 
       )               \ 
)                   \ 
    incomplete_nibble_sequence 

#define BOOST_DETAIL_FIXED_COMPL(bit)          \ 
    BOOST_PP_CAT(BOOST_DETAIL_FIXED_COMPL_, bit) 

#define BOOST_DETAIL_FIXED_COMPL_0 1 

#define BOOST_DETAIL_FIXED_COMPL_1 0 

#define BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE(d, bit_groupings) \ 
    BOOST_PP_EMPTY                \ 
    BOOST_PP_CAT(BOOST_PP_WHILE_, d)           \ 
    (BOOST_DETAIL_BINARY_LITERAL_PREDICATE          \ 
    , BOOST_DETAIL_BINARY_LITERAL_OPERATION          \ 
    , bit_groupings()               \ 
) 

#define BOOST_DETAIL_BINARY_LITERAL_PREDICATE(d, state)      \ 
    BOOST_DETAIL_FIXED_COMPL(BOOST_DETAIL_IS_NULLARY_ARGS(state)) 

#define BOOST_DETAIL_BINARY_LITERAL_OPERATION(d, state)      \ 
    BOOST_DETAIL_SPLIT_AND_SWAP             \ 
    (BOOST_PP_CAT(BOOST_DETAIL_BINARY_LITERAL_ELEMENT_, state)) 

#define BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION(s, dummy_param, tuple)  \ 
    BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL tuple 

#define BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL(bit2, bit1, bit0)    \ 
    BOOST_DETAIL_TRIPLE_TO_OCTAL_ ## bit2 ## bit1 ## bit0 

#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_1 (0)(0) 
#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_2 (0) 
#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_0 

#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1END_BIT 

#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1(bit)  \ 
    ((bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2 

#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2(bit)  \ 
    bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3 

#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3(bit)  \ 
    bit)) BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1 

#define BOOST_DETAIL_SPLIT_AND_SWAP(params)         \ 
    BOOST_PP_IDENTITY(BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS)()(params) 

#define BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS(first_param, second_param)  \ 
    second_param first_param 

#define BOOST_DETAIL_LEFT_OF_COMMA(params)         \ 
    BOOST_PP_IDENTITY(BOOST_DETAIL_FIRST_MACRO_PARAM)()(params) 

#define BOOST_DETAIL_FIRST_MACRO_PARAM(first_param, second_param)   \ 
    first_param 

/* Begin derived concepts from Chaos by Paul Mensonides */ 

#define BOOST_DETAIL_IS_NULLARY_ARGS(param)         \ 
    BOOST_DETAIL_LEFT_OF_COMMA             \ 
    (BOOST_PP_CAT(BOOST_DETAIL_IS_NULLARY_ARGS_R_        \ 
       , BOOST_DETAIL_IS_NULLARY_ARGS_C param       \ 
       )                \ 
) 

#define BOOST_DETAIL_IS_NULLARY_ARGS_C()          \ 
    1 

#define BOOST_DETAIL_IS_NULLARY_ARGS_R_1          \ 
    1, BOOST_PP_NIL 

#define BOOST_DETAIL_IS_NULLARY_ARGS_R_BOOST_DETAIL_IS_NULLARY_ARGS_C   \ 
    0, BOOST_PP_NIL 

/* End derived concepts from Chaos by Paul Mensonides */ 

#define BOOST_DETAIL_TRIPLE_TO_OCTAL_000 0 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_001 1 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_010 2 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_011 3 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_100 4 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_101 5 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_110 6 
#define BOOST_DETAIL_TRIPLE_TO_OCTAL_111 7 

#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0 (0), 
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1 (1), 

#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00 (0)(0), 
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01 (0)(1), 
// ... and so on, until ... 
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111110 (1)(1)(1)(1)(1)(1)(1)(0), 
#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111111 (1)(1)(1)(1)(1)(1)(1)(1), 

To sprawia, że ​​ciężkie korzystanie z makr w boost/preprocessor/, ale nie będę powtarzać tych tutaj. To tysiące linii kodu razem.

Wiem, że to nie jest bardzo pomocna, dogłębna odpowiedź, ale zamierzam ją opublikować, ponieważ jest to lepsze niż nic. Miejmy nadzieję, że ktoś będzie miał odwagę, aby przebrnąć przez to i zapewnić coś bardziej wnikliwego!

Powiązane problemy