This is a lightweight, header-only C++ library for parsing command-line flags.
- Supports
int64_t
,double
,bool
, andstd::string
flag types. - Parses long options (e.g.,
--port 9090
,--port=9090
). - Handles boolean flags without explicit values (e.g.,
--debug
impliestrue
). - Supports positional arguments.
- Provides clear error messages for unknown flags, missing values, and invalid values.
- Includes a
Get<T>
helper function for easy, type-safe value retrieval.
To use the library, simply include the cppflag.hpp
header file in your project.
First, create a FlagSet
object. Then, define your flags using the Int
, Float
, Bool
, and String
methods. You can also provide an optional short name alias for each flag.
#include "cppflag.hpp"
cli::FlagSet fs("my_app", "An example application");
fs.Int("port", 8080, "port to listen on", 'p');
fs.Bool("debug", false, "enable debug logging", 'd');
fs.Float("ratio", 1.5, "a float value", 'r');
fs.String("mode", "fast", "running mode", 'm');
Call the Parse
method with argc
and argv
to parse the command-line arguments.
cli::ParseResult pr = fs.Parse(argc, argv);
if (!pr) {
fs.PrintError(pr, std::cerr);
std::cerr << "\n";
fs.PrintUsage(std::cerr);
return 2;
}
There are two ways to access the parsed values:
Method 1: Use the Flag*
pointer (most efficient)
When you define a flag, the method returns a Flag*
pointer. You can store this pointer and use its As<T>()
method to get the value after parsing.
auto portFlag = fs.Int("port", 8080, "port to listen on");
int64_t port = portFlag->As<int64_t>();
Method 2: Use the Get<T>
helper function (convenient)
This helper function looks up the flag by name and returns its value. This is more convenient if you don't want to store the Flag*
pointers.
int64_t port = cli::Get<int64_t>(fs, "port");
bool debug = cli::Get<bool>(fs, "debug");
double ratio = cli::Get<double>(fs, "ratio");
std::string mode = cli::Get<std::string>(fs, "mode");
Any arguments that are not flags or flag values are treated as positional arguments. You can access them using the Positional()
method.
for (const auto& p : fs.Positional()) {
std::cout << "Positional argument: " << p << "\n";
}
You can use the IsSet
method to check if a flag was explicitly set by the user on the command line.
if (fs.IsSet("port")) {
std::cout << "The port was set by the user.\n";
}
The library automatically defines a --help
(with a short alias -h
) flag for you. When this flag is used, the Parse
method will return a result with kind
equal to cli::ParseErrorKind::HelpRequested
. You can check for this and print the usage information.
cli::ParseResult pr = fs.Parse(argc, argv);
if (pr.kind == cli::ParseErrorKind::HelpRequested) {
fs.PrintUsage(std::cout);
return 0;
}
The help message includes the usage string and a list of all defined flags with their descriptions and default values.
Usage: full_demo [flags]
A full demo for FlagSet
Flags:
-p, --port port to listen on (default: 8080)
-d, --debug enable debug logging (default: false)
-r, --ratio ratio for calculation (default: 1.000000)
-m, --mode running mode (default: fast)
-h, --help show this help message (default: false)
A complete example can be found in full_demo.cpp
.
To compile and run the example:
g++ -std=c++17 full_demo.cpp -o full_demo_app
./full_demo_app --port=-9090 --debug --ratio=2.5 arg1 arg2