Structopt
Parse command line arguments by defining a struct
Install / Use
/learn @p-ranav/StructoptREADME
Quick Start
#include <structopt/app.hpp>
struct Options {
// positional argument
// e.g., ./main <file>
std::string config_file;
// optional argument
// e.g., -b "192.168.5.3"
// e.g., --bind_address "192.168.5.3"
//
// options can be delimited with `=` or `:`
// note: single dash (`-`) is enough for short & long option
// e.g., -bind_address=localhost
// e.g., -b:192.168.5.3
//
// the long option can also be provided in kebab case:
// e.g., --bind-address 192.168.5.3
std::optional<std::string> bind_address;
// flag argument
// Use `std::optional<bool>` and provide a default value.
// e.g., -v
// e.g., --verbose
// e.g., -verbose
std::optional<bool> verbose = false;
// directly define and use enum classes to limit user choice
// e.g., --log-level debug
// e.g., -l error
enum class LogLevel { debug, info, warn, error, critical };
std::optional<LogLevel> log_level = LogLevel::info;
// pair argument
// e.g., -u <first> <second>
// e.g., --user <first> <second>
std::optional<std::pair<std::string, std::string>> user;
// use containers like std::vector
// to collect "remaining arguments" into a list
std::vector<std::string> files;
};
STRUCTOPT(Options, config_file, bind_address, verbose, log_level, user, files);
Create a structopt::app and parse the command line arguments into the Options struct:
int main(int argc, char *argv[]) {
try {
// Line of code that does all the work:
auto options = structopt::app("my_app").parse<Options>(argc, argv);
// Print out parsed arguments:
// std::cout << "config_file = " << options.config_file << "\n";
// std::cout << "bind_address = " << options.bind_address.value_or("not provided") << "\n";
// std::cout << "verbose = " << std::boolalpha << options.verbose.value() << "\n";
// ...
} catch (structopt::exception& e) {
std::cout << e.what() << "\n";
std::cout << e.help();
}
}
Now let's pass some arguments to this program:
foo@bar:~$ ./main config.csv file5.csv file6.json
config_file = config.csv
bind_address = not provided
verbose = false
log_level = 1
user = not provided
files = { file5.csv file6.json }
foo@bar:~$ ./main config.csv --bind-address localhost:9000 -v -log-level error file1.txt file2.txt
config_file = config.csv
bind_address = localhost:9000
verbose = true
log_level = 3
user = not provided
files = { file1.txt file2.txt }
foo@bar:~$ ./main config_2.csv --bind-address 192.168.7.3 -log-level debug file1.txt file3.txt file4.txt --user "John Doe" "john.doe@foo.com"
config_file = config_2.csv
bind_address = 192.168.7.3
verbose = false
log_level = 0
user = John Doe<john.doe@foo.com>
files = { file1.txt file3.txt file4.txt }
Table of Contents
- Getting Started
- Building Samples and Tests
- Compiler Compatibility
- Generating Single Header
- Contributing
- License
Getting Started
structopt is a header-only library. Just add include/ to your include_directories and you should be good to go. A single header file version is also available in single_include/.
Positional Arguments
Here's an example of two positional arguments: input_file and output_file. input_file is expected to be the first argument and output_file is expected to be the second argument
#include <structopt/app.hpp>
struct FileOptions {
// Positional arguments
// ./main <input_file> <output_file>
std::string input_file;
std::string output_file;
};
STRUCTOPT(FileOptions, input_file, output_file);
int main(int argc, char *argv[]) {
try {
auto options = structopt::app("my_app").parse<FileOptions>(argc, argv);
// Print parsed arguments:
std::cout << "\nInput file : " << options.input_file << "\n";
std::cout << "Output file : " << options.output_file << "\n";
} catch (structopt::exception& e) {
std::cout << e.what() << "\n";
std::cout << e.help();
}
}
foo@bar:~$ ./main foo.txt bar.csv
Input file : foo.txt
Output file : bar.csv
foo@bar:~$ ./main foo.csv
Error: expected value for positional argument `output_file`.
USAGE: ./my_app input_file output_file
ARGS:
input_file
output_file
Optional Arguments
Now, let's look at optional arguments. To configure an optional argument, use std::optional in the options struct like below.
#include <structopt/app.hpp>
struct GccOptions {
// language standard
// e.g., -std=c++17
// e.g., --std c++20
std::optional<std::string> std = "c++11";
// verbosity enabled with `-v` or `--verbose`
// or `-verbose`
std::optional<bool> verbose = false;
// enable all warnings with `-Wall`
std::optional<bool> Wall = false;
// produce only the compiled code
// e.g., gcc -C main.c
std::optional<bool> Compile = false;
// produce output with `-o <exec_name>`
std::optional<std::string> output = "a.out";
std::string input_file;
};
STRUCTOPT(GccOptions, std, verbose, Wall, Compile, output, input_file);
int main(int argc, char *argv[]) {
try {
auto options = structopt::app("gcc").parse<GccOptions>(argc, argv);
// Print parsed arguments
std::cout << "std : " << options.std.value() << "\n";
std::cout << "verbose : " << std::boolalpha << options.verbose.value() << "\n";
std::cout << "Wall : " << std::boolalpha << options.Wall.value() << "\n";
std::cout << "Compile : " << std::boolalpha << options.Compile.value() << "\n";
std::cout << "Output : " << options.output.value() << "\n";
std::cout << "Input file : " << options.input_file << "\n";
} catch (structopt::exception &e) {
std::cout << e.what() << "\n";
std::cout << e.help();
}
}
NOTE structopt supports two option delimiters, = and : for optional arguments. This is meaningful and commonly used in single-valued optional arguments, e.g., --std=c++17.
foo@bar:~$ ./main -C main.cpp
std : c++11
verbose : false
Wall : false
Compile : true
Output : a.out
Input file : main.cpp
foo@bar:~$ ./main -std=c++17 -o main main.cpp
std : c++17
verbose : false
Wall : false
Compile : false
Output : main
Input file : main.cpp
foo@bar:~$ ./main main.cpp -v -std:c++14 --output:main -Wall
std : c++14
verbose : true
Wall : true
Compile : false
Output : main
Input file : main.cpp
NOTE In summary, for a field in your struct named bind_address, the following are all legal ways to provide a value:
- Short form:
-b <value>
- Long form:
--bind_address <value>-bind_address <value>
- Kebab case:
--bind-address <value>-bind-address <value>
- Equal (
'=') option delimiter-b=<value>--bind_address=<value>-bind_address=<value>--bind-address=<value>-bind-address=<value>
- Colon
':'option delimiter-b:<value>--bind_address:<value>-bind_address:<value>--bind-address:<value>-bind-address:<value>
Double dash (--) Argument
A double dash (--) is used in most bash built-in commands and many other commands to signify the end of command options, after which only positional parameters are accepted.
Example use: lets say you want to grep a file for the string -v - normally -v will be considered the option to
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
