C++ Module 1 – Start here: toolchains, compiling and first programs
Reading C++ compiler errors and fixing old code
Read GCC and Clang error messages from the first line to the note that explains them, fix ten common beginner errors, and modernise pre-standard C++ code.
What you will learn
- Read an error message from its first line to the note that explains it
- Fix the ten most common beginner errors
- Recognise pre-standard code (iostream.h, conio.h, void main) and modernise it
Before you start
What you’ll learn · Before you start
What you will learn
- Read an error message from its first line to the note that explains it
- Fix the ten most common beginner errors
- Recognise pre-standard code (iostream.h, conio.h, void main) and modernise it
Before you start
On this page
A compiler error is a report with a fixed shape: where the problem is, how serious it is, what the compiler expected,
and often a suggestion. Read the first error first, from its location to the note: lines under it, because one
mistake often produces several errors and only the first one is reliable. This lesson takes you through the parts of
a message, ten errors that beginners meet most, the long errors that templates produce, and old textbook code that
modern compilers reject, with the exact words that Apple clang 21 and GCC 16 printed for each. The two compilers word
the same problem differently, so knowing both helps when you search for a message.
The parts of a diagnostic
This program uses cout without std:::
#include <iostream>
int main() {
cout << "Namaste\n";
} from session import run
run("""
g++-16 -std=c++23 -Wall -Wextra -c undeclared_cout.cpp -o undeclared_cout.o
clang++ -std=c++23 -Wall -Wextra -c undeclared_cout.cpp -o undeclared_cout.o
""") Output
$ g++-16 -std=c++23 -Wall -Wextra -c undeclared_cout.cpp -o undeclared_cout.o
undeclared_cout.cpp: In function 'int main()':
undeclared_cout.cpp:4:5: error: 'cout' was not declared in this scope; did you mean 'std::cout'?
4 | cout << "Namaste\n";
| ^~~~
| std::cout
In file included from undeclared_cout.cpp:1:
/opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/iostream:65:18: note: 'std::cout' declared here
65 | extern ostream cout; ///< Linked to standard output
| ^~~~
[exit status 1]
$ clang++ -std=c++23 -Wall -Wextra -c undeclared_cout.cpp -o undeclared_cout.o
undeclared_cout.cpp:4:5: error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
4 | cout << "Namaste\n";
| ^~~~
| std::cout
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/iostream:57:42: note: 'std::cout' declared here
57 | extern _LIBCPP_EXPORTED_FROM_ABI ostream cout;
| ^
1 error generated.
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 cout_session.py
GCC printed the error as five pieces of information, one after the other:
undeclared_cout.cpp: In function 'int main()':names the function the problem is in. Clang leaves this line out.undeclared_cout.cpp:4:5:is the file, the line and the column. Most editors jump there when you click it.error:is the severity. An error stops the build, a warning does not, and a note adds information to the message above it.'cout' was not declared in this scope; did you mean 'std::cout'?is the message itself, here with a guess.- The source line follows, with
^~~~under the exact spot, and below it a fix-it line showing what to type:std::cout.
Then note: 'std::cout' declared here points into the <iostream> header, to show where the suggested name lives.
Clang’s version of the same error reads use of undeclared identifier 'cout'; did you mean 'std::cout'?, with the
same fix-it line. Different wording, the same information.
One error message, part by part
Text description of the diagram
The diagram splits GCC 16's error for cout used without std:: into six numbered boxes, in two columns, in the order the compiler prints them.
- Where: undeclared_cout.cpp:4:5, the file, the line and the column.
- How serious: error, which stops the build, or warning, which does not.
- What went wrong: 'cout' was not declared in this scope.
- A guess: did you mean 'std::cout'?
- The source line, with ^~~~ under the spot and a fix-it line that shows std::cout.
- A note: 'std::cout' declared here, pointing into the <iostream> header.
Fix the first error first
One mistake can produce a cascade. This program uses std::vector but never includes <vector>:
#include <cstdio>
int main() {
std::vector<int> runs{4, 6, 1};
std::printf("%zu\n", runs.size());
} from session import run
# All the errors first, then only the first one.
run("""
clang++ -std=c++23 -Wall -Wextra -c missing_vector.cpp -o missing_vector.o
g++-16 -std=c++23 -Wall -Wextra -c missing_vector.cpp -o missing_vector.o
clang++ -std=c++23 -ferror-limit=1 -c missing_vector.cpp -o missing_vector.o
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c missing_vector.cpp -o missing_vector.o
missing_vector.cpp:4:10: error: no member named 'vector' in namespace 'std'
4 | std::vector<int> runs{4, 6, 1};
| ^~~~~~
missing_vector.cpp:4:20: error: expected '(' for function-style cast or type construction
4 | std::vector<int> runs{4, 6, 1};
| ~~~^
missing_vector.cpp:4:22: error: use of undeclared identifier 'runs'
4 | std::vector<int> runs{4, 6, 1};
| ^~~~
missing_vector.cpp:5:26: error: use of undeclared identifier 'runs'
5 | std::printf("%zu\n", runs.size());
| ^~~~
4 errors generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c missing_vector.cpp -o missing_vector.o
missing_vector.cpp: In function 'int main()':
missing_vector.cpp:4:10: error: 'vector' is not a member of 'std'
4 | std::vector<int> runs{4, 6, 1};
| ^~~~~~
missing_vector.cpp:2:1: note: 'std::vector' is defined in header '<vector>'; this is probably fixable by adding '#include <vector>'
1 | #include <cstdio>
+++ |+#include <vector>
2 |
missing_vector.cpp:4:17: error: expected primary-expression before 'int'
4 | std::vector<int> runs{4, 6, 1};
| ^~~
missing_vector.cpp:5:26: error: 'runs' was not declared in this scope
5 | std::printf("%zu\n", runs.size());
| ^~~~
[exit status 1]
$ clang++ -std=c++23 -ferror-limit=1 -c missing_vector.cpp -o missing_vector.o
missing_vector.cpp:4:10: error: no member named 'vector' in namespace 'std'
4 | std::vector<int> runs{4, 6, 1};
| ^~~~~~
fatal error: too many errors emitted, stopping now [-ferror-limit=]
2 errors generated.
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 vector_session.py
Clang 21 printed four errors: no member named 'vector' in namespace 'std' on line 4, then
expected '(' for function-style cast or type construction, and twice use of undeclared identifier 'runs'. Only the
first is the mistake. Once std::vector is unknown, the declaration of runs fails, and every later use of runs
fails with it. GCC 16 printed three errors, and its first one came with the exact cure:
note: 'std::vector' is defined in header '<vector>'; this is probably fixable by adding '#include <vector>'. Adding
that one line removes every error.
So read the first error, fix it, and compile again. Later errors may disappear, or they may change. Both compilers can
stop early for you: -fmax-errors=1 for GCC and -ferror-limit=1 for Clang show only the first error. The last
command of the session shows Clang’s version, which ends with
fatal error: too many errors emitted, stopping now [-ferror-limit=]. Clang stops after 20 errors by default; GCC has
no limit unless you set one.
The line in the message is not always the line to fix
A compiler reports a problem where it notices it, which can be after the mistake. One program misses a semicolon, the other a closing brace:
Missing ; · missing_semicolon.cpp
#include <iostream>
int main() {
int marks = 92
std::cout << marks << '\n';
} Missing } · missing_brace.cpp
#include <iostream>
int main() {
for (int over = 1; over <= 3; ++over) {
std::cout << "Over " << over << '\n';
std::cout << "Innings over\n";
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -c missing_semicolon.cpp -o missing_semicolon.o
g++-16 -std=c++23 -Wall -Wextra -c missing_semicolon.cpp -o missing_semicolon.o
clang++ -std=c++23 -Wall -Wextra -c missing_brace.cpp -o missing_brace.o
g++-16 -std=c++23 -Wall -Wextra -c missing_brace.cpp -o missing_brace.o
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c missing_semicolon.cpp -o missing_semicolon.o
missing_semicolon.cpp:4:19: error: expected ';' at end of declaration
4 | int marks = 92
| ^
| ;
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c missing_semicolon.cpp -o missing_semicolon.o
missing_semicolon.cpp: In function 'int main()':
missing_semicolon.cpp:5:5: error: expected ',' or ';' before 'std'
5 | std::cout << marks << '\n';
| ^~~
missing_semicolon.cpp:4:9: warning: unused variable 'marks' [-Wunused-variable]
4 | int marks = 92
| ^~~~~
[exit status 1]
$ clang++ -std=c++23 -Wall -Wextra -c missing_brace.cpp -o missing_brace.o
missing_brace.cpp:8:2: error: expected '}'
8 | }
| ^
missing_brace.cpp:3:12: note: to match this '{'
3 | int main() {
| ^
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c missing_brace.cpp -o missing_brace.o
missing_brace.cpp: In function 'int main()':
missing_brace.cpp:8:2: error: expected '}' at end of input
8 | }
| ^
missing_brace.cpp:3:12: note: to match this '{'
3 | int main() {
| ^
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 lines_session.py
Clang pointed at the right place, line 4, column 19, with expected ';' at end of declaration and a fix-it line
showing the ;. GCC reported expected ',' or ';' before 'std' on line 5, because it only knew the declaration
had not ended when it reached the next word, std. GCC then added a knock-on warning, unused variable 'marks',
because the broken declaration swallowed the line that used marks. When the reported line looks fine, look at the
end of the line above it.
A missing closing brace is reported even further away, at the end of the file. Both compilers reported line 8, the
last line, with expected '}' (Clang) or expected '}' at end of input (GCC), and both added note: to match this '{' pointing at line 3, the brace of main. Yet the brace that is missing closes
the for loop on line 4: the closing brace on line 8 was taken as the end of the loop, which left main open. The
compiler can only tell you that braces do not balance, not which one you forgot, so check the indentation of each
block.
Ten errors you will meet
Typing mistakes
Besides a missing ; or }, a common one is code copied from a PDF, a word processor or a chat app, where straight
quotes have become curly ones:
Curly quotes · smart_quotes.cpp
#include <iostream>
int main() {
std::cout << “Hello” << '\n';
} Non-breaking space · non_breaking_space.cpp
#include <iostream>
int main() {
int runs = 4;
std::cout << runs << '\n';
} from session import run
run("""
clang++ -std=c++23 -c smart_quotes.cpp -o smart_quotes.o
g++-16 -std=c++23 -c smart_quotes.cpp -o smart_quotes.o
clang++ -std=c++23 -c non_breaking_space.cpp -o non_breaking_space.o
g++-16 -std=c++23 -c non_breaking_space.cpp -o non_breaking_space.o
""") Output
$ clang++ -std=c++23 -c smart_quotes.cpp -o smart_quotes.o
smart_quotes.cpp:4:18: error: unexpected character <U+201C>
4 | std::cout << “Hello” << '\n';
| ^
smart_quotes.cpp:4:26: error: character <U+201D> not allowed in an identifier
4 | std::cout << “Hello” << '\n';
| ^
smart_quotes.cpp:4:21: error: use of undeclared identifier 'Hello”'
4 | std::cout << “Hello” << '\n';
| ^~~~~~
3 errors generated.
[exit status 1]
$ g++-16 -std=c++23 -c smart_quotes.cpp -o smart_quotes.o
smart_quotes.cpp:4:18: error: extended character “ is not valid in an identifier
4 | std::cout << “Hello” << '\n';
| ^
smart_quotes.cpp:4:18: error: extended character ” is not valid in an identifier
smart_quotes.cpp: In function 'int main()':
smart_quotes.cpp:4:18: error: '“Hello”' was not declared in this scope
4 | std::cout << “Hello” << '\n';
| ^~~~~~~
[exit status 1]
$ clang++ -std=c++23 -c non_breaking_space.cpp -o non_breaking_space.o
non_breaking_space.cpp:4:8: warning: treating Unicode character as whitespace [-Wunicode-whitespace]
4 | int runs = 4;
| ^
1 warning generated.
$ g++-16 -std=c++23 -c non_breaking_space.cpp -o non_breaking_space.o
non_breaking_space.cpp:4:5: error: extended character is not valid in an identifier
4 | int runs = 4;
| ^
non_breaking_space.cpp: In function 'int main()':
non_breaking_space.cpp:4:5: error: 'int runs' was not declared in this scope
4 | int runs = 4;
| ^~~~~~~~
non_breaking_space.cpp:5:18: error: 'runs' was not declared in this scope
5 | std::cout << runs << '\n';
| ^~~~
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 copied_session.py
Clang printed unexpected character <U+201C>, naming the Unicode code point of the left curly quote, then two
knock-on errors. GCC printed extended character “ is not valid in an identifier. The cure is to retype the quotes
as ". A non-breaking space, which looks exactly like a space, is the other usual suspect: GCC rejected it with
the same message, while Clang treated it as a space and only warned treating Unicode character as whitespace.
Names the compiler cannot find
Used before declared · use_before_declare.cpp
#include <iostream>
int main() {
std::cout << area(3, 4) << '\n';
}
int area(int width, int height) {
return width * height;
} Missing <algorithm> · sort_without_algorithm.cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> runs{4, 6, 1};
std::sort(runs.begin(), runs.end());
std::cout << runs.front() << '\n';
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -c use_before_declare.cpp -o use_before_declare.o
g++-16 -std=c++23 -Wall -Wextra -c use_before_declare.cpp -o use_before_declare.o
g++-16 -std=c++23 -Wall -Wextra sort_without_algorithm.cpp -o sort_without_algorithm && ./sort_without_algorithm
clang++ -std=c++23 -Wall -Wextra sort_without_algorithm.cpp -o sort_without_algorithm
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c use_before_declare.cpp -o use_before_declare.o
use_before_declare.cpp:4:18: error: use of undeclared identifier 'area'
4 | std::cout << area(3, 4) << '\n';
| ^~~~
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c use_before_declare.cpp -o use_before_declare.o
use_before_declare.cpp: In function 'int main()':
use_before_declare.cpp:4:18: error: 'area' was not declared in this scope
4 | std::cout << area(3, 4) << '\n';
| ^~~~
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra sort_without_algorithm.cpp -o sort_without_algorithm && ./sort_without_algorithm
1
$ clang++ -std=c++23 -Wall -Wextra sort_without_algorithm.cpp -o sort_without_algorithm
sort_without_algorithm.cpp:6:10: error: no member named 'sort' in namespace 'std'
6 | std::sort(runs.begin(), runs.end());
| ^~~~
1 error generated.
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 names_session.py
A function must be declared before the line that calls it. In the first file area is defined after main, so both
compilers stop at the call: use of undeclared identifier 'area' (Clang) and 'area' was not declared in this scope
(GCC). Move the function above main, or put a declaration such as int area(int width, int height); before it.
The second file is the dangerous kind. It calls std::sort without #include <algorithm>. GCC 16 compiled it and the
program printed 1, because one of the headers it did include pulls in std::sort on its own. Clang 21, with a
different standard library, stopped with no member named 'sort' in namespace 'std'. Code like this builds on one
computer and fails on the next, or on an online judge. Include the header of everything you use; the reference pages
for each function name its header.
Types and calls
Wrong type · wrong_type.cpp
#include <iostream>
int main() {
int overs = "20";
std::cout << overs << '\n';
} Wrong arguments · wrong_arguments.cpp
#include <iostream>
int area(int width, int height) {
return width * height;
}
int main() {
std::cout << area(3) << '\n';
} Missing () · member_without_call.cpp
#include <iostream>
#include <string>
int main() {
std::string name = "Asha";
std::cout << name.size << '\n';
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -c wrong_type.cpp -o wrong_type.o
g++-16 -std=c++23 -Wall -Wextra -c wrong_type.cpp -o wrong_type.o
clang++ -std=c++23 -Wall -Wextra -c wrong_arguments.cpp -o wrong_arguments.o
g++-16 -std=c++23 -Wall -Wextra -c wrong_arguments.cpp -o wrong_arguments.o
clang++ -std=c++23 -Wall -Wextra -c member_without_call.cpp -o member_without_call.o
g++-16 -std=c++23 -Wall -Wextra -c member_without_call.cpp -o member_without_call.o
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c wrong_type.cpp -o wrong_type.o
wrong_type.cpp:4:9: error: cannot initialize a variable of type 'int' with an lvalue of type 'const char[3]'
4 | int overs = "20";
| ^ ~~~~
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c wrong_type.cpp -o wrong_type.o
wrong_type.cpp: In function 'int main()':
wrong_type.cpp:4:17: error: invalid conversion from 'const char*' to 'int' [-fpermissive]
4 | int overs = "20";
| ^~~~
| |
| const char*
[exit status 1]
$ clang++ -std=c++23 -Wall -Wextra -c wrong_arguments.cpp -o wrong_arguments.o
wrong_arguments.cpp:8:18: error: no matching function for call to 'area'
8 | std::cout << area(3) << '\n';
| ^~~~
wrong_arguments.cpp:3:5: note: candidate function not viable: requires 2 arguments, but 1 was provided
3 | int area(int width, int height) {
| ^ ~~~~~~~~~~~~~~~~~~~~~
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c wrong_arguments.cpp -o wrong_arguments.o
wrong_arguments.cpp: In function 'int main()':
wrong_arguments.cpp:8:22: error: too few arguments to function 'int area(int, int)'
8 | std::cout << area(3) << '\n';
| ~~~~^~~
wrong_arguments.cpp:3:5: note: declared here
3 | int area(int width, int height) {
| ^~~~
[exit status 1]
$ clang++ -std=c++23 -Wall -Wextra -c member_without_call.cpp -o member_without_call.o
member_without_call.cpp:6:23: error: reference to non-static member function must be called; did you mean to call it with no arguments?
6 | std::cout << name.size << '\n';
| ~~~~~^~~~
| ()
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c member_without_call.cpp -o member_without_call.o
member_without_call.cpp: In function 'int main()':
member_without_call.cpp:6:15: error: invalid use of non-static member function 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; size_type = long unsigned int]'
6 | std::cout << name.size << '\n';
| ~~~~~~~~~~^~~~~~~~~~~~
In file included from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/string:58,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/bits/locale_classes.h:43,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/bits/ios_base.h:43,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/ios:46,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/bits/ostream.h:43,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/ostream:42,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/iostream:43,
from member_without_call.cpp:1:
/opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/bits/basic_string.h:1187:7: note: declared here
1187 | size() const _GLIBCXX_NOEXCEPT
| ^~~~
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 calls_session.py
- A string where a number is expected.
int overs = "20";gavecannot initialize a variable of type 'int' with an lvalue of type 'const char[3]'from Clang andinvalid conversion from 'const char*' to 'int' [-fpermissive]from GCC."20"is text; write20. The[-fpermissive]tag only says which flag would turn this error into a warning. Never use that flag to make an error go away. - The wrong number of arguments. Clang said
no matching function for call to 'area'and then, in a note,candidate function not viable: requires 2 arguments, but 1 was provided. GCC saidtoo few arguments to function 'int area(int, int)'and pointed to the declaration. With overloaded functions the notes list every candidate and why each failed, so read them all. - A member function without its parentheses.
name.sizeinstead ofname.size()gave Clang’sreference to non-static member function must be called; did you mean to call it with no arguments?, with a fix-it adding(). GCC’s message,invalid use of non-static member function, ran to a full line of template parameters and eight lines ofIn file included from. Skip that noise and keep the words that matter: an invalid use ofsize().
main must return int
#include <iostream>
void main() {
std::cout << "Hello\n";
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -c void_main.cpp -o void_main.o
g++-16 -std=c++23 -Wall -Wextra -c void_main.cpp -o void_main.o
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c void_main.cpp -o void_main.o
void_main.cpp:3:1: error: 'main' must return 'int'
3 | void main() {
| ^~~~
| int
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c void_main.cpp -o void_main.o
void_main.cpp:3:1: error: '::main' must return 'int'
3 | void main() {
| ^~~~
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 void_main_session.py
Both compilers rejected it: 'main' must return 'int' (Clang, with a fix-it replacing void by int) and
'::main' must return 'int' (GCC). The standard requires main to have the return type int. You do not have to
write return 0; at its end: reaching the end of main returns 0.
All ten at a glance
| Mistake | Clang 21 says | GCC 16 says |
|---|---|---|
Missing ; |
expected ';' at end of declaration |
expected ',' or ';' before 'std' (on the next line) |
Missing } |
expected '}' |
expected '}' at end of input |
| Curly quotes | unexpected character <U+201C> |
extended character “ is not valid in an identifier |
cout without std:: |
use of undeclared identifier 'cout'; did you mean 'std::cout'? |
'cout' was not declared in this scope; did you mean 'std::cout'? |
| Function used before it is declared | use of undeclared identifier 'area' |
'area' was not declared in this scope |
Missing #include <vector> |
no member named 'vector' in namespace 'std' |
'vector' is not a member of 'std', with a note naming <vector> |
Text assigned to an int |
cannot initialize a variable of type 'int' with an lvalue of type 'const char[3]' |
invalid conversion from 'const char*' to 'int' |
| Wrong number of arguments | no matching function for call to 'area' |
too few arguments to function 'int area(int, int)' |
name.size without () |
reference to non-static member function must be called |
invalid use of non-static member function |
void main() |
'main' must return 'int' |
'::main' must return 'int' |
Messages that point the wrong way
Suggestions and messages are the compiler’s best guess, and sometimes the guess is wrong.
This program includes <iostream> but not <vector>:
#include <iostream>
int main() {
std::vector<int> runs{4, 6, 1};
std::cout << runs.size() << '\n';
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -c vector_via_iostream.cpp -o vector_via_iostream.o
g++-16 -std=c++23 -Wall -Wextra -c vector_via_iostream.cpp -o vector_via_iostream.o
""") Output
$ clang++ -std=c++23 -Wall -Wextra -c vector_via_iostream.cpp -o vector_via_iostream.o
vector_via_iostream.cpp:4:22: error: implicit instantiation of undefined template 'std::vector<int>'
4 | std::vector<int> runs{4, 6, 1};
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__fwd/vector.h:22:7: note: template is declared here
22 | class vector;
| ^
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -Wall -Wextra -c vector_via_iostream.cpp -o vector_via_iostream.o
vector_via_iostream.cpp: In function 'int main()':
vector_via_iostream.cpp:4:20: error: wrong number of template arguments (1, should be 2)
4 | std::vector<int> runs{4, 6, 1};
| ^
In file included from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/ostream:45,
from /opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/iostream:43,
from vector_via_iostream.cpp:1:
/opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/format:3195:36: note: provided for 'template<class, class> class std::vector'
3195 | template<typename, typename> class vector;
| ^~~~~~
vector_via_iostream.cpp:4:22: error: scalar object 'runs' requires one element in initializer
4 | std::vector<int> runs{4, 6, 1};
| ^~~~
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 iostream_vector_session.py
With <iostream> included, neither compiler suggested #include <vector>. Clang said
implicit instantiation of undefined template 'std::vector<int>' and GCC said
wrong number of template arguments (1, should be 2), because each library’s <iostream> happens to declare
std::vector without defining it. The messages describe a symptom, not the cause. When a standard type behaves
strangely right after you start using it, check its #include first.
The old program later in this lesson gets another wrong guess: for an unknown cin, Clang suggested did you mean 'sin'?, the sine function, and GCC suggested getc for getch. A “did you mean” points at a name that is spelt
alike, which is not always the name you meant.
Long template errors
Errors inside templates are long because the compiler shows how it got there. std::sort needs iterators that can
jump to any position, which a std::list does not have:
#include <algorithm>
#include <list>
int main() {
std::list<int> scores{72, 45, 90};
std::sort(scores.begin(), scores.end());
} from session import run
# The whole error is long, so each command asks a question of it: how many lines, how many errors, which lines name
# this file, and what the first error says.
run("""
clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | wc -l
clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -c "error:"
clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep "sort_list.cpp:"
clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -m 1 "error:"
g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | wc -l
g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -c "error:"
g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep "sort_list.cpp:"
g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -m 1 "error:"
""") Output
$ clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | wc -l
114
$ clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -c "error:"
4
$ clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep "sort_list.cpp:"
In file included from sort_list.cpp:1:
sort_list.cpp:6:10: note: in instantiation of function template specialization 'std::sort<std::__list_iterator<int, void *>>' requested here
In file included from sort_list.cpp:1:
sort_list.cpp:6:10: note: in instantiation of function template specialization 'std::sort<std::__list_iterator<int, void *>>' requested here
In file included from sort_list.cpp:1:
sort_list.cpp:6:10: note: in instantiation of function template specialization 'std::sort<std::__list_iterator<int, void *>>' requested here
In file included from sort_list.cpp:1:
sort_list.cpp:6:10: note: in instantiation of function template specialization 'std::sort<std::__list_iterator<int, void *>>' requested here
$ clang++ -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -m 1 "error:"
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/make_heap.h:37:31: error: invalid operands to binary expression ('std::__list_iterator<int, void *>' and 'std::__list_iterator<int, void *>')
$ g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | wc -l
33
$ g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -c "error:"
1
$ g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep "sort_list.cpp:"
from sort_list.cpp:1:
sort_list.cpp:6:14: required from here
$ g++-16 -std=c++23 -c sort_list.cpp -o sort_list.o 2>&1 | grep -m 1 "error:"
/opt/homebrew/Cellar/gcc/16.2.0/include/c++/16/bits/stl_algo.h:1914:50: error: no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>')
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sort_list_session.py
Rather than print it all, the session asks the output four questions with wc and grep. Clang 21 printed 114
lines with 4 errors, all inside <algorithm>, and each error has a note on this file:
in instantiation of function template specialization 'std::sort<std::__list_iterator<int, void *>>' requested here.
GCC 16 printed 33 lines with 1 error, no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>'), preceded by required from here lines. To read such an error:
- Find your own file in it. Both compilers name your line in the chain: GCC with
sort_list.cpp:6:14: required from here, Clang with a note onsort_list.cpp:6:10. That is the call to look at. - Read the first
error:line for the kind of failure. Clang’sinvalid operands to binary expressionand GCC’sno match for 'operator-'both say that subtracting two list iterators fails:std::sortwants iterators that can be subtracted, and list iterators cannot. - Skip the candidates (
reverse_iterator,move_iterator) unless the first two steps did not explain it.
The fix is scores.sort();, the list’s own member function, or a std::vector instead of a list.
Version note
New in GCC 16: C++ errors such as this one are printed as a tree, with indentation and bullet points (•) under the
error. -fno-diagnostics-show-nesting or -fdiagnostics-plain-output restores the flat layout of earlier releases.
Constrained algorithms from C++20 give much shorter errors. With std::ranges::sort(scores); instead, Clang printed
22 lines whose notes give the reason itself: because 'std::list<int> &' does not satisfy 'random_access_range'.
GCC’s version came to 51 lines, with required for the satisfaction of 'random_access_range<_Range>' in its tree.
#include <algorithm>
#include <list>
int main() {
std::list<int> scores{72, 45, 90};
std::ranges::sort(scores);
} from session import run
run("""
clang++ -std=c++23 -c sort_list_ranges.cpp -o sort_list_ranges.o
g++-16 -std=c++23 -c sort_list_ranges.cpp -o sort_list_ranges.o 2>&1 | wc -l
""") Output
$ clang++ -std=c++23 -c sort_list_ranges.cpp -o sort_list_ranges.o
sort_list_ranges.cpp:6:5: error: no matching function for call to object of type 'const __sort'
6 | std::ranges::sort(scores);
| ^~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/ranges_sort.h:64:3: note: candidate template ignored: constraints not satisfied [with _Range = std::list<int> &, _Comp = ranges::less, _Proj = identity]
64 | operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/ranges_sort.h:61:13: note: because 'std::list<int> &' does not satisfy 'random_access_range'
61 | template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity>
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__ranges/concepts.h:116:59: note: because 'iterator_t<std::list<int, std::allocator<int>> &>' (aka '__list_iterator<int, void *>') does not satisfy 'random_access_iterator'
116 | concept random_access_range = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__iterator/concepts.h:219:36: note: because 'derived_from<_ITER_CONCEPT<std::__list_iterator<int, void *>>, random_access_iterator_tag>' evaluated to false
219 | bidirectional_iterator<_Ip> && derived_from<_ITER_CONCEPT<_Ip>, random_access_iterator_tag> &&
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__concepts/derived_from.h:27:24: note: because 'is_base_of_v<std::random_access_iterator_tag, std::bidirectional_iterator_tag>' evaluated to false
27 | concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<const volatile _Dp*, const volatile _Bp*>;
| ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__algorithm/ranges_sort.h:57:3: note: candidate function template not viable: requires at least 2 arguments, but 1 was provided
57 | operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -c sort_list_ranges.cpp -o sort_list_ranges.o 2>&1 | wc -l
51
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 ranges_session.py
Old code from textbooks
Many older books and lab manuals show programs like this one:
As printed · old_textbook.cpp
#include <iostream.h>
#include <conio.h>
void main() {
clrscr();
int a, b;
cout << "Enter two numbers: ";
cin >> a >> b;
cout << "Sum = " << a + b;
getch();
} Headers fixed · old_textbook_step2.cpp
#include <iostream>
void main() {
clrscr();
int a, b;
cout << "Enter two numbers: ";
cin >> a >> b;
cout << "Sum = " << a + b;
getch();
} from session import run
# The book's version stops at the first line. With the headers fixed, grep lists every error that is left.
run("""
clang++ -std=c++23 -c old_textbook.cpp -o old_textbook.o
g++-16 -std=c++23 -c old_textbook.cpp -o old_textbook.o
clang++ -std=c++23 -c old_textbook_step2.cpp -o old_textbook_step2.o 2>&1 | grep "error:"
g++-16 -std=c++23 -c old_textbook_step2.cpp -o old_textbook_step2.o 2>&1 | grep "error:"
""") Output
$ clang++ -std=c++23 -c old_textbook.cpp -o old_textbook.o
old_textbook.cpp:1:10: fatal error: 'iostream.h' file not found
1 | #include <iostream.h>
| ^~~~~~~~~~~~
1 error generated.
[exit status 1]
$ g++-16 -std=c++23 -c old_textbook.cpp -o old_textbook.o
old_textbook.cpp:1:10: fatal error: iostream.h: No such file or directory
1 | #include <iostream.h>
| ^~~~~~~~~~~~
compilation terminated.
[exit status 1]
$ clang++ -std=c++23 -c old_textbook_step2.cpp -o old_textbook_step2.o 2>&1 | grep "error:"
old_textbook_step2.cpp:3:1: error: 'main' must return 'int'
old_textbook_step2.cpp:4:5: error: use of undeclared identifier 'clrscr'
old_textbook_step2.cpp:6:5: error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
old_textbook_step2.cpp:7:5: error: use of undeclared identifier 'cin'; did you mean 'sin'?
old_textbook_step2.cpp:7:5: error: reference to overloaded function could not be resolved; did you mean to call it?
old_textbook_step2.cpp:8:5: error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
old_textbook_step2.cpp:9:5: error: use of undeclared identifier 'getch'
$ g++-16 -std=c++23 -c old_textbook_step2.cpp -o old_textbook_step2.o 2>&1 | grep "error:"
old_textbook_step2.cpp:3:1: error: '::main' must return 'int'
old_textbook_step2.cpp:4:5: error: 'clrscr' was not declared in this scope
old_textbook_step2.cpp:6:5: error: 'cout' was not declared in this scope; did you mean 'std::cout'?
old_textbook_step2.cpp:7:5: error: 'cin' was not declared in this scope; did you mean 'std::cin'?
old_textbook_step2.cpp:9:5: error: 'getch' was not declared in this scope; did you mean 'getc'?
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 old_code_session.py
Both compilers stopped at line 1 with a fatal error, which ends the compilation at once:
'iostream.h' file not found (Clang) and iostream.h: No such file or directory followed by
compilation terminated. (GCC). Fixing the headers only uncovers the next layer: with <iostream> in place and
<conio.h> removed, Clang printed seven errors and GCC five, for void main, clrscr, getch, and cout and cin
without std::. None of these features belongs to standard C++:
| Old code | Why it fails | Modern C++ |
|---|---|---|
#include <iostream.h> |
Not a standard header; the standard’s name is <iostream> |
#include <iostream> |
#include <conio.h>, clrscr(), getch() |
Not in standard C or C++; Microsoft’s runtime still has a <conio.h> with _getch(), but the usual Linux and macOS toolchains have no such header |
Leave the screen alone; to pause, std::cin.get() waits for Enter |
void main() |
main must return int |
int main() |
cout, cin without std:: |
Standard names live in namespace std |
std::cout, std::cin |
int a, b; read without a check |
Bad input leaves the values unchanged or 0 | if (!(std::cin >> a >> b)) |
The rewrite compiles without a warning under -Wall -Wextra -Wpedantic on both compilers:
#include <iostream>
int main() {
int a = 0;
int b = 0;
std::cout << "Enter two numbers: ";
if (!(std::cin >> a >> b)) {
std::cerr << "Please type two whole numbers.\n";
return 1;
}
std::cout << "Sum = " << a + b << '\n';
} from session import run
run("""
clang++ -std=c++23 -Wall -Wextra -Wpedantic old_textbook_modern.cpp -o old_textbook_modern && echo "3 4" | ./old_textbook_modern
g++-16 -std=c++23 -Wall -Wextra -Wpedantic old_textbook_modern.cpp -o old_textbook_modern && echo "3 4" | ./old_textbook_modern
""") Output
$ clang++ -std=c++23 -Wall -Wextra -Wpedantic old_textbook_modern.cpp -o old_textbook_modern && echo "3 4" | ./old_textbook_modern Enter two numbers: Sum = 7 $ g++-16 -std=c++23 -Wall -Wextra -Wpedantic old_textbook_modern.cpp -o old_textbook_modern && echo "3 4" | ./old_textbook_modern Enter two numbers: Sum = 7
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 modern_session.py
With 3 4 on standard input it printed Enter two numbers: Sum = 7 with both compilers.
College labs
If your lab or textbook uses Turbo C++, or programs written for it, expect exactly these lines: iostream.h,
conio.h, clrscr(), getch() and void main(). For lab records and exams, write what the syllabus asks for; for
everything else, including placement tests and online judges, write the standard version shown here, which every
current compiler accepts.
A routine for any error
- Compile again with only the first error showing (
-fmax-errors=1or-ferror-limit=1). - Go to the file, line and column, and also read the line above it.
- Read the message word by word, then every
note:under it. In a template error, find your own file first. - Look for a fix-it line, but check that it is what you meant.
- If the message still makes no sense, try the other compiler: Clang and GCC often explain the same mistake in different words. Search for the message with your own names and file paths taken out.
Practice: fix three broken programs
Make each of these compile with -std=c++23 -Wall -Wextra -Werror on your compiler, fixing the cause each time
rather than hiding the message: missing_semicolon.cpp (it should print 92), wrong_arguments.cpp (make it print the
area of a 3 by 4 rectangle, 12) and use_before_declare.cpp (it should print 12). Then take old_textbook.cpp
and rewrite it without looking at the version above.
Check yourself
Check yourself
5 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
Interview questions
When a build prints twenty errors, why do you fix the first one first? (warm-up)
Because the later errors are often consequences of the first. A compiler that meets a mistake tries to carry on, so a
missing #include makes a name unknown, every declaration that uses the name fails, and every use of those
declarations fails again. In this lesson one missing <vector> gave Clang four errors and GCC three, and a single
missing semicolon gave GCC a knock-on warning about an unused variable. Fixing the first error and compiling again
removes most of the cascade, and what remains is real. The first error is also the one whose location is most
trustworthy, although even it can point one line after the mistake, as a missing semicolon does with GCC.
Key takeaways
- A diagnostic tells you where (
file:line:column), how serious (error,warning,note), what, and often how to fix it; read the notes under it too. - Fix the first error and compile again: one missing
#includeproduced four errors with Clang. - The reported line can be after the mistake: a missing
;shows on the next line in GCC, and a missing}at the end of the file. - “Did you mean” is a guess (Clang offered
sinforcin), and a missing header can produce an unrelated-looking error; GCC compiledstd::sortwithout<algorithm>where Clang did not. - In long template errors, find your own file’s line, then read the first
error:; constrainedstd::rangesalgorithms say which requirement failed. GCC 16 shows such errors as a tree. iostream.h,conio.h,clrscr(),getch()andvoid main()are not standard C++; write<iostream>,std::names andint main().
References
- Clang Compiler User's Manual (LLVM Project)
- Options to Request or Suppress Warnings (GCC manual) (GNU Project)
- GCC 16 Release Series, Changes, New Features, and Fixes (GNU Project)
- Working Draft, Programming Languages: C++ (N4950) (ISO/IEC JTC1/SC22/WG21)
- _getch, _getwch (C runtime library reference) (Microsoft)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress