Title here
Summary here
Here’s the translation of the Go code to C++, along with explanations in Markdown format suitable for Hugo:
Our program demonstrates the use of subcommands in command-line applications. Some command-line tools have many subcommands, each with its own set of flags. For example, git commit
and git push
are two different subcommands of the git
tool. We’ll use the <cxxopts>
library to easily define simple subcommands that have their own flags.
#include <iostream>
#include <cxxopts.hpp>
#include <string>
#include <vector>
int main(int argc, char* argv[]) {
// We declare subcommands using cxxopts::Options objects,
// and proceed to define new options specific for each subcommand.
cxxopts::Options fooCmd("foo", "Foo subcommand");
fooCmd.add_options()
("e,enable", "Enable", cxxopts::value<bool>()->default_value("false"))
("n,name", "Name", cxxopts::value<std::string>()->default_value(""));
// For a different subcommand we can define different
// supported options.
cxxopts::Options barCmd("bar", "Bar subcommand");
barCmd.add_options()
("l,level", "Level", cxxopts::value<int>()->default_value("0"));
// The subcommand is expected as the first argument
// to the program.
if (argc < 2) {
std::cout << "expected 'foo' or 'bar' subcommands" << std::endl;
return 1;
}
// Check which subcommand is invoked.
std::string subcommand = argv[1];
// For every subcommand, we parse its own options and
// have access to trailing positional arguments.
if (subcommand == "foo") {
auto result = fooCmd.parse(argc - 1, argv + 1);
std::cout << "subcommand 'foo'" << std::endl;
std::cout << " enable: " << (result["enable"].as<bool>() ? "true" : "false") << std::endl;
std::cout << " name: " << result["name"].as<std::string>() << std::endl;
std::cout << " tail: ";
for (const auto& arg : result.unmatched()) {
std::cout << arg << " ";
}
std::cout << std::endl;
} else if (subcommand == "bar") {
auto result = barCmd.parse(argc - 1, argv + 1);
std::cout << "subcommand 'bar'" << std::endl;
std::cout << " level: " << result["level"].as<int>() << std::endl;
std::cout << " tail: ";
for (const auto& arg : result.unmatched()) {
std::cout << arg << " ";
}
std::cout << std::endl;
} else {
std::cout << "expected 'foo' or 'bar' subcommands" << std::endl;
return 1;
}
return 0;
}
To compile the program:
$ g++ -std=c++11 command_line_subcommands.cpp -o command_line_subcommands -lcxxopts
First invoke the foo subcommand:
$ ./command_line_subcommands foo --enable --name=joe a1 a2
subcommand 'foo'
enable: true
name: joe
tail: a1 a2
Now try bar:
$ ./command_line_subcommands bar --level 8 a1
subcommand 'bar'
level: 8
tail: a1
But bar won’t accept foo’s flags:
$ ./command_line_subcommands bar --enable a1
error: unrecognised option '--enable'
Next we’ll look at environment variables, another common way to parameterize programs.