Dr_*_*Sam 6 c++ templates double-dispatch
我有一个C++代码,我比较了从一个普通的母类派生的不同类Foo.如果两个类的类型不同,则总是进行比较false.否则,它会比较某些特定于该类的内部数据.
我的代码看起来像这样:
class Bar;
class Baz;
class Foo
{
public:
virtual bool isSame( Foo* ) = 0;
virtual bool isSameSpecific( Bar* ){ return false; }
virtual bool isSameSpecific( Baz* ){ return false; }
};
class Bar : public Foo
{
public:
bool isSame( Foo* foo){ return foo->isSameSpecific(this); }
bool isSameSpecific( Bar* bar){ return bar->identifier == identifier; }
int identifier;
};
// and the same for Baz...
Run Code Online (Sandbox Code Playgroud)
这个伟大的工程(我认为这是一个双重分派),我可以比较Bar,并Baz只用指针Foo.
但现在出现了问题.我必须添加一个模板类:
template< typename T>
class Qux : public Foo
{
//...
};
Run Code Online (Sandbox Code Playgroud)
问题是在Foo,我不能宣布的方法isSameSpecific进行Qux*,因为这将是虚拟化和模板.
问题:有没有什么方法可以解决这个问题?
这个问题并没有真正的解决方案:您isSameSpecific使用的模板的每个实例化都需要一个函数。(换句话说,在Foo:
template <typename T>
virtual bool isSameSpecific( Qux<T>* );
Run Code Online (Sandbox Code Playgroud)
是非法的,但是:
virtual bool isSameSpecific( Qux<int>* );
virtual bool isSameSpecific( Qux<double>* );
// etc.
Run Code Online (Sandbox Code Playgroud)
不是。)
您也许可以创建一个 Abstract
QuxBase并Qux<T>从中派生。最有可能的是,这只会将问题转移到QuxBase,但如果
isSameSpecific不依赖于 的类型T,例如因为您可以定义一些规范的包含类型,那么它可能是可行的。在不了解更多关于Qux和 的
情况下isSameSpecific,很难说。(如果
实例化类型不同,则 ifQux<T>::isSameSpecific应始终返回false,例如,您可以键入 check in QuxBase::isSameSpecific,如果类型相同,则转发到另一个虚拟函数。)
请注意,类似的问题也会影响实现多重调度的所有替代方法。最后,您要求在一组开放类型上进行分派,这意味着可能存在无限数量的不同函数。
需要明确的是:我假设您isSame只是一个例子,实际操作可能更复杂。您显示的实际代码显然属于我在第二段中建议的内容;事实上,即使没有多次调度也可以实现。只需定义一个规范的“标识符”类型,定义一个虚getCanonicalIdentifier函数,然后在中使用它isSame:
bool Foo::isSame( Foo const* other ) const
{
return getCanonicalIdentifier()
== other->getCanonicalIdentifier();
}
Run Code Online (Sandbox Code Playgroud)
就此而言,如果不同的类型意味着isSame
返回 false(通常是这种情况,ifisSame意味着它看起来像什么),那么您也不需要双重分派:
bool Foo::isSame( Foo const* other ) const
{
return typeid( *this ) == typeid( *other )
&& isSameSpecific( other );
}
Run Code Online (Sandbox Code Playgroud)
派生类isSameSpecific必须转换指针的类型,但由于它们保证它与 的类型相同this,所以这是一个简单且安全的操作。
最后:如果类没有值语义(如果涉及多态性,几乎肯定不应该有值语义),那么简单如下:
bool Foo::isSame( Foo const* other ) const
{
return this == other;
}
Run Code Online (Sandbox Code Playgroud)
可能就足够了。
然而,所有这些仅适用于类似的东西isSame。如果您的其他功能受到影响,您就会回到我最初所说的。