[英]Why compiler does not see method of base class when using CRTP
我有以下代碼:
struct Iface
{
virtual int Read() = 0;
int Read(int x) {
return Read() + x;
}
};
template <typename Impl>
struct Crtp : public Iface
{
virtual int Read() {
return static_cast<Impl&>(*this).ReadImpl();
}
//using Iface::Read;
};
struct IfaceImpl : public Crtp<IfaceImpl>
{
int ReadImpl() {
return 42;
}
};
int main()
{
IfaceImpl impl;
impl.Read(24); // compilation error
Iface& iface = impl;
iface.Read(24); // always compiles successfully
}
msvc,gcc和clang都拒絕這段代碼,他們找不到方法Read(int x)
但是,如果我在Crtp
using Iface::Read
取消注釋,我的代碼將成功編譯。
請注意,如果我參考Iface,我可以調用Read(int x)
為什么會這樣?
為什么會這樣?
您的問題與CRTP無關。 這是在正常繼承方案中可能發生的名稱隱藏問題。
當你調用impl.Read(24);
,在IfaceImpl
的類范圍內找不到成員函數名Read
。 然后將檢查基類Crtp
的范圍,並在那里找到名稱Read
。 然后名稱查找停止,因此在另一個基類Iface
中的int Read(int x)
將不會被考慮用於重載解析,即使它在這里更合適。
通過using Iface::Read;
你將名稱Read
引入Crtp
的類范圍。 然后可以通過正確的重載分辨率找到並選擇它。
如果你通過Iface
引用調用它,名稱查找將很好。
或者你可以通過impl.Iface::Read(24);
顯式地(和丑陋地)調用它impl.Iface::Read(24);
。
請參閱非限定名稱查找 :
... name lookup檢查范圍如下所述,直到它找到至少一個任何類型的聲明,此時查找停止並且不再檢查其他范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.