c++oopcrtp

CRTP parent cannot access grandparent


#include <iostream>
#include <string>


template<typename T>
class animal
{
    public:
        std::string print()
        {
            return static_cast<T*>(this)->impl_print();
        };

    protected:
        inline const static std::string verb = "says ";  
};

template<typename T>
class pet : public animal<pet<T>>
{

    public:
        std::string impl_print()
        {
            return verb + static_cast<T*>(this)->impl_print();
        };

        inline const static std::string excite = "!"; 
};

class cat : public pet<cat>
{
    public:
        std::string impl_print()
        {
            return "meow" + excite;
        };
};

class dog : public pet<dog>
{
    public:
        std::string impl_print()
        {
            return "WOOF" + excite;
        };
};

int main()
{

    cat a;
    dog c;

    std::cout<<a.print()<<std::endl;
    std::cout<<c.print()<<std::endl;

    return 0;
}

This gets a "'verb' was not declared in this scope" error. Why are the classes at the end of the CRTP chain able to access variables declared by the parent, but the middle class can't access a variable declared by its own parent?

Tested with gcc13.


Solution

  • Because its parent is dependant on template parameter. It's not known what you meant there by using id verb - a global variable or a class member, which formally wasn't declared within this class template. There can be a specialization of animal which could define verb differently before instantiation. Using this-> will fix it.

        std::string impl_print()
        {
            return this->verb + static_cast<T*>(this)->impl_print();
        };