Learn C++ STL

Lesson 7 of 9 · From C to Just-Enough C++

Module 1 · From C to Just-Enough C++

std::, Namespaces and the Headers You Will Actually Include

FreeReading

In this lesson

  • Explain what a namespace is, write two of your own, and reach a name inside one with ::.
  • Choose between std::, a using-declaration and using namespace std;, and say why the last one never goes in a header.
  • Name the header for every standard name this track uses, and say why <bits/stdc++.h> works only on GCC.

Bob's contest program starts with #include <bits/stdc++.h>, and on the Playground it compiles and passes. Maria copies it to her Mac, whose compiler is clang with its own library, and it stops at the first line: fatal error: 'bits/stdc++.h' file not found. Nothing in the program is wrong, and still one compiler takes it and another refuses. To see why, you need two ideas: where a standard name lives, and which file brings it into your program. This lesson gives you both, and a table to keep.

A namespace is a named box of names

In C every function name is global, so two libraries cannot both have a sort. C libraries dodge this with a prefix on every name, such as sqlite3_open. C++ has a better tool. A namespace is a named box of names: two boxes can each hold a sort, and they never clash.

Making a namespace, and reaching into it

namespace box_name {
    declarations: functions, variables, constants
}

box_name::name
  • namespace opens a box; box_name is the box's own name.
  • Everything declared between the braces lives inside the box.
  • ::, the scope operator, looks inside a box: box_name::name means "the name in that box".

Here are two functions called sort in one program, one in a shop's box and one in a school's.

#include <iostream>

namespace shop {
void sort()
{
    std::cout << "shop::sort puts prices cheapest first\n";
}
}

namespace school {
void sort()
{
    std::cout << "school::sort puts marks highest first\n";
}
}

int main()
{
    shop::sort();
    school::sort();
    return 0;
}
shop::sort puts prices cheapest first
school::sort puts marks highest first

The compiler never asks which sort you mean, because each call names its box. main itself lives in no box you made. It sits in the global namespace, the outermost box of every program, where all of C's names live too.

Namespaces as boxes of names the global namespace: main() and your other top-level names namespace shop void sort() call it: shop::sort() namespace school void sort() call it: school::sort() namespace std cout cin string sort max count left vector ... call it: std::sort() three boxes, three sorts, no clash: each call names its box using namespace std; lets every name in std be found without std::

So a namespace lets two pieces of code use the same name, and box::name says which one you mean.

std:: and three ways not to type it

The C++ standard library keeps every one of its names in one namespace, std. That is why lesson 01 wrote std::cout: the cout in the std box. Typing std:: fifty times a program is tiring, so C++ has three ways to skip it.

A using-declaration lets one name in: using std::cout;. A using-directive lets the whole box in: using namespace std;. Each one works from the line it is written on to the end of the block that holds it. Written at the top of the file, that is the rest of the file; written inside a function, it is that function only.

#include <iostream>
#include <string>

using std::cout;

int main()
{
    using std::cin;

    std::string title;
    int pages = 0;
    cin >> title >> pages;
    cout << title << " has " << pages << " pages\n";
    return 0;
}
Matilda has 240 pages

That output is for the input Matilda 240. cout needs no std:: anywhere below its using-declaration, and cin needs none inside main. std::string was never let in, so it keeps its std::.

You writeWhereWhat you can then write without std::
std::coutat every usenothing; you name the box each time
using std::cout;top of the filecout, for the rest of the file
using std::cin;inside a functioncin, inside that function only
using namespace std;top of the fileevery name in std, for the rest of the file

So cout after any of these is still std::cout. What changes is how many names you let out of the box, and how far.

What using namespace std costs, and the one rule

Lesson 01 said that using namespace std; pours hundreds of names into your program, and that one of yours can collide with one of them. Here is the collision. Kenji counts the laps he has left in a global variable named left.

#include <iostream>

using namespace std;

int left = 3;

int main()
{
    cout << left << " laps left\n";
    return 0;
}

GCC 12 refuses it at the Playground's command line and at -Wall -Wextra alike: error: reference to 'left' is ambiguous. The notes name the two candidates, Kenji's 'int left' and 'std::ios_base& std::left(ios_base&)'. std::left is a real name from <iostream>, a setting that lines output up on the left. Kenji never asked for it; the using-directive let it out, and now there are two global lefts.

Move the variable inside main, and the same program compiles and prints 3 laps left. A name declared inside a function hides the ones outside it, the box's included. So the clash bites names at the top of a file, which is where contest programs keep their big arrays and counters.

That is the cost in a single file. In a header, a file that other files include, the cost spreads. #include pastes the header's text into the file that includes it, as in C. So a using-directive inside a header lands in every one of those files. Their authors never wrote it, and their names start colliding.

So this track has one rule, and one habit. The rule: using namespace std; never goes in a header. The habit: a short one-file contest program may use it, but this module, and every project lesson in the track, writes std:: on every standard name.

The header table: which file brings which name

A namespace says what a name is called. A header says where it is declared, and you must #include it before the name exists in your program. Every name in this track comes from one of the headers below. The table is worth keeping open beside your first STL programs.

HeaderWhat it gives youTaught in
<iostream>std::cin, std::cout, std::cerrlessons 01 and 02
<string>std::string, std::getline, std::to_stringModule 3
<sstream>std::istringstream, reading numbers out of a stringpointed at in lesson 02, Module 3
<utility>std::pair, std::swap, std::movelessons 05 and 06
<tuple>std::tuple, std::get, std::tielesson 06
<vector>std::vectorModule 2
<array>std::arrayModule 4
<deque>std::dequeModule 4
<list>std::listModule 5
<forward_list>std::forward_listModule 5
<stack>std::stackModule 6
<queue>std::queue, and also std::priority_queueModule 6, Module 7
<set>std::set, std::multisetModule 8
<map>std::map, std::multimapModule 9
<unordered_set>std::unordered_setModule 10
<unordered_map>std::unordered_mapModule 10
<iterator>std::next, std::prev, std::distanceModule 11
<functional>std::greater, the "larger first" orderModule 7, Module 12
<algorithm>std::sort, std::max, std::min, std::reverse, std::count, std::lower_boundlesson 05, Module 12, Module 13
<numeric>std::accumulate, std::iota, std::gcdModule 14
<bitset>std::bitsetModule 15
<chrono>clocks for timing a programused in lessons 02 to 04 to measure

Two rows surprise people. std::priority_queue has no header of its own; it lives in <queue>. And std::swap is in <utility>, while its neighbours std::max and std::min are in <algorithm>. So when GCC says a name is not a member of 'std', look its header up here first.

Include exactly what you use

Here is a fact found while writing lesson 05. This program has no <algorithm>, and GCC 12 compiles it anyway.

#include <iostream>

int main()
{
    std::cout << std::max(3, 7) << '\n';
    return 0;
}
7

It works by luck. GCC's library, libstdc++, builds <iostream> out of other headers. A few files down that chain it includes <string>, and <string> includes bits/stl_algobase.h, the file where std::max is defined. Compiler Explorer's include list (GCC's -H option) shows every step of it.

Other compilers come with other libraries, built in other ways. On Compiler Explorer we compiled three one-header programs, each including only <iostream>, on three toolchains.

With only <iostream>, a call toGCC 12, libstdc++clang 15, libc++MSVC, Microsoft's library
std::maxcompilescompilescompiles
std::getlinecompilescompileserror C2039: 'getline': is not a member of 'std'
std::sorterror: 'sort' is not a member of 'std'; did you mean 'qsort'?compileserror C2039: 'sort': is not a member of 'std'

The GCC column is the Playground's command line, -O2 -std=c++17. The clang column is clang 15 with -stdlib=libc++, its own library, and the MSVC column is "x64 msvc v19.latest" with /std:c++17. Each library drags in a different set of extras, and none of them promises to keep doing it. So a program that leans on an extra is right on one machine and broken on the next.

The fix costs one line per header. Include every header whose names you use, even when the program compiles without it. Then it compiles on any standard library, today and after the next library update. So the safe answer is never "it compiled on mine", but "every name I use has its header at the top".

bits/stdc++.h: every header at once, on GCC only

<bits/stdc++.h> is a file inside GCC's library that includes every standard header in one go. Its own comment calls it "an implementation file for a precompiled header", a helper for GCC's build speed. It is not part of the C++ standard. Contest programmers love it, because one line replaces a dozen, and the Playground and many contest judges compile with GCC.

#include <bits/stdc++.h>

int main()
{
    std::cout << "hello\n";
    return 0;
}
hello

That is GCC 12's output. Other toolchains do not have the file at all. On Compiler Explorer, clang 15 with libc++, the library a Mac uses by default, stops at line 1: fatal error: 'bits/stdc++.h' file not found. MSVC stops there too: fatal error C1083: Cannot open include file: 'bits/stdc++.h': No such file or directory. That is Bob and Maria's story from the top of this lesson.

It also costs compile time, because the compiler reads every header, used or not. We built the hello program twice, once with <iostream> and once with <bits/stdc++.h>, one run each.

Where, and the commandWith <iostream>With <bits/stdc++.h>
This lesson's machine, GCC 14.2 (MinGW), g++ -std=c++17, wall-clock time1.39 s4.76 s
Compiler Explorer, GCC 12.2, -O2 -std=c++17, its reported build time376 ms1130 ms
Compiler Explorer, GCC 12.2, lines after the preprocessor (-E -P)22,38292,295

On both machines the one line made a five-line program build at least three times slower. Three later runs on Compiler Explorer gave 289 to 378 ms against 1,863 to 2,888 ms. The local runs came after one warm-up build of each, so the disk was not the difference. In a contest that is a cost you can afford; in a project with hundreds of files, every file pays it.

So the track's rule is simple. <bits/stdc++.h> is allowed in a contest program, and we name it as GCC-only every time it appears. It never appears in a project lesson, because a project must build on every compiler its team uses.

Example 1: the same name in two boxes

A namespace can hold variables too. Alice tracks stock for a bookshop and a library, and both counts are called stock.

#include <iostream>

namespace bookshop {
int stock = 0;
}

namespace library {
int stock = 0;
}

int main()
{
    bookshop::stock = 12;
    library::stock = 340;
    bookshop::stock = bookshop::stock - 2;

    std::cout << "bookshop " << bookshop::stock << ", library " << library::stock << '\n';
    return 0;
}
bookshop 10, library 340

Selling two books changed only the bookshop's count. In C the two would need different names, such as bookshop_stock and library_stock; here the box does that job.

Run in Compiler
Example 2: three sorts in one program

Now the shop's and the school's sort do real work, and both are built on a third one, std::sort. It sorts a range of an array into increasing order, and Module 12 teaches it. std::reverse turns a range round.

#include <algorithm>
#include <iostream>

namespace shop {
// Prices go cheapest first.
void sort(int prices[], int n)
{
    std::sort(prices, prices + n);
}
}

namespace school {
// Marks go highest first.
void sort(int marks[], int n)
{
    std::sort(marks, marks + n);
    std::reverse(marks, marks + n);
}
}

void print(const int a[], int n)
{
    for (int i = 0; i < n; i++) {
        if (i > 0) {
            std::cout << ' ';
        }
        std::cout << a[i];
    }
    std::cout << '\n';
}

int main()
{
    int prices[4] = {300, 120, 450, 200};
    int marks[4] = {72, 91, 65, 85};

    shop::sort(prices, 4);
    school::sort(marks, 4);
    print(prices, 4);
    print(marks, 4);
    return 0;
}
120 200 300 450
91 85 72 65

Look inside shop::sort. A plain sort(prices, prices + n) there finds shop::sort itself, the closest box. GCC 12 then says error: invalid conversion from 'int*' to 'int' [-fpermissive], with a note naming void shop::sort(int*, int). std:: is what sends the call to the standard library.

Run in Compiler
Example 3: Amara's price list, every header earning its place

Amara reads her shop's name and n prices, and prints the count, the total, and the cheapest and dearest price. This is the program a beginner really writes, with exactly the headers it uses.

#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>

const int MAX_N = 100;

int main()
{
    std::string shop;
    int n = 0;
    std::cin >> shop >> n;
    if (n == 0) {
        std::cout << shop << ": no items\n";
        return 0;
    }

    int prices[MAX_N] = {0};
    for (int i = 0; i < n; i++) {
        std::cin >> prices[i];
    }

    std::sort(prices, prices + n);
    long long total = std::accumulate(prices, prices + n, 0LL);

    std::cout << shop << ": " << n << " items, total " << total << '\n';
    std::cout << "cheapest " << prices[0] << ", dearest " << prices[n - 1] << '\n';
    return 0;
}
Bookworm: 4 items, total 1070
cheapest 120, dearest 450

That output is for the input Bookworm 4, then 300 120 450 200. Each header pays for itself: <algorithm> for std::sort, <iostream> for std::cin and std::cout, <numeric> for std::accumulate and <string> for std::string. std::accumulate adds up a range starting from 0LL, so the total is a long long (Module 14).

Zara tried Bookworm 0 first. Without the n == 0 check, prices[n - 1] would read prices[-1], outside the array; with it, the program prints Bookworm: no items.

Run in Compiler

Where this is used

  • SQLite. Its C interface has no namespaces to use, so every public name starts with sqlite3_, as in sqlite3_open and sqlite3_exec. A prefix is C's stand-in for a box.
  • LLVM. The LLVM Coding Standards have a rule titled "Do Not Use 'using namespace std'". They prefer an explicit std::, and say a using-directive in a header pollutes every file that includes it.
  • Chromium. Google's browser follows the Google C++ Style Guide, which says not to use using-directives such as using namespace foo.
  • GCC's own library. bits/stdc++.h ships with libstdc++, and its comment describes it as an implementation file for a precompiled header. That is why it exists on GCC and on judges that use GCC, and nowhere else.

Common mistakes

1. Leaving out std:: with no using line.

cout << "hello\n";

An error at every command line: error: 'cout' was not declared in this scope; did you mean 'std::cout'?. GCC even names the box. Write std::cout. You will make this one because most code you find online starts with using namespace std;, and you copy the body without that line.

2. One colon instead of two.

std:cout << "hello\n";

The Playground's command line gives the same message as mistake 1. With -Wall -Wextra, GCC 12 adds the clue: warning: label 'std' defined but not used [-Wunused-label]. std: with one colon is a C label, a target for goto, so cout is left bare. You will type it when you are fast, because a double colon is one key pressed twice.

3. Using a name without its header.

#include <iostream>

int main()
{
    std::vector<int> v(3);
    return 0;
}

An error at every command line: error: 'vector' is not a member of 'std', and a helpful note, 'std::vector' is defined in header '<vector>'; did you forget to '#include <vector>'?. GCC does not always know the header: for std::sort it suggests 'qsort', and for std::accumulate it suggests nothing. So read "is not a member of 'std'" as "a header is missing", and look the name up in the table.

4. Calling your own function without its box.

namespace shop {
void sort()
{
}
}

sort();

An error at every command line: error: 'sort' was not declared in this scope; did you mean 'shop::sort'?. Outside the box, its names need the box's name. Write shop::sort();. You will forget it because inside shop the plain name worked.

Brain teaser

Bob reads up to 100 marks, sorts them, and prints how many there were and the lowest. He keeps the count in a global variable, the way he did in C.

#include <algorithm>
#include <iostream>

using namespace std;

int count = 0;

int main()
{
    int marks[100] = {0};
    int x = 0;
    while (count < 100 && cin >> x) {
        marks[count] = x;
        count++;
    }
    sort(marks, marks + count);
    cout << count << " marks, lowest " << marks[0] << '\n';
    return 0;
}

GCC 12 refuses it, on every line that says count, although Bob never asked the library for anything called count. What does GCC 12 say, and why? Then find two different fixes, each keeping the variable's name count and the line using namespace std;.

Read the <algorithm> row of the header table again: sort is not alone in there. Then recall which kind of variable can hide a name that the using-directive let out, and which kind cannot.

Exercise 1Easy

Zara makes a spelling list for her class and wants the words in dictionary order. Write the program with exactly the headers it uses: no header it does not need, none missing, and no <bits/stdc++.h>.

Input. A line with n, then n words.

Output. The n words in dictionary order, one per line.

Constraints. 1 <= n <= 100. Each word is 1 to 20 lowercase letters.

Sample. Input 4, then pear apple zebra mango, gives apple, mango, pear and zebra on four lines.

#include <iostream>
// Add the other headers this program uses here, one per line,
// in alphabetical order. Not <bits/stdc++.h>.

const int MAX_N = 100;

int main()
{
    int n = 0;
    std::cin >> n;

    // Read n words into an array of std::string, sort it with
    // std::sort, and print the words one per line.

    return 0;
}

Not graded on its own. On the Playground it may compile with a header missing, which is this lesson's point, so check every std:: name against the table.

Run in Compiler
Exercise 2Medium

Zara's weather station wants the stronger of two readings: the one further from zero, so -7 beats 5. That is not what std::max means, so she writes her own max in a box of her own, weather, and prints both answers to compare.

Input. Two integers a and b.

Output. Two lines: std::max, one space and the larger of the two; then weather::max, one space and the one further from zero. If both are equally far from zero, weather::max gives a.

Constraints. Each integer is between -100 and 100.

Sample. Input -7 5 gives std::max 5 and weather::max -7 on two lines.

#include <algorithm>
#include <iostream>

namespace weather {
// Return whichever of a and b is further from zero; on a tie, return a.
int max(int a, int b)
{
    return a; // replace this line
}
}

int main()
{
    int a = 0;
    int b = 0;
    std::cin >> a >> b;

    // Print "std::max " and std::max(a, b) on one line,
    // then "weather::max " and weather::max(a, b) on the next.

    return 0;
}

Not graded on its own. Zara would test 5 -5 and 0 0 before the sample.

Run in Compiler

Common doubts

  • Does using namespace std; make my program bigger or slower?

    No. It only changes which names the compiler finds while it reads your code. The program it produces is the same as with std:: written everywhere.

  • Does <bits/stdc++.h> make the program run slower?

    No, only compile slower. A declaration nobody uses produces no machine code. On this lesson's machine the two hello programs came out 65,052 and 65,241 bytes, built with GCC 14.2 (MinGW).

  • Why std::cout with two colons, but std::cin.tie with a dot?

    :: looks inside a namespace, a box of names. . reaches a member of one object, exactly as with a C struct. std::cin is an object in the std box, and tie is one of its members.

  • Can I add my own function to std?

    No. The C++ standard says that adding your own declarations to namespace std is undefined behaviour, apart from a few narrow cases. Put your names in a box of your own, as shop and weather do.

  • Bob asks: can I still use scanf and printf?

    Yes. In C++ they come from <cstdio>, the C++ form of stdio.h, as std::scanf and std::printf. Lesson 02's rule still holds: one family of input and output per program.

Key takeaways

  • A namespace is a named box of names, and box::name reaches inside it, so shop::sort and school::sort never clash.
  • The whole standard library lives in std; using std::cout; lets one name out, and using namespace std; lets them all out.
  • using namespace std; is fine in a short contest file, never in a header; this module writes std:: on every standard name.
  • Every standard name comes from a header in the table; include each one you use, because what a header drags in differs between libraries.
  • <bits/stdc++.h> is GCC's own file: clang with libc++ and MSVC refuse it, and it made a hello program build at least three times slower.

That is the last lesson of this module. Next comes its problem set, ten judged problems that use lessons 01 to 07, and after it Module 2 opens std::vector.

End of lesson 7

Mark it done, and your progress moves with you.

Next: Problems: Just-Enough C++