Как макрос BOOST_BINARY анализирует пробелы?

Рассмотрим приведенный ниже код.

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

Может кто-нибудь объяснить, как BOOST_BINARY вычисляет значение int там?

Ответ 1

Это очень, очень сложно. Эта библиотека BOOST использует макросы, созданные другими макросами.

Я представлю вам упрощенный пример программирования препроцессора:

Упрощенный вопрос:

Как сделать добавление макроса 0 или 1 в начале отдыха - как в этом примере:

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

Итак - как-то , должно быть помещено между ними оба аргумента последовательно. Хорошо, я сделал это:

// 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)

Это действительно работает (по крайней мере, в gcc): http://ideone.com/EKlTGt

Теперь представьте, насколько сложна работа, выполняемая людьми BOOST в их библиотеке? Да, это очень сложно, но использовать такие препроцессорные трюки, которые я представил, и, возможно, многие другие - я посмотрел на источник этой библиотеки BOOST http://www.boost.org/doc/libs/1_46_1/boost/utility/binary.hpp сегодня в первый раз (верьте или нет).

Ответ 2

Используйте источник, Люк!

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.

И это довольно легко. Нам просто нужно определить несколько макросов. Держитесь крепко.

#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), 

Это сильно использует макросы в boost/preprocessor/, но я не буду повторять их здесь. Это тысячи строк кода вместе.

Я знаю, что это не очень полезный, углубленный ответ, но я все равно опубликую его, потому что это лучше, чем ничего. Надеюсь, у кого-то хватит смелости пробраться через это и предоставить что-то более проницательное!