Domanda

Splitting questo fuori dalla mia domanda per quanto riguarda al CPP macro :

qualcuno qui

??ha utilizzato il Boost.Preprocessor tipi di dati della biblioteca per attuare qualcosa di simile alla X -Macro?

È stato utile?

Soluzione

Ho appena alzò gli occhi quello che un X-Macro dovrebbe essere e credo di aver fatto qualcosa di simile a quello che stai chiedendo.

Quello che ho voluto fare è quello di sostenere facilmente e rapidamente serializzazione per una serie di lezioni piuttosto simili. Il problema che ho avuto è che ho dovuto convertire alcune informazioni di runtime (un int) in un tipo di tempo di compilazione (una classe) per essere in grado di fare il mio serializzazione. Avrei potuto scrivere un paio di istruzioni case per fare il lavoro, ma ciò significherebbe che devo aggiornare diverse funzioni ogni volta che ho voluto aggiungere una classe.

Per ovviare a questo problema, in primo luogo ho definito un sequenza di tuple contenenti la mappatura:

#define WIN_MESSAGE_TYPE_SEQ \
    ((EM_REPLACESEL, em_replacesel))((WM_CHAR, wm_char)) //...

I nomi maiuscoli sono definisce che tengono un int e il minuscolo nomi sono classi che ho definito da qualche altra parte.

I può quindi utilizzare questa sequenza in collaborazione con alcuni dei preprocessori Boost per generare tutti i tipi di codice per me. Ad esempio, per ottenere una dichiarazione anticipata delle classi posso solo fare questo:

#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
    class BOOST_PP_TUPLE_ELEM(2,1,_elem_);

BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)

#undef WIN_MESSAGE_TYPE_BUILD_MACRO

Per fare il runtime per compilare la mappatura tempo, genera una serie di istruzioni case in questo modo:

#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
    case BOOST_PP_TUPLE_ELEM(2,0,_elem_): return win_message_serializer<BOOST_PP_TUPLE_ELEM(2,1,_elem_)>::serialize(msg, o_arch);

template <typename Archive>
void serialize_win_message (p_win_message_base msg, Archive& o_arch) {
    message_type_t message_type = msg->type();

    switch (message_type) {

    // This will generate a series of case statement for each message type that will invoke
    // the serializer for the correct types.
    BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)

    default: //...
    };
}

#undef WIN_MESSAGE_TYPE_BUILD_MACRO

L'intero codice comporta un po 'più di questo, ma questo dovrebbe ancora dare un'idea su come generare il codice utilizzando i preprocessori Boost. Nel mio esempio posso rapidamente e facilmente aggiungere il supporto di serializzazione per una classe semplicemente aggiornando la mia sequenza.

Si noti che usare il preprocessore Boost non produce codice molto leggibile quindi cerco di mantenere la macro utilizzata dal per ogni macro più semplice possibile. Anche io non sarei sorpreso se qualcuno da qualche parte ha una soluzione più elegante a questo problema. Questo è proprio quello che mi è venuta per un progetto personale in cui non mi importa la complessità supplementare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top