Relations
Use static constexpr auto relations when a relationship between fields should
be part of the typed schema, generated help, and parse-time validation. The
help generator renders short relation metadata inline on affected options, and
named groups in an Option groups: section.
This is intentionally metadata, not a replacement for constraints().
Relations cover simple occurrence-based rules that are independent of runtime
values. Keep constraints() for value-dependent logic such as "--type foo
requires --foo-config".
API
struct Args {
cli::StringOption<"user"> user;
cli::StringOption<"password"> password;
cli::Flag<"json"> json;
cli::Flag<"markdown"> markdown;
cli::StringOption<"profile"> profile;
static constexpr auto relations = cli::relations(
cli::group({.name = "legacy_auth", .members = {"user", "password"}}),
cli::conflicts("json", "markdown"),
cli::depends_on("legacy_auth", "profile"));
};
Names are written without the command-line prefix: use "json", not
"--json".
Relation Types
cli::group({.name = "...", .members = {...}})requires all members in the named group to be provided together, or none of them.cli::conflicts("a", "b")rejects input when both operands are provided.cli::depends_on("a", "b")rejects input whenais provided butbis not.
All checks are based on provided(): defaults do not count as CLI occurrence.
Named Groups
group creates a named group that can be reused as an operand in another
relation:
static constexpr auto relations = cli::relations(
cli::group({.name = "legacy_auth", .members = {"user", "password"}}),
cli::depends_on("legacy_auth", "profile"));
This means --user and --password must appear together, and that legacy auth
requires --profile.
The generated help shows the rule where users look for it:
--user <string> User name [requires: --profile]
--password <string> Password [requires: --profile]
--profile <string> Profile [required by: legacy_auth]
Option groups:
legacy_auth:
--user, --password must be used together
requires: --profile
Well-Formed Schema Rules
The relation schema is checked at compile time as part of ArgumentSpec.
- Every field or group name used by a relation must exist.
- A
groupneeds a non-empty unique name and at least two members. - A group name must not collide with an option or command name.
- Each field may participate in only one direct relation.
conflicts("a", "a")anddepends_on("a", "a")are invalid.
These rules are deliberately strict. They keep help text and parse-time validation unambiguous.
Relation Metadata vs constraints()
Use relations when the rule is static and occurrence-based:
--jsonconflicts with--markdownlegacy_authdepends on--profile--userand--passwordmust be provided together
Use constraints() when the rule depends on parsed values:
--type s3requires--bucket--mode fastrejects--exact- one numeric option must be greater than another
Example
See Relations Example for a complete program.