Linker errors and the ODR
The header triple.h, guarded by #pragma once, holds not a declaration but a definition: int triple(int x) { return x * 3; }. Two files include it—report.cpp and this main.cpp:
#include <iostream>
#include "triple.h" // ✗
int main() {
std::cout << triple(14) << '\n';
}Each file compiles without errors, but the build clang++ main.cpp report.cpp stops at linking:
multiple definition of `triple(int)'The one definition rule
The linker joins the object files of all translation units into one program. Each of the two units got its own definition of triple from the header, so the program now has two. The one definition rule (ODR) forbids this: a function has at most one definition per program, and exactly one if called. #pragma once does not help here: the copies sit in different translation units.
The rule can be broken from the other side too. If triple.h holds only a declaration and the build command leaves out triple.cpp, every file still compiles: each has the declaration. Then the linker reports undefined reference, or undefined symbol in the course exercises. It names the function, not the file: find the .cpp file that defines it and check that the command lists it.
inline in a header
If the definition has to stay in the header, the function is declared inline:
#pragma once
inline int triple(int x) {
return x * 3;
}The word inline lets a function's definition repeat in different translation units, as long as all the copies are identical. Copies from one header are always identical, and the linker keeps one of them. constexpr functions count as inline too, so they are defined right in headers. Other functions are usually split: the declaration goes in the header, the definition in a .cpp file.
Common mistake
A .cpp file is included instead of the header:
#include <iostream>
#include "triple.cpp" // ✗
int main() {
std::cout << triple(14) << '\n';
}main.cpp itself compiles, but the build clang++ main.cpp triple.cpp fails with multiple definition again. The definition of triple ended up in two translation units: in triple.cpp and in main.cpp, where #include pasted it. Include the header triple.h, and pass .cpp files only to the build command. The tests in the course exercises do include your solution's .cpp file, but there the whole build is one translation unit.