Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why compiler does not see method of base class when using CRTP

I have the following piece of code:

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
}

Both msvc, gcc and clang reject this code, they cannot find method Read(int x)

However if I uncomment using Iface::Read in Crtp my code compiles successfully.

Note that if I take a reference to Iface I can call Read(int x)

Why does this happen?

like image 471
Alexey Avatar asked Jun 08 '16 08:06

Alexey


1 Answers

Why does this happen?

Your problem has nothing to do with CRTP. It's a name hiding issue that may happen in a normal inheritance scenario.

When you call impl.Read(24);, the member function name Read can't be found at the class scope of IfaceImpl. Then the scope of base class Crtp will be examined, and the name Read found there. Then name lookup stops, so int Read(int x) in the further base class Iface won't be considered for overload resolution, even though it is more appropriate here.

By using Iface::Read; you're introducing the name Read into the class scope of Crtp. Then it could be found and selected by overload resolution correctly.

And if you call it via Iface reference, the name lookup will work well.

Or you can call it explicitly (and ugly) by impl.Iface::Read(24);.

See Unqualified name lookup:

... name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

like image 94
songyuanyao Avatar answered Nov 16 '22 18:11

songyuanyao