Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;使用模板的静态分派 假设我有一些C++代码,看起来像: class Base { virtual void dummy() = 0; // this is to generate a vtable, but note there is no virtual f() }; class A : public Base { public: void f() { /* ... */ }; void dummy() {}; } class B : public Base { public: void f() { /* different implementation from A */ }; void dummy() {}; } template<class T1, class T2, class T3> void doStuff(T1 &x, T2 &y, T3 &z) { for (i=1; i<100000; ++i) { x.f(); y.f(); z.f(); } }_C++_Templates - Fatal编程技术网

C++;使用模板的静态分派 假设我有一些C++代码,看起来像: class Base { virtual void dummy() = 0; // this is to generate a vtable, but note there is no virtual f() }; class A : public Base { public: void f() { /* ... */ }; void dummy() {}; } class B : public Base { public: void f() { /* different implementation from A */ }; void dummy() {}; } template<class T1, class T2, class T3> void doStuff(T1 &x, T2 &y, T3 &z) { for (i=1; i<100000; ++i) { x.f(); y.f(); z.f(); } }

C++;使用模板的静态分派 假设我有一些C++代码,看起来像: class Base { virtual void dummy() = 0; // this is to generate a vtable, but note there is no virtual f() }; class A : public Base { public: void f() { /* ... */ }; void dummy() {}; } class B : public Base { public: void f() { /* different implementation from A */ }; void dummy() {}; } template<class T1, class T2, class T3> void doStuff(T1 &x, T2 &y, T3 &z) { for (i=1; i<100000; ++i) { x.f(); y.f(); z.f(); } },c++,templates,C++,Templates,为了解决这个问题(如所建议的),我似乎必须显式地构造一个静态分派函数: void doStuff(Base &x, Base &y, Base &z) { A *a_x = dynamic_cast<A*>(&x); B *b_x = dynamic_cast<B*>(&x); A *a_y = dynamic_cast<A*>(&y); B *b_y = dynamic_cast

为了解决这个问题(如所建议的),我似乎必须显式地构造一个静态分派函数:

void doStuff(Base &x, Base &y, Base &z) {
    A *a_x = dynamic_cast<A*>(&x);
    B *b_x = dynamic_cast<B*>(&x);
    A *a_y = dynamic_cast<A*>(&y);
    B *b_y = dynamic_cast<B*>(&y);
    A *a_z = dynamic_cast<A*>(&z);
    B *b_z = dynamic_cast<B*>(&z);
    if (a_x && a_y && a_z) {
        doStuff(*a_x, &a_y, &a_z);
    } else if (a_x && a_y && b_z) {
        doStuff(*a_x, &a_y, &b_z);
    } 
    // ... and so on for all eight combinations of A and B.
}
void doStuff(底部和x、底部和y、底部和z){
A*A_x=动态演员阵容(&x);
B*B_x=动态施法(&x);
A*A_y=动态投射(&y);
B*B_y=动态投射(&y);
A*A_z=动态施法(&z);
B*B_z=动态_投射(&z);
if(a_x&&a_y&&a_z){
doStuff(*a_x,&a_y,&a_z);
}else if(a_x&&a_y&&b_z){
doStuff(*a_x、a_y和b_z);
} 
//…对于A和B的所有八种组合,依此类推。
}
但是这是一些非常烦人的重复代码,如果我有几个类似于
doStuff
的函数,它将很快变得难以管理,特别是如果其中任何一个函数有四个或更多参数的话


所以我的问题是,有没有办法避免这种重复的代码?似乎进一步巧妙地使用模板应该能够消除它,但我不太明白如何做到这一点。

您问题的标题:“静态调度”-不幸的是,您的问题需要在运行时找出类型。。。您希望从一些基类指针中识别实际类型。这将只在运行时起作用

使用
dynamic\u cast
是一种技巧,使用dynamic\u cast通常意味着糟糕的OO设计。顺便说一句,我打赌使用
dynamic\u cast
dynamic\u cast
可能非常慢!)然后静态函数调用比简单地将
f()
虚拟化并将其放入基类并以这种方式调用要慢

当然,你的情况有点特别,你想为8种情况做一些其他的事情,但是这是一个肮脏的工作,你不能用C++中的简洁代码来优雅地解决。可以打造一个不太容易出错/易于扩展的解决方案,或者一个性能更好的解决方案,但没有一个是简洁和/或优雅的。您当前的
doStuff()
实现是一个不太容易出错的“防弹”解决方案,我刚刚想到了另一个丑陋的解决方案,即使对于许多派生类和类组合(自己的类型enum和自己的gettype+开关),它也会有很好的性能,但这非常丑陋


总结:这个问题在C++中没有好的解决方案。您必须重新考虑您的设计,或者在遇到无法用C++优雅地解决的问题时,您必须忍受丑陋的代码:例如,在序列化的情况下,您经常会发现像这样丑陋的代码…

这是一个经典的多分派问题。这在文献中得到了很好的发展。其中一个解决方案是Visitor模式(您需要应用它两次,因为您有3个参数要分派)。另一个是
map
(后一个类应该有一个虚拟的
doStuff
方法,并对其中的所有参数进行动态转换)。

模板可能很难,但是Boost的预处理器库可能会对您有所帮助:dynamic_cast只适用于具有vtable@Alex如果我在基类中添加一个虚拟的虚拟方法似乎没问题——我已经编辑了文章。实际上,代码作为一个整体不起作用——模板
doStuff
函数不会编译,因为没有
Base::f()
。所以我似乎需要找到一个不同的解决方案来解决这个问题。事实上,如果你纠正一些拼写错误,它确实有效。这是糟糕的OO设计!不幸的是,糟糕的设计是SIMD并行作为编译器优化而不是语言特性的自然结果——这就是需要以这种方式构建它的原因。请注意,
f()
连续调用100000次(编译器可以对其进行向量化),而
动态强制转换只调用一次,因此成本相对来说非常低。但是是的,我倾向于认为你可能是对的,没有优雅的方式来做到这一点。(但问也无妨)如果你有时间,你能给我指一下第二种解决方案的草图吗?我从90年代起就没有使用过STL,所以我很难想象它的代码。
void doStuff(Base &x, Base &y, Base &z) {
    A *a_x = dynamic_cast<A*>(&x);
    B *b_x = dynamic_cast<B*>(&x);
    A *a_y = dynamic_cast<A*>(&y);
    B *b_y = dynamic_cast<B*>(&y);
    A *a_z = dynamic_cast<A*>(&z);
    B *b_z = dynamic_cast<B*>(&z);
    if (a_x && a_y && a_z) {
        doStuff(*a_x, &a_y, &a_z);
    } else if (a_x && a_y && b_z) {
        doStuff(*a_x, &a_y, &b_z);
    } 
    // ... and so on for all eight combinations of A and B.
}