[c++] invalid use of incomplete type

I'm trying to use a typedef from a subclass in my project, I've isolated my problem in the example below.

Does anyone know where I'm going wrong?

template<typename Subclass>
class A {
    public:
        //Why doesn't it like this?
        void action(typename Subclass::mytype var) {
            (static_cast<Subclass*>(this))->do_action(var);
        }
};

class B : public A<B> {
    public:
        typedef int mytype;

        B() {}

        void do_action(mytype var) {
            // Do stuff
        }
};

int main(int argc, char** argv) {
    B myInstance;
    return 0;
}

This is the output I get:

sean@SEAN-PC:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp
test.cpp: In instantiation of ‘A<B>’:
test.cpp:10:   instantiated from here
test.cpp:5: error: invalid use of incomplete type ‘class B’
test.cpp:10: error: forward declaration of ‘class B’

This question is related to c++ templates typedef crtp

The answer is


Not exactly what you were asking, but you can make action a template member function:

template<typename Subclass>
class A {
    public:
        //Why doesn't it like this?
        template<class V> void action(V var) {
                (static_cast<Subclass*>(this))->do_action();
        }
};

class B : public A<B> {
    public:
        typedef int mytype;

        B() {}

        void do_action(mytype var) {
                // Do stuff
        }
};

int main(int argc, char** argv) {
    B myInstance;
    return 0;
}

You need to use a pointer or a reference as the proper type is not known at this time the compiler can not instantiate it.

Instead try:

void action(const typename Subclass::mytype &var) {
            (static_cast<Subclass*>(this))->do_action();
    }

You can get around this by using a traits class:
It requires you set up a specialsed traits class for each actuall class you use.

template<typename SubClass>
class SubClass_traits
{};

template<typename Subclass>
class A {
    public:
        void action(typename SubClass_traits<Subclass>::mytype var)
        {
                (static_cast<Subclass*>(this))->do_action(var);
        }
};


// Definitions for B
class B;   // Forward declare

template<> // Define traits for B. So other classes can use it.
class SubClass_traits<B>
{
    public:
        typedef int mytype;
};

// Define B
class B : public A<B>
{
    // Define mytype in terms of the traits type.
    typedef SubClass_traits<B>::mytype  mytype;
    public:

        B() {}

        void do_action(mytype var) {
                // Do stuff
        }
};

int main(int argc, char** argv)
{
    B myInstance;
    return 0;
} 

You derive B from A<B>, so the first thing the compiler does, once it sees the definition of class B is to try to instantiate A<B>. To do this it needs to known B::mytype for the parameter of action. But since the compiler is just in the process of figuring out the actual definition of B, it doesn't know this type yet and you get an error.

One way around this is would be to declare the parameter type as another template parameter, instead of inside the derived class:

template<typename Subclass, typename Param>
class A {
    public:
        void action(Param var) {
                (static_cast<Subclass*>(this))->do_action(var);
        }
};

class B : public A<B, int> { ... };

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to templates

*ngIf else if in template 'if' statement in jinja2 template How to create a link to another PHP page Flask raises TemplateNotFound error even though template file exists Application not picking up .css file (flask/python) Django: How can I call a view function from template? Angularjs Template Default Value if Binding Null / Undefined (With Filter) HTML email in outlook table width issue - content is wider than the specified table width How to redirect on another page and pass parameter in url from table? How to check for the type of a template parameter?

Examples related to typedef

How do I use typedef and typedef enum in C? Overloading operators in typedef structs (c++) What is the difference between 'typedef' and 'using' in C++11? typedef fixed length array Typedef function pointer? C++ template typedef dereferencing pointer to incomplete type uint8_t vs unsigned char typedef struct vs struct definitions Understanding typedefs for function pointers in C

Examples related to crtp

invalid use of incomplete type