Callback Entry Point
Open this when parsing should populate application state for some other entry point, service object, or orchestration function.
This page is the bridge between cli20 and a larger application architecture. The parser gathers state first, and then your real program entry point runs with that prepared state.
Source
Source: examples/callback_entry_point.cc
examples/callback_entry_point.cc
// callback_entry_point.cc — demonstrates using on_parse callbacks to populate
// an application state object before handing off to the real entry point.
#include <iostream>
#include "cli/argument.hh"
#include "cli/parser.hh"
struct AppState {
bool verbose = false;
int jobs = 1;
std::vector<std::string> includes;
std::vector<std::string> inputs;
};
struct Args {
cli::Description description{
"Populate application state via callbacks, then call the real entry "
"point."};
cli::Help<> help;
cli::Flag<"verbose", 'v'> verbose;
cli::IntOption<"jobs", 'j'> jobs;
cli::ListOption<std::string, "include", 'I', cli::nargs::exactly<1>> includes;
cli::Positional<std::string, cli::nargs::one_or_more> inputs;
};
auto run(const AppState& state) -> int {
std::cout << "verbose: " << std::boolalpha << state.verbose << '\n';
std::cout << "jobs: " << state.jobs << '\n';
for (const auto& include_dir : state.includes) {
std::cout << "include: " << include_dir << '\n';
}
for (const auto& input : state.inputs) {
std::cout << "input: " << input << '\n';
}
return 0;
}
auto main(int argc, char* argv[]) -> int {
AppState state;
Args args;
args.verbose = cli::Flag<"verbose", 'v'>{{
.on_parse = [&state](const bool& value) -> void { state.verbose = value; },
}};
args.jobs = cli::IntOption<"jobs", 'j'>{{
.on_parse = [&state](const int& value) -> void { state.jobs = value; },
}};
args.includes =
cli::ListOption<std::string, "include", 'I', cli::nargs::exactly<1>>{{
.on_parse = [&state](const std::vector<std::string>& value) -> void {
state.includes = value;
},
}};
args.inputs = cli::Positional<std::string, cli::nargs::one_or_more>{{
.on_parse = [&state](const std::vector<std::string>& value) -> void {
state.inputs = value;
},
}};
const auto result = cli::Parser<Args>{}.parse(std::move(args), argc, argv);
if (!result) {
std::cerr << result.error.message() << '\n';
return result.error.exit_code();
}
return run(state);
}
What This Example Shows
This example updates application state incrementally as each argument is parsed
and then hands the finished state to the real entry point. It keeps CLI wiring
at the edge, supports repeated --include options without swallowing
positionals, and leaves the final state in verbose, jobs, includes, and
inputs.
Try It
cli20@cli20-dev:~$ callback_entry_point
Things to try:
- Happy path —
--verbose --jobs 8 --include src --include include main.cc lib.cc - Help —
--help - Multiple includes — add more
--include pathflags to see the list grow - No inputs —
--verboseto see what happens with no positional arguments