Как я могу заставить параметр шаблона 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 не является подклассом Baseclass (или 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 это a, BaseClass потому что объявленные члены BaseClassмогут повторяться в объявлении T.