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();
}
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();
}
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).
ah tak, to dobry pomysł. dzięki! Rozumiem, że nie ma możliwości zdefiniowania go w definicji szablonu? – phant0m
@ 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
ah ic. Wielkie dzięki za wyjaśnienie! – phant0m
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.
To nie gwarantuje, że 'T' * jest *' BaseClass', ponieważ deklarowane elementy w 'BaseClass' mogą być powtórzone w deklaracji' T'. –
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()
{
//...
}
dzięki za sugestię. Sprawdzę to. – phant0m
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.
Co się stanie, jeśli otoczysz wszystkie takie funkcje? co nowego wraca? –
'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. –
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>();
}
dzięki za link! – phant0m
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. –
W istocie jest to piekielna odpowiedź! Dzięki. Wymieniona strona jest przenoszona tutaj: http://www.stroustrup.com/bs_faq2.html#constraints –
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.
Dla mnie działa to również następująco: 'szablon
To działa tylko wtedy, gdy cały szablon jest w nagłówku. – peterh
Co próbujesz osiągnąć, robiąc to? – sth
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
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. –