[英]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.