Як я можу змусити параметр шаблону Tбути підкласом певного класу Baseclass? Щось на зразок цього:
template <class T : Baseclass> void function(){
T *object = new T();
}
Як я можу змусити параметр шаблону Tбути підкласом певного класу Baseclass? Щось на зразок цього:
template <class T : Baseclass> void function(){
T *object = new T();
}
Tпоходить від Baseclass. На сьогоднішній день ця перевірка є неявною і не відображається для дозволу на перевантаження. Але якщо ніде не робиться такого неявного обмеження, здається, немає причин для штучного обмеження.
Відповіді:
У цьому випадку ви можете зробити:
template <class T> void function(){
Baseclass *object = new T();
}
Це не буде скомпільовано, якщо T не є підкласом базового класу (або T є базовим класом).
За допомогою компілятора, сумісного з C ++ 11, ви можете зробити щось подібне:
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...
...
}
}
Я перевірив це за допомогою компілятора gcc 4.8.1 всередині середовища CYGWIN - тому він також повинен працювати в середовищах * nix.
template<class TEntity> class BaseBiz { static_assert(std::is_base_of<BaseEntity, TEntity>::value, "TEntity not derived from BaseEntity");...
Щоб виконати менш марний код під час виконання, ви можете подивитися: http://www.stroustrup.com/bs_faq2.html#constraints, який надає деякі класи, які ефективно виконують перевірку часу компіляції та видають приємніші повідомлення про помилки.
Зокрема:
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'та unused variable 'pb'?
(void)pb;після B* pb = p;.
Вам не потрібні поняття, але ви можете використовувати 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
}
Зверніть увагу, що це створить функцію лише тоді, коли умова виконана, але вона не дасть помітної помилки, якщо умова не виконана.
enable_ifЗаймає другий тип параметра , який по замовчуванням void. Вираз enable_if< true, int >::typeпредставляє тип int. Я не можу зрозуміти, що саме ваше перше запитання, ви можете використовувати SFINAE, що завгодно, але я не зовсім розумію, що ви маєте намір робити з цим за всіма функціями.
З C ++ 11 вам не потрібен Boost або static_assert. C ++ 11 вводить is_base_of та enable_if. C ++ 14 представляє зручний тип enable_if_t, але якщо ви застрягли в C ++ 11, ви можете просто використовувати його enable_if::type.
Рішення Девіда Родрігеса можна переписати таким чином:
#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
}
З C ++ 17 ми маємо is_base_of_v. Рішення можна переписати на:
#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
}
Ви також можете просто обмежити весь шаблон. Ви можете використовувати цей метод для визначення цілих класів. Зверніть увагу, як enable_if_tбув вилучений другий параметр (раніше його було встановлено як void). Його значення за замовчуванням насправді void, але це не має значення, оскільки ми його не використовуємо.
#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
}
З документації параметрів шаблону ми бачимо, що typename = enable_if_t...це параметр шаблону з порожнім ім'ям. Ми просто використовуємо його, щоб переконатися, що існує визначення типу. Зокрема, enable_if_tне буде визначено, якщо Baseне є базою T.
Методика, наведена вище, наведена як приклад в enable_if.
template <class T : Base>
Ви можете використовувати підштовхування Concept Check «и 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()
{
//...
}
Викликаючи функції всередині вашого шаблону, які існують у базовому класі.
Якщо ви спробуєте створити шаблон для вашого типу, який не має доступу до цієї функції, ви отримаєте помилку під час компіляції.
T це BaseClass тому, що заявлені члени в BaseClassможуть бути повторені в декларації T.