2010-07-04 14 views
55

Jak wymusić, aby parametr szablonu T był podklasą określonej klasy Baseclass? coś takiego:Ogranicz parametr szablonu C++ do podklasy

template <class T : Baseclass> void function(){ 
    T *object = new T(); 

} 
+3

Co próbujesz osiągnąć, robiąc to? – sth

+2

Chcę tylko upewnić się, że T jest faktycznie instancją podklasy lub samej klasy. Kod wewnątrz funkcji, którą podałem, jest prawie nieistotny. – phant0m

+6

wręcz przeciwnie, jest to bardzo istotne. Określa, czy dobrym pomysłem jest włożenie pracy do tego testu. W wielu (wszystkich?) Przypadkach, nie ma absolutnie potrzeby wymuszania takich ograniczeń samodzielnie, ale raczej pozwól kompilatorowi zrobić to podczas tworzenia instancji. Na przykład dla zaakceptowanej odpowiedzi dobrze byłoby sprawdzić, czy 'T' pochodzi od' Baseclass'. W chwili obecnej kontrola ta jest niejawna i nie jest widoczna dla rozdzielczości przeciążania. Ale jeśli nigdzie nie ma takiego niejawnego przymusu, wydaje się, że nie ma powodu do sztucznego ograniczenia. –

Odpowiedz

44

W tym przypadku można zrobić:

template <class T> void function(){ 
    Baseclass *object = new T(); 

} 

Nie będzie to skompilować jeśli T nie jest podklasą klasy bazowej (lub T jest klasy bazowej).

+0

ah tak, to dobry pomysł. dzięki! Rozumiem, że nie ma możliwości zdefiniowania go w definicji szablonu? – phant0m

+2

@ phant0m: Dokładnie. Nie można jawnie ograniczać parametrów szablonu (z wyjątkiem użycia koncepcji, które zostały uznane za C++ 0x, ale następnie zostały usunięte). Wszystkie więzy zdarzają się niejawnie przez operacje wykonywane na nim (lub innymi słowy, jedynym ograniczeniem jest "Typ musi obsługiwać wszystkie operacje, które są wykonywane na nim"). – sepp2k

+1

ah ic. Wielkie dzięki za wyjaśnienie! – phant0m

0

Wywołanie funkcji wewnątrz szablonu istniejących w klasie bazowej.

Jeśli spróbujesz utworzyć szablon z typem, który nie ma dostępu do tej funkcji, pojawi się błąd podczas kompilacji.

+2

To nie gwarantuje, że 'T' * jest *' BaseClass', ponieważ deklarowane elementy w 'BaseClass' mogą być powtórzone w deklaracji' T'. –

5

Można użyć Boost Concept Check „s BOOST_CONCEPT_REQUIRES:

#include <boost/concept_check.hpp> 
#include <boost/concept/requires.hpp> 

template <class T> 
BOOST_CONCEPT_REQUIRES(
    ((boost::Convertible<T, BaseClass>)), 
(void)) function() 
{ 
    //... 
} 
+0

dzięki za sugestię. Sprawdzę to. – phant0m

8

Nie trzeba koncepcje, ale można użyć SFINAE:

template <typename T> 
boost::enable_if< boost::is_base_of<Base,T>::value >::type function() { 
    // This function will only be considered by the compiler if 
    // T actualy derived from Base 
} 

Zauważ, że to będzie instancję funkcję tylko wtedy, gdy warunek jest spełniony, ale nie zapewni rozsądnego błędu, jeśli warunek nie zostanie spełniony.

+0

Co się stanie, jeśli otoczysz wszystkie takie funkcje? co nowego wraca? –

+0

'enable_if' przyjmuje drugi parametr, który domyślnie przyjmuje wartość' void'. Wyrażenie "enable_if < true, int > :: type" reprezentuje typ 'int'. Naprawdę nie mogę zrozumieć, jakie jest twoje pierwsze pytanie, możesz użyć SFINAE na cokolwiek chcesz, ale nie do końca rozumiem, co zamierzasz zrobić z tymi wszystkimi funkcjami. –

39

Aby wykonać mniej niepotrzebnego kodu w czasie wykonywania można spojrzeć na: http://www.stroustrup.com/bs_faq2.html#constraints który zapewnia niektórych klas, które wykonują próbę czasu kompilacji wydajnie produkować ładniejsze i komunikaty o błędach.

W szczególności:

template<class T, class B> struct Derived_from { 
     static void constraints(T* p) { B* pb = p; } 
     Derived_from() { void(*p)(T*) = constraints; } 
}; 

template<class T> void function() { 
    Derived_from<T,Baseclass>(); 
} 
+1

dzięki za link! – phant0m

+1

Dla mnie jest to najlepsza i najciekawsza odpowiedź. Koniecznie sprawdź FAQ w Stroustrup, aby dowiedzieć się więcej o wszystkich ograniczeniach, które możesz wymusić podobnie. –

+1

W istocie jest to piekielna odpowiedź! Dzięki. Wymieniona strona jest przenoszona tutaj: http://www.stroustrup.com/bs_faq2.html#constraints –

54

Z kompilatora zgodnego C++ 11, można zrobić coś takiego:

template<class Derived> class MyClass { 

    MyClass() { 
     // Compile-time sanity check 
     static_assert(std::is_base_of<BaseClass, Derived>::value, "Derived not derived from BaseClass"); 

     // Do other construction related stuff... 
     ... 
    } 
} 

Przetestowałem to z wykorzystaniem kompilatora gcc 4.8.1 w środowisku CYGWIN - więc powinno działać również w środowiskach * nix.

+0

Dla mnie działa to również następująco: 'szablon klasa BaseBiz { static_assert (std :: is_base_of :: value," TEntity nie pochodzi od BaseEntity ");' ... –

+0

To działa tylko wtedy, gdy cały szablon jest w nagłówku. – peterh

Powiązane problemy