【发布时间】:2011-06-11 18:04:18
【问题描述】:
我正在使用一个简单的对象模型,其中对象可以实现接口以提供可选功能。从本质上讲,一个对象必须实现一个getInterface 方法,该方法被赋予一个(唯一的)接口ID。然后,该方法返回一个指向接口的指针 - 或 null,以防对象未实现请求的接口。这是一个代码草图来说明这一点:
struct Interface { };
struct FooInterface : public Interface { enum { Id = 1 }; virtual void doFoo() = 0; };
struct BarInterface : public Interface { enum { Id = 2 }; virtual void doBar() = 0; };
struct YoyoInterface : public Interface { enum { Id = 3 }; virtual void doYoyo() = 0; };
struct Object {
virtual Interface *getInterface( int id ) { return 0; }
};
为了让在这个框架中工作的客户更轻松,我使用了一个小模板,它会自动生成“getInterface”实现,这样客户只需实现接口所需的实际功能。这个想法是从Object 以及所有接口派生一个具体类型,然后让getInterface 只返回指向this 的指针(转换为正确的类型)。这是模板和演示用法:
struct NullType { };
template <class T, class U>
struct TypeList {
typedef T Head;
typedef U Tail;
};
template <class Base, class IfaceList>
class ObjectWithIface :
public ObjectWithIface<Base, typename IfaceList::Tail>,
public IfaceList::Head
{
public:
virtual Interface *getInterface( int id ) {
if ( id == IfaceList::Head::Id ) {
return static_cast<IfaceList::Head *>( this );
}
return ObjectWithIface<Base, IfaceList::Tail>::getInterface( id );
}
};
template <class Base>
class ObjectWithIface<Base, NullType> : public Base
{
public:
virtual Interface *getInterface( int id ) {
return Base::getInterface( id );
}
};
class MyObjectWithFooAndBar : public ObjectWithIface< Object, TypeList<FooInterface, TypeList<BarInterface, NullType> > >
{
public:
// We get the getInterface() implementation for free from ObjectWithIface
virtual void doFoo() { }
virtual void doBar() { }
};
这很好用,但是有两个难看的问题:
对我来说,一个阻碍是这不适用于 MSVC6(它对模板的支持很差,但不幸的是我需要支持它)。 MSVC6 在编译时会产生 C1202 错误。
由递归
ObjectWithIface模板生成整个类范围(线性层次结构)。这对我本身来说不是问题,但不幸的是我不能只做一个switch语句来将接口ID 映射到getInterface中的指针。相反,层次结构中的每个步骤都会检查单个接口,然后将请求转发到基类。
有人对如何改善这种情况提出建议吗?通过使用ObjectWithIface 模板修复上述两个问题,或者通过建议使对象/接口框架更易于使用的替代方案。
【问题讨论】:
-
如果您需要支持 VC6,我认为您在模板元编程技巧方面的选择是有限的。
-
@jalf:我肯定是有限的,是的 - 我仍然希望在这些限制内有所改进。 :-]
标签: c++ templates metaprogramming typelist