Problem
Normally when you use boost's program_options
the order of arguments is not available.
#include <boost/program_options.hpp>
using namespace boost::program_options;
int main(int argc, char** argv) {
options_description options_filters("Filters");
options_filters.add_options()
("lowercase", "Lowercase line")
("uppercase", "Uppercase line")
("max-length", value<int>(), "Remove lines that are longer than this");
variables_map vm;
store(parse_command_line(argc, argv, options_filters), vm);
notify(vm);
for (auto &opt : vm) {
cout << opt.first << endl;
}
}
So running
./app --lowercase --max-length=5
might end up printing
max-length
lowercase
because vm
is an std::map
and the order of items is not preserved.
Solution
It turns out that parse_command_line
returns an object which contains a vector of all arguments in order.
auto parsed = parse_command_line(argc, argv, options_filters);
for (auto &opt : parsed.options) {
cout << opt.string_key << endl;
}
Example
#include <iostream>
#include <iterator>
#include <boost/program_options.hpp>
using namespace std;
using namespace boost;
using namespace boost::program_options;
int main(int argc, char** argv) {
try {
options_description options_filters("Filters");
options_filters.add_options()
("lowercase", "Lowercase line")
("uppercase", "Uppercase line")
("max-length", value<int>()->notifier([](int arg) { cout << "Max=" << arg << endl }),
"Remove lines that are longer than this");
cout << options_filters << endl;
variables_map vm;
auto parsed = parse_command_line(argc, argv, options_filters);
store(parsed, vm);
notify(vm);
for (auto &x : parsed.options) {
cout << x.string_key << endl;
filters.push_back(x.string_key);
auto opt = options_all.find(x.string_key, false).semantic();
opt->notify(vm[x.string_key].value());
}
for (auto &f : filters) {
cout << f << endl;
}
return 0;
} catch (std::exception& e) {
cerr << "error: " << e.what() << endl;
return 1;
} catch (...) {
cerr << "Exception of unknown type!" << endl;
return 1;
}
}