如何解决通过编译时,通过模板自动确定类型是否为Abstract Base Class
|| 是否可以在编译时自动确定某个类是否为抽象基类? 我有一个对象工厂,该对象工厂有时通过其他通用代码被实例化为Abstract Base Class类型。该代码无法编译,因为它在ABC上调用了新的T()。我最终不得不专门为每个ABC创建对象工厂创建代码,以在这种情况下改为assert(0)。如果可以在编译时自动确定某个类型是否为ABC,则可以自动进行这种专业化处理。 一个简化的示例如下:// this program code compiles w/ gcc 4.4
#include <iostream>
#include <typeinfo>
// How to automatically specialize this class at compile-time?
template<typename T>
struct isAbstractBaseClass
{
enum { VALUE = 0 };
};
// Factory to create T,lives in a struct to allow default template parameters
template<typename T,int ABSTRACT = isAbstractBaseClass<T>::VALUE >
struct Create
{
static T* create()
{
return new T();
}
};
// specialize Create for abstract base classes
template<typename T>
struct Create<T,1>
{
static T* create()
{
std::cout << \"Cannot create and Abstract Base Class!\\n\";
std::cout << \"Create Failed on type_info::name() = \" << typeid(T).name() << \"\\n\";
return 0;
}
};
struct Foo
{
Foo() { std::cout << \"Foo created\\n\"; }
};
struct Baz
{
virtual void bar() = 0; // make this an Abstract Base Class
};
// template specialize on Baz to mark it as an Abstract Base Class
// My Question: is it possible to automatically determine this at compile-time?
template<> class isAbstractBaseClass<Baz> { enum { VALUE = 1 }; };
int main()
{
std::cout << \"Attempting to create a Foo class.\\n\";
delete Create<Foo>::create();
std::cout << \"Attempting to create a Baz class.\\n\";
delete Create<Baz>::create();
return 0;
}
输出:
> c ++ abstract.cpp && ./a.out
尝试创建Foo类。
Foo创建
试图创建一个Baz类。
无法创建和抽象基类!
在type_info :: name()= 3Baz上创建失败
编辑1 @jwismar向我介绍了Boost \的is_abstract实现。老实说,查看代码并试图推断出boost正在做什么是非常痛苦的。有人可以说出他们正在使用的技巧吗? (实际上是编辑2,我在看错误的代码,在下面的编辑2中找到了它)
@raj是的,存在一个约束,即该类必须具有默认的公共构造函数。它不是完全通用的,但它为我关心的99%类型提供了功能。添加create()方法不是一种选择,因为我无法控制某些被包装的类(第三方代码)。
@DennisZickefoose代码确实可以编译-带有专门用于处理ABC的模板。是的,可以改进设计以确保使用ABC实例化create()方法的代码不会这样做,但是该代码还可以执行对ABC和非ABC都有意义的其他职责。在这一点上,这将是一个重大的重写,我正在寻找更短期的解决方案。
@raj和@DennisZickefoose都很好地说明了示例的设计和基础代码库,但是我只对主题有关如何在编译时确定ABC类型的问题感兴趣。最好不要使用Boost。我对这种需求的基本看法与眼前的问题正交。
编辑2由于我无法以100分的声誉回答自己的问题,因此我将在此处发布答案:
我能够充分理解Boost的is_abstract代码,以创建满足我需要的isAbstractBaseClass版本。在ABC类型的情况下,它使用SFINAE回退到check_sig(...)版本。
template<class T>
struct isAbstractBaseClass
{
// Inspired by boost/type_traits/is_abstract.hpp
// Deduction fails if T is void,function type,// reference type (14.8.2/2)or an abstract class type
// according to review status issue #337
template<class U>
static char check_sig(U (*)[1]);
template<class U>
static short check_sig(...);
//
enum { VALUE = sizeof(isAbstractBaseClass<T>::template check_sig<T>(0)) - 1 };
};
解决方法
Boost类型特征库具有is_abstract函子。您可以直接使用它,也可以查看实现并查看他们如何处理它。
, 或只是删除此:
// specialize Create for abstract base classes
template<typename T>
struct Create<T,1>
{
static T* create()
{
std::cout << \"Cannot create and Abstract Base Class!\\n\";
std::cout << \"Create failed on type_info::name() = \" << typeid(T).name() << \"\\n\";
return 0;
}
};
那么当您尝试创建abc时,编译器只会发出错误。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。