如何强制将模板参数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
。到目前为止,该检查是隐式的,对于重载解决方案不可见。但是,如果在任何地方都没有这样的隐式约束,则似乎没有理由进行人为约束。
Answers:
在这种情况下,您可以执行以下操作:
template <class T> void function(){
Baseclass *object = new T();
}
如果T不是Baseclass的子类(或T是Baseclass),则不会编译。
使用符合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...
...
}
}
我已经在CYGWIN环境中使用gcc 4.8.1编译器对此进行了测试-因此它也应该在* 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
。
大卫·罗德里格斯(DavidRodríguez)的解决方案可以重写如下:
#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>
您可以使用Boost 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
。