C++ C++;模板限制
我想知道有没有办法对模板类设置限制?C++ C++;模板限制,c++,templates,C++,Templates,我想知道有没有办法对模板类设置限制? 指定模板中替换的每个类型都必须有特定的祖先(实现某些接口) 您可以使用或类似的库来声明对模板参数的限制 例如: #include <limits> #include <boost/static_assert.hpp> template <class UnsignedInt> class myclass { private: BOOST_STATIC_ASSERT((std::numeric_limits<Un
指定模板中替换的每个类型都必须有特定的祖先(实现某些接口) 您可以使用或类似的库来声明对模板参数的限制 例如:
#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 */
};
#包括
#包括
模板
类myclass
{
私人:
BOOST\u STATIC\u ASSERT((标准::数字限制::数字>=16)
&&标准::数值限制::是否专用
&&标准::数值限制::是整数
&&!std::数值限制::有符号);
公众:
/*这里的细节*/
};
编辑:例如,您可以编写
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();
}
};
模板
甲级{
BOOST_STATIC_ASSERT(BOOST::is_base_of);
公众:
B*obj;
int f(){
返回B::x+this->obj->f();
}
};
您可以使用这样的技巧(如果您不想使用Boost):
类基
{
公众:
静态常量int模板需要基本类=0;
};
类正确:公共基
{
};
类别不正确
{
};
模板
TMPL类
{
静态常量int TEMPLATE_REQUIRES_BASE_CLASS=T::TEMPLATE_REQUIRES_BASE_CLASS;
T*m\T;
};
void main()
{
tmplone;//好的
tmpltwo;//将不编译
}
第一行将编译。第二个将不编译,并将出现以下错误:
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
test.cpp
test.cpp(18):错误C2039:“模板\u需要\u基类”:不是“不正确”的成员
测试cpp(12):见“不正确”声明
cpp(25):请参阅对正在编译的类模板实例化“TMPL”的引用
具有
[
T=不正确
]
test.cpp(18):错误C2065:“模板\u需要\u基类”:未声明的标识符
test.cpp(18):错误C2057:预期的常量表达式
<代码>未来的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>
C类{};
模板
甲级;
模板
甲级
{
//这里的类定义
};
结构D:C{};
A d;//好的
A n;//编译错误-未定义的类A
我已经给出了<>代码> Enable的独立定义,如果和 iSaseBaseION和派生的 .
模板是C++中的一种鸭式输入。
如果类支持模板使用的所有内容,则可以将其用作模板参数,否则不能
如果您的模板中有
C *instance;
void foo(T *t)
{
instance = t;
}
然后,您强制要求T是从C派生的(或者至少是与指针兼容的赋值)以下内容在VC10中使用静态断言。我刚刚看到过这种用法,并没有深入了解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;
}
#包括
阶级基础
{
};
派生类:公共基
{
};
课堂
{
};
模板
甲级
{
静态断言(std::tr1::is_base_of::value,“T不是从base派生的”);
};
int _tmain(int argc,_TCHAR*argv[]
{
argc;argv;
//
//这将编译
A A;
//
//这将引发编译错误
A b;
返回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> ]
1>d:\temp\aaa\aaa\aaa.cpp(25):错误C2338:T不是从基
1> d:\temp\aaa\aaa\aaa.cpp(41):请参阅对正在编译的类模板实例化“A”的引用
1> 与
1> [
1> T=某个随机类
1> ]
为什么您认为您需要这个?sooooo的可能重复不是初学者的问题:-)。这段代码在g++4.4下并没有失败,原因不明。一般来说,我会说在这种情况下,通常使用枚举:枚举{TEMPLATE_REQUIRES_BASE_CLASS=0};这还有一个额外的好处,就是在g++@Semen下,GCC不符合预期。该标准要求在隐式实例化类时实例化数据成员的声明,并且类内初始值设定项是声明的一部分,而不是声明的定义。然而,该标准有点不清楚,它说“静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式要求静态数据成员的定义存在。”-然而,该规则似乎只适用于类外初始值设定项(否则就没有意义了)@Johannes:谢谢你的解释,当它建得很好的时候,我还以为我疯了……但我想enum的使用更简单。(我只是跟着Vandervourde:)
C *instance;
void foo(T *t)
{
instance = t;
}
#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> ]