C++模板限制
我想知道有什么方法可以对模板类设置限制吗?
指定在模板中替换的每个类型都必须具有特定的祖先(实现某个接口)。C++模板限制
template < class B > //and every B must be a child of abstract C
class A {
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
像=>在Haskell
func :: (Ord a, Show b) => a -> b -> c
可以use BOOST_STATIC_ASSERT
或类似的库断言在模板参数的限制。
例如:
#include <limits>
#include <boost/static_assert.hpp>
template <class UnsignedInt>
class myclass
{
private:
BOOST_STATIC_ASSERT((std::numeric_limits<UnsignedInt>::digits >= 16)
&& std::numeric_limits<UnsignedInt>::is_specialized
&& std::numeric_limits<UnsignedInt>::is_integer
&& !std::numeric_limits<UnsignedInt>::is_signed);
public:
/* details here */
};
编辑:对于你的榜样,你可以写
template < class B >
class A {
BOOST_STATIC_ASSERT(boost::is_base_of<C, B>);
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
你可以使用一个小技巧是这样的(如果你不想使用升压) :
class Base
{
public:
static const int TEMPLATE_REQUIRES_BASE_CLASS = 0;
};
class Correct : public Base
{
};
class Incorrect
{
};
template <typename T>
class TMPL
{
static const int TEMPLATE_REQUIRES_BASE_CLASS = T::TEMPLATE_REQUIRES_BASE_CLASS;
T *m_t;
};
void main()
{
TMPL<Correct> one; // OK
TMPL<Incorrect> two; // Will not compile
}
第一行将编译。第二个将无法编译,并给了以下错误:
test.cpp
test.cpp(18) : error C2039: 'TEMPLATE_REQUIRES_BASE_CLASS' : is not a member of 'Incorrect'
test.cpp(12) : see declaration of 'Incorrect'
test.cpp(25) : see reference to class template instantiation 'TMPL<T>' being compiled
with
[
T=Incorrect
]
test.cpp(18) : error C2065: 'TEMPLATE_REQUIRES_BASE_CLASS' : undeclared identifier
test.cpp(18) : error C2057: expected constant expression
由于某些未知原因,此代码在g ++ 4.4下不会失败。一般来说,我会说在这种情况下,通常使用枚举: enum {TEMPLATE_REQUIRES_BASE_CLASS = 0}; 这还有一个额外的好处,就是在g ++下没有达到预期的效果。 – iksemyonov 2010-06-17 15:34:14
@Semen,GCC不合格。标准要求数据成员的声明在类被隐式实例化时实例化,并且类内的初始化器是声明的一部分,而不是定义它的定义。然而,该标准略有不清,称“除非静态数据成员本身以需要定义静态数据成员存在的方式使用,否则不会发生静态数据成员的初始化(以及任何关联的副作用)。 “ - 这个规则似乎只适用于一个超类初始化(否则没有意义) – 2010-06-17 16:13:51
@Johannes:谢谢你的解释,我认为当它建好的时候我疯了......但是我猜枚举仍然是使用更简单。 (我只是跟随范德瓦尔德:) – iksemyonov 2010-06-17 16:28:17
C++的未来版本将支持这一本身使用的概念(这并没有使之成为C++ 11)。来解决这个问题
一种方法是在一个虚拟的模板参数使用专业化:
class C {};
template <class B, class dummy=void>
class A;
template <class B>
class A<B, typename enable_if<is_base_and_derived<C, B> >::type>
{
// class definition here
};
struct D : C {};
A<D> d; // fine
A<int> n; // compile error - undefined class A<B>
我就把enable_if
和is_base_and_derived
here独立的定义。
谢谢,真棒一段代码 – Andrew 2010-06-17 15:29:26
模板是用C++编写的鸭子。
如果你的类支持模板使用的所有东西,那么它可以用作模板参数,否则它不能。
如果您的模板,你有类似
C *instance;
void foo(T *t)
{
instance = t;
}
那么你执行T是从C(或至少assignement兼容的指针)
下使用VC10衍生作品static_assert。我刚刚看到这个使用过,并没有真正挖掘static_assert实际上做了什么 - 也许别人可以回答。
#include <type_traits>
class Base
{
};
class Derived : public Base
{
};
class SomeRandomClass
{
};
template<typename T>
class A
{
static_assert(std::tr1::is_base_of<Base, T>::value, "T not derived from Base");
};
int _tmain(int argc, _TCHAR* argv[])
{
argc; argv;
//
// This will compile
A<Derived> a;
//
// This will throw a compilation error
A<SomeRandomClass> b;
return 0;
}
编译器输出端:
1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1> d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1> with
1> [
1> T=SomeRandomClass
1> ]
为什么你认为你需要这个? – fredoverflow 2010-06-17 14:14:07
可能的[特定基类的C++类模板]的副本(http://*.com/questions/2012950/c-class-template-of-specific-baseclass) – SLaks 2010-06-17 14:14:44
sooooo不是初学者的问题:-)。概念实际上颇具争议。 – 2010-06-17 14:33:30