2010-10-21 16 views
9

io sono confuso circa i vantaggi di usare i leVantaggi di usare boost :: :: MPL bool_ invece di un bool const

bool_<true> 

e

bool_<false> 

tipi contro semplicemente usando Caccio const in il contesto del modello metaprogrammazione.

La libreria boost :: mpl chiaramente preferisce il primo approccio e definisce le funzioni di supporto come e_, o_ per aiutare a gestire tale bool_. Metafunzioni condizionali come if_ "prendono" un bool_ come argomento primo (modello), ma dietro le quinte "chiamano" una metafunzione if_c che si aspetta un (const) bool come argomento primo (modello).

Quali sono gli argomenti alla base di questa decisione?

Grazie in anticipo per il vostro aiuto!

risposta

11

Ecco un breve esempio di come uso questi tipi di tanto in tanto. Questo esempio non sarebbe possibile, utilizzando const bool:

void do_something(boost::mpl::bool_<true>) 
{ 
    ... 
} 

void do_something(boost::mpl::bool_<false>) 
{ 
    ... 
} 

chiamata una di queste due funzioni a seconda del tipo di argomento:

template<class T> 
void doIt(void) 
{ 
    do_something(boost::mpl::bool_<boost::is_pointer<T>::val>()) 
} 

In questo caso la prima o la seconda funzione sarà chiamato, a seconda del fatto se il tipo T è un puntatore o meno. Questi tipi ti consentono di utilizzare l'overloading delle funzioni, dove non sarebbe possibile utilizzare un const bool. Con un const bool dovresti decidere in fase di esecuzione, quale ramo prendere. Ciò è particolarmente importante se le funzioni chiamate sono esse stesse template, che non si compilano correttamente, se sono state istanziate per tipi diversi da quelli previsti, ad es. la prima definizione di funzione sopra potrebbe contenere codice, che compila solo per i puntatori.

+0

Grazie, questo è un buon esempio! – stepelu

+0

Oh sì, ho dimenticato di sovraccaricare! – sbi

+2

Questa è una buona risposta, ma è molto più verbosa del necessario. Puoi scrivere 'do_something (boost :: is_pointer ())', che farà la stessa cosa più o meno allo stesso modo. –

2

Suppongo che una delle ragioni è che bool_<...> sono i tipi, e quando li utilizzano come risultati di una meta funzioni, non si avrà mai fermarsi a pensare se il risultato è un tipo e si deve fare

typedef some_type result; 

o un valore, che deve essere restituito come

const static ??? result = some_value; 

dove si hanno anche per tenere traccia del tipo.

Inoltre, ho il sospetto (non ho ancora lavorato con Boost.MPL) che entrambi hanno un tipo result nidificato riferendosi a se stessi, in modo che è possibile scrivere funzioni meta semplicemente che ne derivano:

template< bool b > 
struct my_meta_func : bool_<b> {}; 

e può richiamare my_meta_func::result.

+0

Hai ragione su, solo i risultati sono sempre chiamato ':: type' in MPL. –

8

Si tratta di creare un'uniformità sufficiente che la libreria può fornire funzionalità utili. Il protocollo MPL è: "tutti gli argomenti della metafunzione (e restituisce) sono tipi." Questo ci consente di scrivere modelli che possono operare genericamente su metafunzioni. Ad esempio, questo modello accetta qualsiasi metafunction (o qualsiasi metafunction con fino a N argomenti in C++ 03):

template <template <class...> class some_metafunction> 
struct wrapper; 

Una volta che si permettono alcuni degli argomenti modello da non-tipi, la scrittura di un tale involucro diventa impossibile.Per un esempio pratico del perché ci interessa, questa uniformità consente alla libreria di distinguere e valutare le espressioni lambda MPL. Se gli argomenti della metafunzione non erano consentiti, la funzionalità non sarebbe implementabile, poiché non sarebbe possibile scrivere tutte le specializzazioni parziali necessarie per districare il modello esterno xxx dagli argomenti ai in xxx<a1,a2,a3,...>.

Una parte meno interessante, se non meno valida, della ragione è che molte cose diventano meno prolisse nel modo in cui lo abbiamo fatto in MPL. confrontare:

and_<mf0<x,y>, mf1<z>, mf2<x,z> >::value 

vs

mf0<x,y>::value && mf1<z>::value && mf2<x,z>::value 
Problemi correlati