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’
asked Mar 16, 2009 at 21:07
seanhodgesseanhodges
17.4k15 gold badges71 silver badges93 bronze badges
The reason is that when instantiating a class template, all its declarations (not the definitions) of its member functions are instantiated too. The class template is instantiated precisely when the full definition of a specialization is required. That is the case when it is used as a base class for example, as in your case.
So what happens is that A<B>
is instantiated at
class B : public A<B>
at which point B
is not a complete type yet (it is after the closing brace of the class definition). However, A<B>::action
‘s declaration requires B
to be complete, because it is crawling in the scope of it:
Subclass::mytype
What you need to do is delaying the instantiation to some point at which B
is complete. One way of doing this is to modify the declaration of action
to make it a member template.
template<typename T>
void action(T var) {
(static_cast<Subclass*>(this))->do_action(var);
}
It is still type-safe because if var
is not of the right type, passing var
to do_action
will fail.
answered Mar 16, 2009 at 21:36
1
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;
}
answered Mar 16, 2009 at 22:07
Martin YorkMartin York
256k85 gold badges333 silver badges558 bronze badges
2
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> { ... };
answered Mar 16, 2009 at 21:29
sthsth
221k53 gold badges281 silver badges367 bronze badges
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();
}
answered Mar 16, 2009 at 21:17
1
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;
}
answered Mar 16, 2009 at 21:45
John DiblingJohn Dibling
99.4k30 gold badges184 silver badges324 bronze badges
In this guide, we will walk you through the process of troubleshooting and fixing C++ Invalid Use of Incomplete Type Errors. These errors usually occur when you try to use a class or structure that has been declared, but not yet defined or fully specified. Let’s dive into the details and learn how to fix these errors in your C++ code.
Table of Contents
- Understanding Invalid Use of Incomplete Type Errors
- Identifying the Causes of Invalid Use of Incomplete Type Errors
- Step-by-Step Guide to Fixing Invalid Use of Incomplete Type Errors
- FAQ
- Related Links
Understanding Invalid Use of Incomplete Type Errors
In C++, an incomplete type is a type that has been declared but not defined. This means that the compiler doesn’t have enough information about the type to determine its size or layout in memory. When you try to use an incomplete type in a way that requires the compiler to know its size or layout, you will encounter an «Invalid Use of Incomplete Type» error.
Here’s an example of an incomplete type error:
class MyClass; // Forward declaration
void myFunction(MyClass obj) {
// Invalid use of incomplete type 'class MyClass'
int x = obj.someFunction();
}
In this example, MyClass
has been declared but not defined, so the compiler doesn’t know the size or layout of the class. When you try to use an object of type MyClass
inside the myFunction
function, the compiler generates an error.
Identifying the Causes of Invalid Use of Incomplete Type Errors
There are several common causes for Invalid Use of Incomplete Type Errors:
- Missing includes: If you forget to include the header file that contains the definition of a type, the compiler will only have access to its declaration and will treat it as an incomplete type.
- Forward declarations: When you use a forward declaration instead of including the header file, the type remains incomplete until it’s defined later in the code.
- Circular dependencies: If two types depend on each other, the compiler may not be able to determine their size and layout, which can result in an incomplete type error.
Step-by-Step Guide to Fixing Invalid Use of Incomplete Type Errors
- Check your includes: Make sure you’ve included the appropriate header files that contain the definitions of the types you’re using. If you’re unsure which header files to include, consult the documentation or source code of the library or module you’re using.
- Replace forward declarations with includes: If you’re using a forward declaration, consider replacing it with an include statement for the header file that contains the type’s definition. This will provide the compiler with the necessary information about the type.
- Resolve circular dependencies: If two types depend on each other, you may need to refactor your code to break the circular dependency. This can be done by using pointers or references instead of direct object instances, or by moving the common functionality to a base class or separate utility class.
FAQ
Why does forward declaration cause an incomplete type error?
Forward declaration is a technique used to inform the compiler about the existence of a class or structure without providing its full definition. This can be helpful in certain situations to avoid circular dependencies or reduce compile times. However, when you use a forward-declared type in a way that requires the compiler to know its size or layout, you will encounter an incomplete type error.
Can I use pointers or references to avoid incomplete type errors?
Yes, using pointers or references can help you avoid incomplete type errors because they don’t require the compiler to know the size or layout of the underlying type. Instead, the compiler only needs to know the size of the pointer or reference itself. This can be a useful technique when working with forward-declared types or circular dependencies.
How can I fix circular dependencies that cause incomplete type errors?
To fix circular dependencies, you can use one or more of the following techniques:
- Use pointers or references instead of direct object instances, as they don’t require the compiler to know the size or layout of the underlying type.
- Move common functionality to a base class or separate utility class, which can then be included by both dependent classes without creating a circular dependency.
Is it possible to use forward declarations and avoid incomplete type errors?
Yes, it is possible to use forward declarations without encountering incomplete type errors, as long as you only use the forward-declared type in ways that don’t require the compiler to know its size or layout. This typically means using pointers or references to the forward-declared type or only using the type in function declarations, not definitions.
What is the difference between a declaration and a definition in C++?
In C++, a declaration introduces a name and a type to the compiler, while a definition provides the complete information required to create an instance of the type. For example, a class declaration specifies the class name and any base classes or interfaces it inherits from, while the class definition includes the full list of member variables and member functions.
- C++ Forward Declarations
- C++ Incomplete Types
- C++ Class Definitions
- C++ Circular Dependency Solutions
- C++ Headers and Includes
Problem:
You are compiling a C/C++ program using GCC. You get an error message similar to this:
error: invalid use of incomplete type ‘class SomeType’
Solution:
There are multiple possible issues, but in general this error means that GCC can’t find the full declaration of the given class or struct.
The most common issue is that you are missing an #include
clause. Find out in which header file the declaration resides, i.e. if the error message mentions class Map
, look for something like
class Map { // ... };
Usually the classes reside in header files that are similar to their name, e.g. MyClass
might reside in a header file that is called MyClass.h
, MyClass.hpp
or MyClass.hxx
, so be sure to look for those files first. Note that you might also be looking for a type from a library. Often the best approach is to google C++ <insert the missing type here>
to find out where it might be located.
Another possible reason is that you have your #include
clause after the line where the error occurs. If this is the case, ensure that all required types are included before they are used.
For other reasons, see StackOverflow, e.g. this post
Заголовочные файлы надо писать так, чтобы порядок их подключения был неважен.
В реализации подключать первым собственный заголовочник — правильная идея; так мы убеждаемся, что в заголовочнике нет недостающих зависимостей.
Совать #include в пространство имён без хорошего обоснования не стоит.
По вашему обтекаемому описанию не видно, как устроены ваши заголовки, именованное пространство имён или нет, закрыты ли все скобки в хедерах, и т.д. Но причина ошибки очевидна: из-за пространств имён компилятор не отождествил классы в первом и втором заголовке; предварительное объявление «class A;» осталось неразрешённым. Поэкспериментировав, я выяснил вот что.
// Не компилируется!
class A;
namespace XXX {
std::shared_ptr<A> a;
class A { public: int x; };
void xxx();
}
void XXX::xxx() {
a->x;
}
// Компилируется!
class A;
namespace XXX {
class A { public: int x; };
std::shared_ptr<A> a;
void xxx();
}
void XXX::xxx() {
a->x;
}
// Тоже компилируется!
namespace XXX {
class A;
}
namespace XXX {
std::shared_ptr<A> a;
class A { public: int x; };
void xxx();
}
void XXX::xxx() {
a->x;
}
В первом случае shared_ptr<::A>
, который, естественно, не определён (есть XXX::A
).
Во втором — определение наперёд ::A вообще ни на что не сдалось; используется shared_ptr<XXX::A>
.
В третьем примере только один тип, XXX::A.
Если первым идёт не использование, а make_shared — выходит другая ошибка, не удаётся получить sizeof недоопределённого типа A.
Invalid use of incomplete type is a type of programming error that means the programmer has not included the type of the file or command, due to which the program cannot compile or is not recognized by the program.
This article explains this error in detail, and the reader will understand all the possible solutions to this error. Without any further delay, let’s start with the reasons that cause this error.
Contents
- Why Is the “Invalid Use of Incomplete Type” Error Message Occurring?
- – The Map Is Inside a Function in the Combat Class
- – The Program Did Not Pass the Compiler
- – The Function Was Not Declared
- – Syntax Errors
- How To Resolve the “Invalid Use of Incomplete Type” Error Message?
- – The Map Should Not Be Inside a Function
- – The Function Should Be Declared
- – Check and Remove All Syntax Errors
- – Use #Include Clause Properly
- Conclusion
- References
Why Is the “Invalid Use of Incomplete Type” Error Message Occurring?
The “invalid use of incomplete type” error message occurs because the program is not recognized or the compiler cannot read the program due to syntax or other programming errors. Major reasons behind this error include “the map is inside a function”, failure to pass the compiler and undeclared functions.
In a nutshell, the main reasons behind this error are:
- The Map is inside a function in the combat class
- The program did not pass the compiler.
- The function was not declared.
- Syntax errors.
– The Map Is Inside a Function in the Combat Class
When Map is inside another function, the error will occur. The programmer must define the Map before using it in a class. In the following example, the programmer has used Map inside a function in the combat class, and their Map was also not defined; thus, an error occurred.
Moreover, a forward declaration can define a particular class later, so it is alright to use it as a reference or have pointers to objects, etc. However, it cannot define what member a class has, so when it comes to compiling, it cannot happen until Map is fully declared. Invalid use of incomplete type template is given below:
For example:
#include <string>
#include <cstdlib>
using namespace std;
class Map;
class Player
{
Public:
int damage;
int health;
int gems;
int defense=0;
string race;
string name;
string location;
};
class Enemy
{
Public:
int ehealth;
int edamage;
int edefense;
int echoice;
};
class combat
{
Public:
Map* mapobj;
int damagedealt;
Player playerobj;
Enemy enemeyobj;
string cchoice;
string retry;
void initial()
};
– The Program Did Not Pass the Compiler
When the program does not pass the compiler, an error message will occur, such as the Invalid use of incomplete type FooReaderPrivate. The error can occur because the user did not put the inline portion into the *.cpp implementation file.
However, sometimes, it is just a design/structure issue in the program. In some programs, cross reference of two classes is okay to do, but it is recommended to avoid it at the start of the design.
For example:
public:
FooReader() : d(new FooReaderPrivate(this)) { }
private:
FooReaderPrivate* e;
};
=== In a separate file ===
class FooReaderPrivate {
public:
FooReaderPrivate(FooReader*) : parent(d) { }
private:
FooReader* parent;
};
– The Function Was Not Declared
As mentioned above, this particular error message will occur when the function is not declared completely before compiling. The programmer must show the declaration of the function. Another reason why this error occurs is that the user may not have created an interface class with pure virtual methods for the Map class.
– Syntax Errors
Syntax errors are the most common reason such errors occur in the first place. While compiling a program in a C/C++ program using GCC, the programmer can get an error notification, such as fix-GCC-error-invalid-use-of-incomplete-type-class.no-highlight or error: invalid use of incomplete type ‘class SomeType’.
Furthermore, another type of syntax error that causes this message to occur can be due to the wrong usage of the #include function in the program. Furthermore, the compilation of files was not done properly by using either .h or .cpp syntax. Thus, an error occurred. Some other types of similar error messages due to the wrong syntax include:
- Invalid use of incomplete type / forward declaration c++.
- Invalid use of incomplete type c++.
- Invalid application of ‘sizeof’ to incomplete type.
- Invalid use of incomplete typedef.
- Invalid use of incomplete type’ struct.
- Gtest invalid use of incomplete type.
- Invalid use of incomplete type qt.
How To Resolve the “Invalid Use of Incomplete Type” Error Message?
You can resolve the invalid use of incomplete type error messages by avoiding the use of Map in the function. Moreover, the Map should always be fully declared before and the function must be clearly declared as well before compiling.
However, there are various other reasons, and they are discussed below:
– The Map Should Not Be Inside a Function
In order to resolve this error, the programmer should follow the C++ pattern of the class declaration in a .h file and the function bodies in a .cpp file. They have to be careful not to put Maps inside a function during this period.
By using this technique, all the declarations will appear before the first declaration, and the compiler will work without causing any errors.
– The Function Should Be Declared
As mentioned above, it is necessary to declare the function properly, or else the program will not be recognized, and an error will occur. The programmer has to create an interface class with pure virtual methods for the Map class.
They should declare the functions they are using and put the created interface class at the beginning of the file. This way, the error will be resolved.
Moreover, don’t forget to derive the Map from the file and use a pointer to the interface. Pointers are used in the process of declaring the functions. Following is an example of the correct way of declaring a function:
Program Example:
#include <string>
#include <cstdlib>
using namespace std;
class MapIf {
public:
virtual void relaypointa() = 1;
};
class Player {
public:
int health;
int damage;
int defense;
int gems = 1;
string race;
string name;
string location;
};
class Enemy {
public:
int ehealth;
int edamage;
int edefense;
int echoice;
};
class combat {
public:
MapIf * mapobj;
int damagedealt;
Player playerobj;
Enemy enemeyobj;
string cchoice;
string retry;
void initial() {
cout << “A wild tiger has appearedn”;
cout << “What do we do?n”;
cout << “—————————n”;
cout << “|————————-|n”;
cout << “|—-Attack it—–Defend yourself—-|n”;
cout << “|————————-|n”;
cout << “—————————n”;
cin >> cchoice;
this -> battlefield();
}
void newturn() {
cout << “The tiger is still alive!”;
cout << “What do we do?”;
cout << “n—————————n”;
cout << “|————————-|n”;
cout << “|—-Attack it—–Defend yourself—-|n”;
cout << “|————————-|n”;
cout << “—————————n”;
cin >> cchoice;
this -> battlefield();
};
void battlefield() {
enemeyobj.echoice = rand() % 3;
if (enemeyobj.echoice = 2) {
if (cchoice == “Attack it”) {
playerobj.damage;
enemeyobj.ehealth = enemeyobj.ehealth – playerobj.damage;
cout << “We did ” << playerobj.damage << ” points of damage to the enemy.n”;
if (enemeyobj.ehealth > 1) {
playerobj.health = enemeyobj.edamage – playerobj.health;
cout << “The enemy attacked us. We now have ” << playerobj.health << “health”;
if (playerobj.health > 1) {
this -> newturn();
} else if (playerobj.health <= 1) {
cout << playerobj.name << “was finally killedn”;
cout << “Game Is Over”;
}
} else if (enemeyobj.ehealth <= 1) {
cout << “We have defeated the tiger!”;
if (playerobj.location == “b”) {
mapobj -> relaypointa();
}
};
– Check and Remove All Syntax Errors
The programmer should carefully scan the program and remove all the possible syntax errors in order to remove “incomplete type” error messages. This can also be done by using special software. In general, such type of error means that GCC cannot find the full declaration of the current class or struct.
The most common syntax issue is that the program does not have a #include clause in it. Try to find out in which of the header files the declaration resides. For example, if the error message mentions Map class, then look for something like:
– Use #Include Clause Properly
Another reason for this error message to occur is due to the use of the #include function after the line where the error occurs. In order to resolve it, ensure that all required types are included before their usage.
Conclusion
After reading this guide, the reader will know the possible reasons behind the invalid use of incomplete type errors and its solutions as well. Some key takeaways from this article are:
- The programmer should have completely declared all the functions and Maps before calling a compiling function.
- Sometimes, the program is written in a way that is not recognized by the compiler; thus, the error occurs. Therefore, ensure the program is recognizable.
- Do not use the #include function after the error message. Use it at the beginning of the program.
The reader can now resolve their similar error message and continue with the program smoothly. Thank you for reading!
References
- https://stackoverflow.com/questions/20013901/im-getting-an-error-invalid-use-of-incomplete-type-class-map
- https://techoverflow.net/2018/01/21/how-to-fix-gcc-error-invalid-use-of-incomplete-type-class/
- Author
- Recent Posts
Your Go-To Resource for Learn & Build: CSS,JavaScript,HTML,PHP,C++ and MYSQL. Meet The Team