Jak mogę wymusić, Taby parametr szablonu był podklasą określonej klasy Baseclass? Coś takiego:
template <class T : Baseclass> void function(){
T *object = new T();
}
Jak mogę wymusić, Taby parametr szablonu był podklasą określonej klasy Baseclass? Coś takiego:
template <class T : Baseclass> void function(){
T *object = new T();
}
Tpochodzi z Baseclass. W tej chwili to sprawdzenie jest niejawne i nie jest widoczne w celu rozpoznania przeciążenia. Ale jeśli nigdzie nie ma takiego domniemanego ograniczenia, wydaje się, że nie ma powodu do sztucznego ograniczenia.
Odpowiedzi:
W takim przypadku możesz:
template <class T> void function(){
Baseclass *object = new T();
}
Nie zostanie to skompilowane, jeśli T nie jest podklasą klasy podstawowej (lub T jest klasą podstawową).
Korzystając z kompilatora zgodnego z C ++ 11, możesz 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 przy użyciu kompilatora gcc 4.8.1 w środowisku CYGWIN - więc powinno działać również w środowiskach * nix.
template<class TEntity> class BaseBiz { static_assert(std::is_base_of<BaseEntity, TEntity>::value, "TEntity not derived from BaseEntity");...
Aby wykonać mniej bezużyteczny kod w czasie wykonywania, możesz zajrzeć na stronę: http://www.stroustrup.com/bs_faq2.html#constraints, która zawiera kilka klas, które wydajnie wykonują test czasu kompilacji i generują ładniejsze 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>();
}
unused variable 'p'i unused variable 'pb'?
(void)pb;po B* pb = p;.
Nie potrzebujesz pojęć, ale możesz 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 spowoduje to utworzenie instancji funkcji tylko wtedy, gdy warunek zostanie spełniony, ale nie zapewni rozsądnego błędu, jeśli warunek nie zostanie spełniony.
enable_ifTrwa drugi typ parametru, który domyślnie void. Wyrażenie enable_if< true, int >::typereprezentuje typ int. Nie bardzo rozumiem, jakie jest twoje pierwsze pytanie, możesz użyć SFINAE do wszystkiego, co chcesz, ale nie do końca rozumiem, co zamierzasz z tym zrobić we wszystkich funkcjach.
Od C ++ 11 nie potrzebujesz Boost ani static_assert. C ++ 11 wprowadza is_base_of i enable_if. C ++ 14 wprowadza wygodny typ enable_if_t, ale jeśli utkniesz z C ++ 11, możesz po prostu użyć enable_if::typezamiast tego.
Rozwiązanie Davida Rodrígueza można przepisać w następujący sposób:
#include <type_traits>
using namespace std;
template <typename T>
enable_if_t<is_base_of<Base, T>::value, void> function() {
// This function will only be considered by the compiler if
// T actualy derived from Base
}
Od C ++ 17 mamy is_base_of_v. Rozwiązanie można dalej przepisać na:
#include <type_traits>
using namespace std;
template <typename T>
enable_if_t<is_base_of_v<Base, T>, void> function() {
// This function will only be considered by the compiler if
// T actualy derived from Base
}
Możesz także ograniczyć cały szablon. Możesz użyć tej metody do definiowania całych klas. Zwróć uwagę, jak enable_if_tusunięto drugi parametr z (poprzednio był ustawiony na void). Jego domyślna wartość to faktycznie void, ale nie ma to znaczenia, ponieważ jej nie używamy.
#include <type_traits>
using namespace std;
template <typename T,
typename = enable_if_t<is_base_of_v<Base, T>>>
void function() {
// This function will only be considered by the compiler if
// T actualy derived from Base
}
Z dokumentacji parametrów szablonu widzimy, że typename = enable_if_t...jest to parametr szablonu z pustą nazwą. Używamy go po prostu do upewnienia się, że istnieje definicja typu. W szczególności enable_if_tnie zostanie zdefiniowany, jeśli Basenie jest podstawą T.
Powyższa technika jest podana jako przykład w enable_if.
template <class T : Base>
Można użyć Boost, Concept Sprawdź „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()
{
//...
}
Wywołując funkcje wewnątrz szablonu, które istnieją w klasie bazowej.
Jeśli spróbujesz utworzyć wystąpienie szablonu z typem, który nie ma dostępu do tej funkcji, zostanie wyświetlony błąd kompilacji.
T to, że tak jest,BaseClass ponieważ zadeklarowani członkowie BaseClassmogliby zostać powtórzeni w deklaracji T.