21

Can anyone tell me when does a c++ compiler throw an "incomplete type error"?

Note: I have intentionally left this question a little open ended so that I can debug my code myself.

Nickal
  • 669
  • 2
  • 11
  • 25
  • A possibly cv-qualified type that is not defined or is void is an incomplete type. An object shall not be defined as an incomplete type. And no, this is not a good question format – Passer By Jul 07 '17 at 05:36
  • See this for example https://stackoverflow.com/questions/6349822/incomplete-type-in-class-which-has-a-member-of-the-same-type-of-the-class-itse – Abdulkadir Dalga Jul 07 '17 at 05:37
  • @PasserBy I got somebody who answered my question and helped me find out the error. He was more helpful that you. Nevertheless, thank you. – Nickal Jul 07 '17 at 09:13
  • When debug code that compiled by clang++, I reproduced, and switch to g++. – douyu Nov 06 '22 at 04:36

4 Answers4

33

This happens usually when the compiler has seen a forward declaration but no full definition of this type, while the type is being used somewhere. For example:

class A;

class B { A a; };

The second line will cause a compiler error and, depending on the compiler, will report an incomplete type (other compilers give you a different error, but the meaning is the same).

When you however just use a pointer to such a forward declaration no complain will come up, since the size of a pointer to a class is always known. Like this:

class A;
class B {
   A *a;
   std::shared_ptr<A> aPtr;
};

If you ask what could be wrong in a concrete application or library when this error comes up: that happens usually when a header is included which contains the forward declaration, but full definition hasn't been found yet. The solution is quite obvious: include also the header that gives you access to the full type. Sometimes you may also simply have no or the wrong namespace used for a type and need to correct that instead.

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • Actually in my case, it is coming from a PCL library header file . Since it is a library file, there should not be any error in the file as such. There should be something else which is driving in this error. – Nickal Jul 07 '17 at 05:50
  • does it happen when the header files are included in the project but library is not linked??? – Nickal Jul 07 '17 at 06:17
  • No, compilation and linking are 2 different steps. First the compiler has to create object code (and therefor needs to know all used types), then the linker links them all together into the final binaries. – Mike Lischke Jul 07 '17 at 08:18
  • Thanks. The edit was very useful. I included the file that contained full definition before including the header. That worked. – Nickal Jul 07 '17 at 09:10
  • This also comes up when a class definition has a member whose type is itself (e.g., a binary tree `Node` class that contains a left/right `Node` pointer). Question: how is the size of a pointer to a class always known? Is it fixed size (32-bits on a 32-bit machine, 64 bit on a 64-bit machine)? – MTV Jul 01 '22 at 16:28
  • Is it fixed sized, per architecture. But please ask follow up questions as own ones in SO. – Mike Lischke Jul 07 '22 at 06:56
3

This happens when we try to use a class/object or its methods and they have not been defined yet. For example

class A;
class B {
    class A obj;
}

or

class A;
class B {
    class A *obj;
    B() {   
           obj->some_method();
        }

To resolve this, A has to be defined first or its total declaration has to given(best practice is to do it in a header file) and all methods of both the classes should be defined later(best practice is to do it in another file).

class A {
    //definition
}
class B {
class A obj;
}
2

This also happens when you use forward declaration with std::unique_ptr (for example, to implement PIMPL idiom) in your class with a default destructor, which leads to such issue.

It is good explained here: Forward declaration with unique_ptr?

Mykola Khyliuk
  • 1,234
  • 1
  • 9
  • 16
1

In my case, it was due to poor knowledge of templates. I declared a class between a template definition and the function which was associated with that template.

template<typename T>
class
{
  foo a;
  foo b;
};
function(T a,int b)
{

 . . . . .

}

And this created issues as the template definition is associated with the class, in this case, an error comes in the parameter list of the function that T is not defined and also that incomplete type is not allowed. If you have to use a template for multiple entities, then you have to reuse this statement before that entities' definition:

template<typename T>