Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

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.

  • Beginner
  • 20 minutes
  • Examples run with Clang 21.0.0, GCC 16.2.0 and Python 3.14.8
  • By MySmartCoPilot
Free: 20 minutes

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

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:::

undeclared_cout.cpp C++ · undeclared_cout.cpp
#include <iostream>

int main() {
    cout << "Namaste\n";
}
The same mistake, as GCC 16 and Clang 21 report it Python · cout_session.py
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:

  1. undeclared_cout.cpp: In function 'int main()': names the function the problem is in. Clang leaves this line out.
  2. undeclared_cout.cpp:4:5: is the file, the line and the column. Most editors jump there when you click it.
  3. error: is the severity. An error stops the build, a warning does not, and a note adds information to the message above it.
  4. 'cout' was not declared in this scope; did you mean 'std::cout'? is the message itself, here with a guess.
  5. 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.

The six parts of a compiler error, top to bottom: location, severity, message, suggestion, source line with fix-it, and note.1. Whereundeclared_cout.cpp:4:5file : line : column2. How seriouserror stops the build,warning does not3. What went wrong'cout' was not declaredin this scope4. A guessdid you mean'std::cout'?5. The source line^~~~ under the spot,then the fix-it: std::cout6. note:'std::cout' declared here(in <iostream>)

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.

  1. Where: undeclared_cout.cpp:4:5, the file, the line and the column.
  2. How serious: error, which stops the build, or warning, which does not.
  3. What went wrong: 'cout' was not declared in this scope.
  4. A guess: did you mean 'std::cout'?
  5. The source line, with ^~~~ under the spot and a fix-it line that shows std::cout.
  6. 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>:

missing_vector.cpp C++ · missing_vector.cpp
#include <cstdio>

int main() {
    std::vector<int> runs{4, 6, 1};
    std::printf("%zu\n", runs.size());
}
Four errors from one missing line Python · vector_session.py
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:

Two mistakes at the end of a line

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";
}
Where the compilers report them Python · lines_session.py
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:

Characters copied into code

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';
}
What the compilers make of them Python · copied_session.py
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.

Unicode Character Inspector Paste a line the compiler rejects to see every character's code point, including curly quotes and non-breaking spaces.

Names the compiler cannot find

Two ways to make a name unknown

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';
}
One error on both, one error on Clang only Python · names_session.py
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

Values and calls that do not fit

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';
}
Three mistakes, two compilers Python · calls_session.py
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"; gave cannot initialize a variable of type 'int' with an lvalue of type 'const char[3]' from Clang and invalid conversion from 'const char*' to 'int' [-fpermissive] from GCC. "20" is text; write 20. 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 said too 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.size instead of name.size() gave Clang’s reference 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 of In file included from. Skip that noise and keep the words that matter: an invalid use of size().

main must return int

void main() C++ · void_main.cpp
#include <iostream>

void main() {
    std::cout << "Hello\n";
}
Both compilers reject it Python · void_main_session.py
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>:

No <vector>, but <iostream> C++ · vector_via_iostream.cpp
#include <iostream>

int main() {
    std::vector<int> runs{4, 6, 1};
    std::cout << runs.size() << '\n';
}
Two unhelpful errors Python · iostream_vector_session.py
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:

Sorting a std::list C++ · sort_list.cpp
#include <algorithm>
#include <list>

int main() {
    std::list<int> scores{72, 45, 90};
    std::sort(scores.begin(), scores.end());
}
Questions asked of a long error Python · sort_list_session.py
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:

  1. 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 on sort_list.cpp:6:10. That is the call to look at.
  2. Read the first error: line for the kind of failure. Clang’s invalid operands to binary expression and GCC’s no match for 'operator-' both say that subtracting two list iterators fails: std::sort wants iterators that can be subtracted, and list iterators cannot.
  3. 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.

The same mistake with std::ranges::sort C++ · sort_list_ranges.cpp
#include <algorithm>
#include <list>

int main() {
    std::list<int> scores{72, 45, 90};
    std::ranges::sort(scores);
}
A constrained algorithm explains itself Python · ranges_session.py
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:

A program written for a pre-standard compiler

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();
}
One layer of errors at a time Python · old_code_session.py
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:

The same program in standard C++ C++ · old_textbook_modern.cpp
#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';
}
Built with every warning, given 3 and 4 Python · modern_session.py
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

  1. Compile again with only the first error showing (-fmax-errors=1 or -ferror-limit=1).
  2. Go to the file, line and column, and also read the line above it.
  3. Read the message word by word, then every note: under it. In a template error, find your own file first.
  4. Look for a fix-it line, but check that it is what you meant.
  5. 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.

  1. Question 1 of 5 Clang reports four errors for a program that uses std::vector without #include <vector>. What do you do first?

    Choose one answer.

    Show the answer to question 1

    Answer: Fix the first error, by adding the include, and compile again

    Only the first error is the mistake. The other three ("use of undeclared identifier 'runs'" and the like) follow from it, so they disappear once <vector> is included. -fpermissive never fixes a missing header.

  2. Question 2 of 5 GCC reports "expected ',' or ';' before 'std'" on line 5, and line 5 looks correct. Where is the mistake most likely to be?

    Choose one answer.

    Show the answer to question 2

    Answer: At the end of line 4, which is missing its semicolon

    GCC only knew that the declaration on line 4 had not ended when it met the next word, std, on line 5. Clang reported the same mistake on line 4 itself, with a fix-it showing the missing ;.

  3. Question 3 of 5 For an unknown name cin, Clang 21 asked "did you mean 'sin'?". What is the right fix?

    Choose one answer.

    Show the answer to question 3

    Answer: Write std::cin, because cin is in namespace std

    A "did you mean" suggestion is only a name that is spelt alike, here the sine function. The program meant the standard input stream, std::cin from <iostream>.

  4. Question 4 of 5 A call to std::sort produces 114 lines of errors inside <algorithm>. What should you look for first?

    Choose one answer.

    Show the answer to question 4

    Answer: The line in your own file, named by "required from here" (GCC) or "in instantiation of ... requested here" (Clang)

    Template errors show the chain of instantiations that led to the failure. Your own call is in that chain, and the first error line then says what the call's arguments lacked: list iterators cannot be subtracted.

  5. Question 5 of 5 Which of these lines are not standard C++? Choose every one.

    Choose every answer that is right.

    Show the answer to question 5

    Answer:

    • void main()
    • #include <iostream.h>
    • clrscr();

    <iostream.h> is not one of the headers the standard lists, main must return int, and clrscr() is not declared by any standard header. <iostream> and int main() are standard, and every current compiler accepts them.

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 #include produced 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 sin for cin), and a missing header can produce an unrelated-looking error; GCC compiled std::sort without <algorithm> where Clang did not.
  • In long template errors, find your own file’s line, then read the first error:; constrained std::ranges algorithms say which requirement failed. GCC 16 shows such errors as a tree.
  • iostream.h, conio.h, clrscr(), getch() and void main() are not standard C++; write <iostream>, std:: names and int main().

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.