假設我有一些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();
}
}
這樣做的目的是爲了避免內循環中的虛函數調用f()
,爲了讓編譯器的優化。 (這顯然是我的實際代碼的簡化版本,關於我的使用案例的詳細信息,請參閱此more specific question)。
這工作正常,如果doStuff
的參數的類型在運行時知道,但如果他們不那麼它失敗:
int main() {
Base *x = new A();
Base *y = new B();
Base *z = new A();
doStuff(*x, *y, *z);
// oops - this instantiates to doStuff(Base &, Base &, Base &)
// and there's no Base::f().
}
來解決這個問題(由this answer的建議),它看來我要建立明確的靜態調度功能:
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.
}
但是,這是一些很煩人的重複代碼,如果我有沿doStuff
線多種功能,將很快得到不可收拾,特別是如果其中任何公頃有四個或更多的論點。
所以我的問題是,有什麼辦法可以避免這個重複的代碼?看起來,模板的一些更巧妙的使用應該能夠消除它,但我不知道如何去做。
模板可能很難,但Boost的預處理器庫可能會幫助您:http://www.boost.org/doc/libs/1_40_0/libs/preprocessor/doc/ –
dynamic_cast將僅適用於具有vtable的層次結構類 –
@Alex它似乎是好的,如果我添加一個虛擬的虛擬方法的基類 - 我已經編輯帖子。 – Nathaniel