I am wondering why the follow does not work:
template<typename Derived>
struct Base0 {
    const auto& derived() { return static_cast<const Derived& >(*this);}
}
template<typename Derived>
struct Base1: Base0<Base1<Derived>> {
    auto foo () { return derived().foo_impl();}
}
struct Foo: Base1<Foo>> {
    auto foo_impl () { return "foo";}
}
It complains  that derived() is not a member. Changing derived()  to this->derived() works, but I guess this will get Base1<Base0<Foo>>& instead of Foo& (which is not desired), right?
Alternatively, we can do the follow:
template<typename Derived>
struct Base0 {
    const auto& derived() { return static_cast<const Derived& >(*this);}
}
template<typename Derived>
struct Base1: Base0<Derived> {
    // for some reason, "this->" is still needed here, why??? 
    auto foo () { return this->derived().foo_impl();}
}
struct Foo: Base1<Foo>> {
    auto foo_impl () { return "foo";}
}
But I am not sure if this is the conventional way of doing multilevel inheritance using CRTP. Any comments?