基于模板参数的C++动态调度仿真

Jon*_*rdy 5 c++ polymorphism rtti dynamic-dispatch

为了这个问题,这被大大简化了.说我有一个层次结构:

struct Base {
    virtual int precision() const = 0;
};

template<int Precision>
struct Derived : public Base {

    typedef Traits<Precision>::Type Type;

    Derived(Type data) : value(data) {}
    virtual int precision() const { return Precision; }

    Type value;

};
Run Code Online (Sandbox Code Playgroud)

我想要一个带有签名的非模板函数:

Base* function(const Base& a, const Base& b);
Run Code Online (Sandbox Code Playgroud)

函数结果的具体类型与任何一个类型相同ab具有更大的类型Precision; 像下面的伪代码:

Base* function(const Base& a, const Base& b) {

    if (a.precision() > b.precision())

        return new A( ((A&)a).value + A(b.value).value );

    else if (a.precision() < b.precision())

        return new B( B(((A&)a).value).value + ((B&)b).value );

    else

        return new A( ((A&)a).value + ((A&)b).value );

}
Run Code Online (Sandbox Code Playgroud)

哪个AB哪些是特定类型的ab.我想function独立于Derived有多少实例来操作.我想避免大量的typeid()比较表,尽管RTTI的答案很好.有任何想法吗?

Bro*_*ses 3

如果不在所有可能类型的大量列表中进行选择,则不能直接将 function() 委托给模板化代码,因为模板在编​​译时扩展,并且在编译时 function() 不知道它实际上会是什么派生类型被称为与. 您需要为operation所需的模板化函数的每个版本编译模板化代码的实例,这可能是一个无限集。

按照这个逻辑,唯一知道可能需要的所有模板的地方就是Derived类本身。因此,你的Derived类应该包含一个成员:

Derived<Precision> *operation(Base& arg2) {
  Derived<Precision> *ptr = new Derived<Precision>;
  // ...
  return ptr;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以function像这样定义,并间接进行调度:

Base* function(const Base& a, const Base& b) {
  if (a.precision() > b.precision())
    return a.operation(b);
  else 
    return b.operation(a);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这是简化版本;如果您的操作在其参数中不对称,则需要定义成员函数的两个版本 - 一个用它this代替第一个参数,另一个用它代替第二个参数。

此外,这忽略了这样一个事实:您需要某种方法来a.operation获取适当形式的 ,b.value而不知道 的派生类型b。您必须自己解决这个问题 - 请注意,(按照与之前相同的逻辑)不可能通过 的 类型模板来解决这个问题b,因为您是在运行时调度的。解决方案取决于您所拥有的类型,以及是否有某种方法可以让更高精度的类型从等于或更低精度的Derived对象中提取值,而无需知道该对象的确切类型。这可能是不可能的,在这种情况下,您会得到一长串类型 ID 的匹配列表。

不过,您不必在 switch 语句中执行此操作。您可以为每种Derived类型提供一组成员函数,以便向上转换为更高精度的函数。例如:

template<int i>
upCast<Derived<i> >() {
  return /* upcasted value of this */
}
Run Code Online (Sandbox Code Playgroud)

然后,您的operator成员函数可以对 进行操作b.upcast<typeof(this)>,而不必显式进行转换来获取所需类型的值。您可能必须显式实例化其中一些函数才能编译它们;我还没有对 RTTI 做足够的工作来确定这一点。

但从根本上来说,问题在于,如果您有 N 种可能的精度,那么您就有 N N 种可能的组合,而每一种组合实际上都需要单独编译的代码。如果你不能在 的定义中使用模板function,那么你必须拥有所有 N N 个可能性的编译版本,并且以某种方式你必须告诉编译器生成它们全部,并且以某种方式你必须选择正确的一个来生成它们。在运行时调度到。使用成员函数的技巧去掉了 N 的其中一个因素,但另一个仍然存在,并且没有办法使其完全通用。