假設我有一個 Java 訪問者。
interface Visitor<T> {
T visitA(VisitableA a);
T visitB(VisitableB b);
}
abstract class Visitable {
abstract <T> T accept(Visitor<T> visitor);
}
class VisitableA extends Visitable {
@Override <T> T accept(Visitor<T> visitor) {
return visitor.visitA(this);
}
}
class VisitableB extends Visitable {
@Override <T> T accept(Visitor<T> visitor) {
return visitor.visitB(this);
}
}
現在,如果我想用 C 撰寫它,我可以這樣做
class VisitableA;
class VisitableB;
template <typename T> class Visitor {
virtual T visitA(VisitableA& a) = 0;
virtual T visitB(VisitableB& b) = 0;
};
class MyVisitor : public Visitor<int> {
int visitA(VisitableA& a) override { /* do something */ return 42; }
int visitB(VisitableB& b) override { /* do something */ return 1337; }
};
class Visitable {
template <typename T> virtual T accept(Visitor<T>& visitor) = 0;
};
class VisitableA : public Visitable {
template <typename T> T accept(Visitor<T>& visitor) override { return visitor.visitA(*this); }
};
class VisitableB : public Visitable {
template <typename T> T accept(Visitor<T>& visitor) override { return visitor.visitB(*this); }
};
但這不能編譯,因為我不能有一個虛擬的模板化方法。
我可以使用std::any(或類似的東西),但我想知道是否有辦法在沒有它的情況下實作它。
必須注意,accept在構造Visitables 時,回傳型別是未知的。
如果需要,C 20 很好。
uj5u.com熱心網友回復:
做 Java 在幕后所做的事情。
替換T為std::any。
用于Visitable創建一個回傳any兩種方法的基類。然后創建一個實作any回傳 as的模板類final,并創建一個T回傳Visitas pure 供實作者實作。
Visitable有兩種方法;一個純粹的虛擬私有Visitable模板,一個公共模板,一個VitiableT模板。它呼叫純虛擬的并將 轉換any為 a T。
Java泛型基本上只是為您撰寫膠水。
您可能需要在幕后進行轉換,或者查看 typeids,具體取決于您如何使用它。
struct VistableA; struct VistableB;
struct Visitor{
virtual std::any visitA(VisitableA&)=0;
virtual std::any visitB(VisitableB&)=0;
};
template<class T>
struct VisitorT:Visitor{
std::any visitA(VisitableA& a) final{ return visitTA(a); }
T visitTA(VisitableA& a) = 0;
std::any visitB(VisitableB& b) final{ return visitTB(b); }
T visitTB(VisitableB& b) = 0;
};
class MyVisitor : public VisitorT<int> {
int visitTA(VisitableA& a) override { /* do something */ return 42; }
int visitTB(VisitableB& b) override { /* do something */ return 1337; }
};
class Visitable {
template <typename T> T accept(VisitorT<T>& visitor) {
return std::any_cast<T>(accept(static_cast<Visitor&>(visitor)));
}
virtual std::any accept(Visitor& visitor)=0;
};
class VisitableA : public Visitable {
std::any accept(Visitor& visitor) override { return visitor.visitA(*this); }
};
class VisitableB : public Visitable {
std::any accept(Visitor& visitor) override { return visitor.visitB(*this); }
};
現在這是 C ,還有另外六種方法可以解決您的問題,這些方法不模擬 Java。但這是 Java 風格的方式。
請注意,因為我們正在撰寫 Java 為您撰寫的膠水代碼,如果我們在膠水中出錯,我們就不是型別安全的。
在VisitableAJava 中檢查所有的Ts都使用相同的“通用型別” ;在 C 中,我使用了 a std::any,它可能與其他“泛型”混淆并破壞某些型別安全。你可以想象一個復雜的標記系統std::any來避免這種情況。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/338992.html
