我们有一个子项目’commonUtils’,它有许多在父项目中使用的通用代码片段.
我看到的一个有趣的东西是: –
/*********************************************************************
If T is polymorphic, the compiler is required to evaluate the typeid
stuff at runtime, and answer will be true. If T is non-polymorphic,
the compiler is required to evaluate the typeid stuff at compile time,
whence answer will remain false
*********************************************************************/
template <class T>
bool isPolymorphic() {
bool answer=false;
typeid(answer=true,T());
return answer;
}
我相信评论并认为这是一个非常有趣的模板,尽管它不是
在整个项目中使用.为了好奇,我试着像这样使用它…
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
if (isPolymorphic<PolyBase>())
std::cout<<"PolyBase = Polymorphic\n";
if (isPolymorphic<NPolyBase>())
std::cout<<"NPolyBase = Also Polymorphic\n";
但这些都没有回归真实. MSVC 2005没有发出警告,但是Comeau警告typeid表达没有任何效果. C标准中的5.2.8节没有说明评论所说的内容,即在编译时为非多态类型评估typeid,在运行时评估多态类型.
1)所以我猜这个评论是误导/明白错误,或者因为这段代码的作者是一位资深的C程序员,我错过了什么?
2)OTOH,我想知道我们是否可以使用某种技术测试一个类是否是多态的(至少有一个虚函数)?
3)什么时候想知道一个类是多态的?胡乱猜测;使用dynamic_cast< void *>(T)获取类的起始地址(因为dynamic_cast仅适用于多态类).
等待你的意见.
提前致谢,
解决方法:
我无法想象任何可能的方式如何使用typeid来检查该类型是多态的.它甚至不能用来断言它,因为typeid可以在任何类型上工作.
Boost有一个实现here.至于为什么它可能是必要的 – 我知道的一个案例是Boost.Serialization库.如果要保存非多态类型,则只需保存即可.如果保存多态,则必须使用typeid获取其动态类型,然后为该类型调用序列化方法(在某些表中查找).
更新:看来我其实是错的.考虑这个变种:
template <class T>
bool isPolymorphic() {
bool answer=false;
T *t = new T();
typeid(answer=true,*t);
delete t;
return answer;
}
这实际上正如名称所示,确切地说就是原始代码段中的每条评论.如果“不指定多态类类型的左值”(std 3.2 / 2),则不评估typeid内的表达式.因此,在上面的情况中,如果T不是多态的,则不评估typeid表达式.如果T是多态的,则* t确实是多态类型的左值,因此必须评估整个表达式.
现在,你原来的例子仍然是错的:-).它使用T(),而不是* t.并且T()创建rvalue(std 3.10 / 6).因此,它仍然产生一个不是“多态类的左值”的表达式.
这是一个相当有趣的技巧.另一方面,它的实际价值有些限制 – 因为虽然boost :: is_polymorphic为你提供了一个编译时常量,但是这个给你一个运行时值,所以你不能为多态和非多态类型实例化不同的代码.