A standalone competitive-programming track under cpp/, independent of the
Gradle build. Design: docs/superpowers/specs/2026-08-16-cpp-track-design.md.
brew install cmake ninja clang-format gcccpp/.clang-format is Google style at ColumnLimit: 100; the repo's git pre-commit hook runs
clang-format --dry-run --Werror on staged .cpp/.hpp files, which is what clang-format
above is for.
g++-16 must be at /opt/homebrew/bin/g++-16; every preset pins it. Apple
clang is never used — <bits/stdc++.h> and __gnu_pbds are libstdc++-only, so
building with clang would diverge from the judges.
gcc is what supplies that binary: the formula is GCC 16.1.0 today, and it
installs the versioned g++-16 rather than a bare g++. The formula tracks the
newest major, so when it moves to GCC 17 the presets keep pinning a g++-16
that a fresh machine no longer has — at that point bump CMAKE_CXX_COMPILER in
cpp/CMakePresets.json, or brew install gcc@16 to keep the pinned path valid.
Open cpp/ as its own CLion project. The repo root has no CMakeLists.txt
because it is a Gradle build. CLion run configurations have a "Redirect input
from" field — point it at a .in file to run one problem against one sample.
cpp/<judge>/<problem>.cpp solution, self-contained, has main()
cpp/<judge>/tests/<problem>/<stem>.in input
cpp/<judge>/tests/<problem>/<stem>.out expected output
A judge is any subdirectory of cpp/ except cmake/ and build/. Adding one
requires no build-file edit.
| Preset | Build dir | Purpose |
|---|---|---|
dev |
cpp/build/dev |
Everyday solving; sanitizers on. Override PS_SCOPE per problem |
all |
cpp/build/all |
Full sweep across every judge |
judge |
cpp/build/judge |
-O2, no sanitizers — matches how BOJ and Codeforces compile |
Separate build directories, so a scoped dev build and a full all sweep
coexist without reconfiguring each other.
Cache variables:
| Variable | Default | Meaning |
|---|---|---|
PS_SCOPE |
all |
all, <judge>, or <judge>/<problem> |
PS_STD |
23 |
C++ standard |
PS_TIMEOUT |
5 |
Per-test timeout in seconds |
Keep your active problem in cpp/CMakeUserPresets.json (gitignored — CMake merges it
with CMakePresets.json automatically), or override per configure:
cd cpp
cmake --preset dev -DPS_SCOPE=boj/1000
cmake --build --preset dev
ctest --preset devCMakeUserPresets.json is not tracked, so its shape has to live here. Template:
{
"version": 3,
"cmakeMinimumRequired": { "major": 3, "minor": 24, "patch": 0 },
"configurePresets": [
{
"name": "current",
"displayName": "current problem",
"inherits": "dev",
"cacheVariables": { "PS_SCOPE": "boj/1000" }
}
]
}current defines only a configure preset — there is no matching current entry under
buildPresets or testPresets, so cmake --build --preset current fails. Because current
inherits dev (and therefore dev's binaryDir), the loop that actually works is:
cd cpp
cmake --preset current
cmake --build --preset dev
ctest --preset devEdit PS_SCOPE in the file each time you switch problems.
- Write
cpp/<judge>/<problem>.cppwith amain. - Add samples under
cpp/<judge>/tests/<problem>/with descriptive stems —max-values.in, not3.in. CTest names each test after the stem, so failures readboj/1000/max-values. cmake --preset dev -DPS_SCOPE=<judge>/<problem> && cmake --build --preset dev && ctest --preset dev- Submit:
pbcopy < cpp/<judge>/<problem>.cpp. Every solution is one self-contained file, so there is no bundling step. - Add the problem to cpp/README.md.
Local fidelity to the judge is a recurring concern, not a one-off — the Java
side carries -Xss128m in boj/build.gradle.kts and -Xss64m in
ps.test-conventions for the same reason. The C++ instances:
- Stack. macOS gives the main thread 8 MB; judges give more. All presets
link
-Wl,-stack_size,0x4000000(64 MB), so a deep DFS does not segfault locally on code the judge accepts. - libstdc++. g++-16 provides
<bits/stdc++.h>and__gnu_pbds. - Compiler version. This is the gap C++23 introduces. Local g++-16
implements more of C++23 than the judges' GCC does, so newer library
additions (
<print>,std::ranges::to,std::mdspan,<stdfloat>) can compile here and fail on the judge. The fallback needs no file edit:cmake --preset dev -DPS_STD=20.
Each .in file becomes one CTest test that runs the binary as a subprocess
and compares stdout to the sibling .out. Subprocess rather than in-process
because it gives a fresh process per case (so a global int a[200005]; cannot
leak between cases), captures printf/scanf output, and survives a solution
calling exit().
Comparison normalizes trailing whitespace only — judges ignore it, but a bug emitting a stray leading space must still fail.
Two configure-time guards exist because an empty glob yields zero tests, and zero tests pass green:
- a
.inwith no matching.outis a fatal error; - a solution with no test data is a warning.
Function-signature judges (LeetCode, Programmers) are designed for but not yet built — see the spec's "Deferred" section.