Compiler and linker errors
C++ "does not name a type": causes and fixes
“Does not name a type” means the compiler cannot resolve a type name where the code uses it. Common causes include a missing header, a missing std:: prefix, a statement outside a function, or using a type before its definition.
Read the name and location
The diagnostic usually quotes the unknown name. Start there: identify whether it should be a class, struct, alias, or standard-library type. Then check the include list, namespace, declaration order, and surrounding braces. The quoted name helps you decide whether the missing declaration should introduce a type or another identifier. MSVC often reports an unknown type with C2065 or C4430, depending on the source and compiler mode.
Failing C++17 example
#include <iostream>
string greeting = "Mira";
int main() {
std::cout << greeting << '\n';
return 0;
}
GCC diagnostic core:
error: 'string' does not name a typeAt namespace scope, GCC reports the unqualified string as an unknown type. MSVC reports C2065 for this name.
Fixed example
#include <iostream>
#include <string>
std::string greeting = "Mira";
int main() {
std::cout << greeting << '\n';
return 0;
}
Expected output:
Mira
Include and qualify standard types
The standard type is std::string, declared by <string>. At namespace scope, an unqualified string in a declaration such as string greeting = "Hi"; is not recognized as a type. Use std::string and include <string>. Inside a function, the same missing qualification usually produces a "was not declared in this scope" diagnostic. Apply the same header and namespace rule to std::vector. A misspelled or wrongly capitalized name, such as Vector or strng, is a different unknown type; match the declaration exactly.
Keep statements inside functions
A declaration such as int score = 7; is valid at namespace scope, but an assignment such as score = 7; is a statement and must run inside a function. If you accidentally close main too early, later statements appear at file scope and can trigger confusing type or declaration messages. Count braces from the function opening to the suspected line. Move executable statements into main or another function.
Define a type before using it by value
A compiler needs a complete class definition to create an object or access its members. If a function declares a local object before the struct definition appears, move the definition earlier or include its header. A forward declaration can name a class for pointers and references, but it does not provide enough information for a by-value object. Keep declarations in a header and definitions in one source file when a project has multiple files.
Failing C++17 example: use a type before its definition
#include <iostream>
Record makeRecord();
struct Record {
int value;
};
int main() {
const Record item = makeRecord();
std::cout << item.value << '\n';
return 0;
}
Record makeRecord() {
return {7};
}
GCC diagnostic core:
error: 'Record' does not name a typeThe function declaration names Record before the compiler has seen its definition. Move the struct definition above the declaration.
Fixed example
#include <iostream>
struct Record {
int value;
};
Record makeRecord();
int main() {
const Record item = makeRecord();
std::cout << item.value << '\n';
return 0;
}
Record makeRecord() {
return {7};
}
Expected output:
7
Include your own class header
Your class may be declared in a project header that the source file does not include. If a source file uses Record by value, include the header that defines it before the use.
Record.h
#pragma once
struct Record {
int value;
};
Failing C++17 example
#include <iostream>
int main() {
const Record item{7};
std::cout << item.value << '\n';
return 0;
}
GCC diagnostic core:
error: 'Record' does not name a typeMSVC reports C2065 for the undeclared class name. Compiler wording can vary by version.
Fixed example
Record.h (unchanged):
#pragma once
struct Record {
int value;
};
main.cpp:
#include <iostream>
#include "Record.h"
int main() {
const Record item{7};
std::cout << item.value << '\n';
return 0;
}
Expected output:
7
Two headers that include each other can expose one class before its definition is available. Break that cycle with a forward declaration when a class only stores a pointer or reference to the other class; include the full definition in the source file where it accesses members or creates an object by value.
Separate type errors from linker errors
A missing type name is a compile-time problem. Adding a function prototype does not define a missing class, and adding a using-directive does not include a missing header. Fix the first diagnostic, then rebuild. If compilation succeeds but linking reports an undefined reference, investigate whether a function definition is missing instead.
Exercise
Move the assignment into main. At file scope, count = 4; is parsed as a declaration and GCC reports that count does not name a type.
Broken program
#include <iostream>
int main() {
int count = 3;
}
count = 4;
Compiler diagnostic core:
error: 'count' does not name a typeMSVC reports C4430 for this missing type specifier.
Sample input: none.
Expected output after the fix:
4
Hint 1: A statement cannot run at namespace scope. Hint 2: Move only the assignment into main.
Show one possible solution
#include <iostream>
int count = 3;
int main() {
count = 4;
std::cout << count << '\n';
return 0;
}
Expected output:
4
Related guides
- Fix a name that is not declared in scope
- Read a no-matching-function diagnostic
- Understand an undefined-reference linker error
Keep learning with CppPath
Continue with the Header & Source Files lesson. The full lesson includes a quiz and a checked coding challenge with a free account.