A lightweight C++17 single-header command-line parser with no third-party dependencies.
| Type | Examples |
|---|---|
| Flag | --verbose, -v |
| Option | --output=result.txt, --output result.txt, -o=result.txt, -o result.txt |
| Positional | photo.png |
| End of options | -- -photo.png (keeps the leading dash) |
As this lib is header-only, just install the hpp file then include it.
- Install
command-line
wget https://github.com/IridiumNan/cpp-arg-parser/raw/refs/heads/main/arg_parser.hpp
# or curl
# curl -fsSL https://github.com/IridiumNan/cpp-arg-parser/raw/refs/heads/main/arg_parser.hpp -o arg_parser.hppbrowser
- Include
#include "arg_parser.hpp"If your project uses CMake, you can add this repository as a subdirectory:
add_subdirectory(cpp-arg-parser)
target_link_libraries(your_app PRIVATE arg_parser::arg_parser)Note
For Best Practice
See best_practice.cpp
Just use this lib with 3 steps
This can be used as follows
-
Step 1: Add expected arguments
-
Step 2: Parse all args
-
Step 3: Fetch argument with type assign or fetch by index (for positional args)
#include "arg_parser.hpp"
#include <exception>
#include <iostream>
#include <string>
constexpr const char *usage = "Usage: \ng++ [options] file...\n";
#ifdef _WIN32
int wmain(int argc, wchar_t *argv[])
#else
int main(int argc, char *argv[])
#endif
{
using arg_parser::ArgType;
arg_parser::ArgParser parser("g++", usage);
// or set the program name by set_xxx function
// parser.set_program_name("cpp");
// parser.set_usage(usage);
// step 1: set the required arguments
// [ArgType::Option] and [ArgType::Flag] support
// default Flag
// For Flag, default value will be false, no need to set manually
parser.add_argument("verbose", "v")
.set_description("if true, print with verbose output");
parser.add_argument("output", "o", ArgType::Option)
.set_description("Place the output into <file>.")
.set_required(true);
parser.add_argument("help", "h")
.set_description("print help manual");
try {
// step 2: parse arguments directly
// WARN: Don't use the vector version unless you know what you're doing
parser.parse(argc, argv);
// step 3: traverse the positional args
// fetch option value with type assign
for (size_t i = 0; i < parser.size(); i++) {
std::cout << i << " pos: " << parser.at(i) << '\n';
}
std::cout << "verbose: " << parser.get<bool>("v") << '\n';
std::cout << "output: " << parser.get<std::string>("o") << '\n';
} catch (const std::exception &err) {
std::cerr << err.what() << '\n';
// if you have setted usage, just leave it empty
std::cout << parser.help();
return 1;
}
}- compile
g++ -std=c++17 example.cpp -o bin/example- run
bin/example photo.png -o result.txt -v
# output
0 pos: photo.png
verbose: 1
output: result.txtbin/example -o bin/main hello -- --port world
#output
# all arguments behind -- will be treated as positional args
0 pos: hello
1 pos: --port
2 pos: world
verbose: 0
output: bin/main- auto help manual generation (for Options)
bin/example example.cpp main.cpp
# output
Required argument not provided: output
Usage:
g++ [options] file...
Options:
--verbose, -v
if true, print with verbose output
--output, -o <value>
Place the output into <file>.
--help, -h
print help manualOn Windows with MinGW, use wmain and add -municode:
int wmain(int argc, wchar_t* argv[])g++ -std=c++17 -municode example.cpp -o example.exe| Function | Description |
|---|---|
ArgParger(program_name, usage) |
Create a new parser |
add_argument(name, alias = nullopt, type = ArgType::Flag) |
Register an argument. |
set_program_name(program_name) |
Set program name for parser |
set_usage(usage) |
Set usage for parser |
parse(argc, argv) |
Parse main arguments (skips argv[0]). |
has(name) |
Check if provided, by name or alias. |
get<T>(name) |
Get a typed value, by name or alias. |
help() |
Return the help text. |
size() / at(i) |
Access positional arguments. |
| Function | Description |
|---|---|
set_default(value) |
Set a default value. |
set_description(text) |
Set the help description. |
set_required(true) |
Throw if the argument is not provided. |
- Values starting with
-require=:--count=-12works,--count -12does not. - Combined short flags like
-vhare not supported. - Call
parse()once per instance. -h/--helpare not automatic — checkparser.get<bool>("help")yourself.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureTo build examples as well:
cmake -S . -B build -DARG_PARSER_BUILD_EXAMPLES=ON
cmake --build buildThanks to KAI-SHUNG who write the first version of this parser