2010-10-21 21 views
9

Jestem mylić o zaletach korzystania z tychZalety korzystania z boost :: mpl :: bool_ zamiast const bool

bool_<true> 

i

bool_<false> 

rodzajów przeciwko prostu za pomocą const bools w kontekst metaprogramowania szablonu.

Biblioteka boost :: mpl zdecydowanie preferuje pierwsze podejście i definiuje funkcje pomocnicze, takie jak i_, lub_, aby pomóc w zarządzaniu takim boolem. Warunkowe metafunkcje, takie jak if_ "biorą" bool_ jako pierwszy (szablonowy) argument, ale za kulisami "wywołują" metafunkcje if_c, które spodziewają się (const) bool jako pierwszego (szablonu) argumentu.

Jakie są argumenty za tą decyzją?

Z góry dziękujemy za pomoc!

Odpowiedz

11

Oto krótki przykład, jak używam tych typów od czasu do czasu. Ten przykład nie byłoby możliwe przy użyciu const bool:

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

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

zadzwonić do jednego z tych dwóch funkcji w zależności od typu argumentu:

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

W tym przypadku pierwszy lub drugi funkcja będzie wywoływana, w zależności od tego, czy typ T jest wskaźnikiem czy nie. Tego typu pozwalają na przeciążanie funkcji, gdzie nie byłoby to możliwe za pomocą stałej bool. W przypadku stałej bool będziesz musiał zdecydować w czasie wykonywania, którą gałąź wybrać. Jest to szczególnie ważne, jeśli wywoływane funkcje same są szablonami, które nie zostałyby skompilowane poprawnie, gdyby zostały utworzone dla typów innych niż oczekiwane, np. pierwsza definicja funkcji może zawierać kod, który kompiluje się tylko dla wskaźników.

+0

Dziękuję, że to dobry przykład! – stepelu

+0

O tak, zapomniałem o przeciążeniu! – sbi

+2

To jest dobra odpowiedź, ale jest znacznie bardziej gadatliwa niż to konieczne. Możesz napisać 'do_something (boost :: is_pointer ())', które zrobi to samo w podobny sposób. –

2

Przypuszczam, jednym z powodów jest to, że bool_<...> są typy, a przy stosowaniu ich jako wyniki meta funkcji, nigdy nie będziesz musiał się zatrzymać i pomyśleć, czy wynik jest rodzajem i trzeba zrobić

typedef some_type result; 

lub wartość, która ma być zwrócona jako

const static ??? result = some_value; 

gdzie trzeba także śledzić typu.

Również podejrzewam (nie pracowałem z Boost.MPL jeszcze), że obaj mają result typ zagnieżdżony odnosząc się do siebie, tak, że można napisać funkcje meta po prostu wynikające z nich:

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

i można wywołać my_meta_func::result.

+0

jesteś na tylko wyniki są zawsze nazywane ':: type' w MPL. –

8

Chodzi o stworzenie wystarczającej jednolitości, aby biblioteka mogła zapewnić użyteczną funkcjonalność. Protokół MPL to: "wszystkie argumenty metafunkcji (i zwroty) są typami." Dzięki temu możemy napisać szablony, które mogą działać ogólnie na metafunkcje. Na przykład ten szablon akceptuje żadnej metafunkcji (lub dowolną metafunkcji z maksymalnie N argumentów w C++ 03):

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

Po pozwoli niektóre argumenty szablonu, aby nie być takie typy, pisanie staje wrapper niemożliwy.Dla praktycznego przykładu, dlaczego nam zależy, ta jednolitość pozwala bibliotece wybierać i oceniać wyrażenia lambda MPL. Gdyby argumenty metafunkcji mogły być nie-typami, to funkcja byłaby nie do zaimplementowania, ponieważ nie byłoby możliwości wypisania wszystkich specjalizacji częściowych potrzebnych do rozplątania zewnętrznego szablonu xxx z jego argumentów: w argumencie.

Mniej interesująca, jeśli nie mniej ważna, część tego powodu jest taka, że ​​wiele rzeczy staje się mniej szczegółowych, tak jak to robiliśmy w MPL. porównaj:

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

vs

mf0<x,y>::value && mf1<z>::value && mf2<x,z>::value 
Powiązane problemy