Installation¶
melon is header-only and dependency-free: adding its include/ directory to your include path and compiling with C++23 is enough. The sections below cover the packaged routes, which additionally give you an imported CMake target.
Requirements¶
C++23 is the baseline; GCC 15 / C++26 is recommended. Every configuration below is exercised by CI on every commit.
| Compiler | Minimum version | CI configuration |
|---|---|---|
| GCC | 14 | GCC 14 / C++23, GCC 15 / C++26 |
| Clang | 18 | Clang 18 / C++23 (with libstdc++ 14) |
| Apple Clang | 21 (Xcode 26.4) | Apple Clang 21 / C++23 (libc++, macOS arm64) |
| MinGW-w64 GCC | 15 | MinGW GCC 15 / C++26 (Windows) |
| MSVC | VS 2022 17.11 (toolset v14.41) | MSVC 17.11 / C++23 (Windows) |
The compiler floors are really standard-library floors: libstdc++ 14 or
libc++ 20, whichever the compiler is paired with. Clang against an older
libstdc++ stops at a single readable #error naming the requirement. On
libc++ the limiting feature is std::jthread, which is experimental before
release 20; Apple Clang 21 (Xcode 26.4) is the first Apple toolchain whose
libc++ meets it, and the Apple Clang 17 line (Xcode 16.3 to 26.3) does not.
Linux and Windows clang builds against libc++ 20 or newer are expected to
work but are not in the CI matrix.
MSVC
melon builds with /std:c++latest on MSVC (the CMake and Conan routes
select it automatically from C++23). Two MSVC-specific facts are worth
knowing. First, MSVC ignores [[no_unique_address]], so melon objects
carry a few extra bytes there — behaviour is identical. Second, an MSVC
front-end limitation (present through VS 2026): in a translation unit
with a file-scope using namespace melon;, creating maps over a graph
that provides create_vertex_map / create_arc_map / create_edge_map
as free functions
fails to compile, because MSVC's instantiation-time lookup reaches the
customization point object itself. Qualify melon names, or use targeted
using-declarations, in such files. Graphs with member map factories —
every melon container and view included — are unaffected.
CMake 3.24 or later is required for the CMake integration, and Conan 2.0 or later for the Conan one. Asking CMake for a C++26 build needs 3.30: CXX_STANDARD 26 became a valid value in 3.25, but no -std=c++26 mapping exists for GCC before 3.30, where the cxx_std_26 compile feature was finally implemented. Older CMake is not an error — the melon::melon target requires only cxx_std_23, so you get a working C++23 build with the range shapes noted below.
C++23 versus C++26
melon uses std::ranges::concat_view, which is a C++26 addition. When the
standard library does not advertise it through __cpp_lib_ranges_concat,
melon falls back to a bundled implementation — this needs no flag, and is
why C++23 works. Nothing else in the library is conditional.
The fallback is a forward range ending at a sentinel; std's is also sized, common and random-access whenever its bases are. Three members are built on it, and only one of them — over a graph whose own incidence ranges are richer than forward — can tell the difference:
| expression | C++23 | GCC 15 / C++26 |
|---|---|---|
incidence(ug, v), ug undirecting a static_digraph |
forward | forward, bidirectional, random-access, sized, common |
incidence(ug, v), ug undirecting a mutable_digraph |
forward | forward |
in_arcs(g, v) on a complete_digraph |
forward | forward |
bidirectional_dijkstra::path() |
forward | forward |
So C++23 is the shape melon guarantees: a range documented only by
concept is a forward_range you walk to its end, and a C++26 standard
library may hand you a stronger one but never a weaker one. Write against
that floor — ask degree(ug, v) for a cardinality rather than sizing the
range — and the same code compiles on every configuration in the table
above. Code that requires sized_range, common_range or
random_access_range of one of those ranges compiles on GCC 15 / C++26
and fails on the GCC 14 minimum.
To catch that from a C++26 build without installing GCC 14, configure with
-DMELON_PORTABLE_RANGE_SHAPES=ON (or define the macro of the same name):
melon then uses the fallback everywhere and reproduces the C++23 shapes.
The setting must be the same for every translation unit of a program — it
changes the return type of incidence() — which is why the CMake option
puts it on the melon::melon interface target, and it is also why objects
compiled as C++23 and as C++26 must not be linked into one program.
As a Conan package¶
From the repository (the tagged 1.0.0 release — the recommended route):
$ git clone https://github.com/fhamonic/melon
$ cd melon
$ conan create . -u -b=missing -pr=<your_conan_profile>
Then declare the dependency in your own conanfile.txt:
From Conan Center (latest published release):
Warning
The 1.0.0-alpha.1 package on Conan Center is a pre-1.0 alpha that
predates two breaking changes: it still depends on range-v3, and its
symbols live in the fhamonic::melon namespace rather than melon.
Prefer the repository / tagged release until the 1.0.0 package lands on
Conan Center.
Either way, consume it from CMake with:
As a CMake subdirectory¶
Clone melon into your project, or add it as a submodule:
then:
The melon target is an INTERFACE library carrying the cxx_std_23 compile feature, so linking against it raises your target's standard if needed. It exports no warning flags of its own.
MELON_BUILD_TESTS defaults to PROJECT_IS_TOP_LEVEL, so consuming melon this way builds no tests and downloads no GTest.
Installed system-wide¶
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DMELON_BUILD_TESTS=OFF
$ cmake --install build --prefix /usr/local
This installs the headers together with melonConfig.cmake and
melonConfigVersion.cmake (SameMajorVersion, architecture-independent), so consumers can find_package(melon CONFIG) exactly as with the Conan package.
Headers¶
Every component is a separate header under melon/, and you include what you use:
melon/all.hpp pulls in the entire public API — convenient for a scratch program, wasteful in a build you care about. The header map lists every header and what it declares.
Everything lives in namespace melon. Prior releases nested it inside an umbrella fhamonic namespace; that was removed, so fhamonic::melon::dijkstra is now melon::dijkstra.
Four sub-namespaces carve out the parts that would otherwise take very generic names at top level: melon::views for graph views, melon::maps for mapping views, melon::numeric for rational / integer / bounded_value, and melon::experimental. See Headers.
API stability¶
Starting with 1.0.0, melon follows semantic versioning: every header is frozen API for the whole 1.x series, with two explicit exceptions that carry no stability guarantee and may change or disappear in any release:
melon/detail/— implementation details, as well as any symbol in adetailnamespace;melon/experimental/— work-in-progress data structures. These live innamespace melon::experimental, so nothing reaches the stablemelonnamespace by accident.
The guarantee covers every documented name in namespace melon, melon::views, melon::maps and melon::numeric — the customization point objects (vertices, out_arcs, …) are reachable as melon:: names and covered as such, while melon::cpo, which holds only their implementation types, stays out per the detail rule above — plus the behavioural contracts stated throughout this documentation — the algorithm lifecycle, the ownership rules, the mapping concepts. Those contracts are deliberate design decisions, each pinned by tests (test/api_consistency.cpp, test/api_review.cpp), and will not be relitigated within 1.x. If a 1.x release ever breaks code that follows them, that is a bug in melon.
Do not forward-declare melon types
Whether a documented name is a class, a class template or an alias of
one — static_digraph is basic_static_digraph<> — is not part of the
guarantee, and a defaulted template parameter may be appended in a
minor release. A user-side class static_digraph; can therefore stop
compiling; include the header instead.
Types documented only by concept are not frozen
The exact type of a member documented only by concept — the concrete range
type an algorithm's iteration yields, for instance, beyond what
traversal_algorithm promises — is not covered. Spell such types with
auto or decltype.
melon/version.hpp is the single source of truth for the version number and lets you feature-test:
#include "melon/version.hpp"
#if MELON_VERSION >= 10000 // MAJOR * 10000 + MINOR * 100 + PATCH
...
#endif
Building the test suite¶
From a checkout, with Conan:
or with plain CMake, which falls back to fetching GTest if it is not installed:
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
$ cmake --build build -j"$(nproc)"
$ ctest --test-dir build --output-on-failure
Set MELON_SANITIZE to build the suite with sanitizers, e.g. -DMELON_SANITIZE=address,undefined.
Next steps¶
A first graph walks through building a graph and running an algorithm on it.