'What is boost::program_options::notify() for?
This question is about the C++ Boost program_options library.
All the tutorials are very clear that I should call notify() on my completed variable map, but I'm not sure what this is actually doing for me. Commenting it out didn't seem to have any effect, and the documentation didn't go into much detail:
http://www.boost.org/doc/libs/1_47_0/doc/html/boost/program_options/notify.html
Other sources suggest that it runs "user-defined" functions. If so, how are those functions registered and what do they do? Might they throw exceptions?
Solution 1:[1]
I think you are on the right track when you mention "functor"...
It's quite common for an option to be processed by passing its argument(s) to some object's method. This can be done more directly with notifiers if you can wrap the method into something that notifier() will accept as an argument. And you can. (If boost::function has a way of doing so, I'm not familiar enough with it (and am too lazy to go study up on it now) -- the following uses the routines in header functional from STDLIB.)
Example:
One of your options is --config-file, taking a string argument, which tells the path of a non-default configuration file. You have a class called ConfigParser. Without notifiers, your code might look something like this:
ConfigParser *cp = new ConfigParser();
std::string cp_path;
desc.add_options()
("config-file", value<std::string>(&cp_path)->default_value("~/.myconfig"), "Config File")
// ... the rest of your options
;
cp->setPath(cp_path);
With notifiers:
#include <functional>
ConfigParser *cp = new ConfigParser();
desc.add_options()
("config-file", value<std::string>()->default_value("~/.myconfig")->notifier(std::bind1st(std::mem_fun(&ConfigParser::setPath), cp)), "Config File")
// ... the rest of your options
;
Solution 2:[2]
I like to look straight to the source. So, here you go: https://github.com/boostorg/program_options/blob/develop/include/boost/program_options/variables_map.hpp#L52:
/** Runs all 'notify' function for options in 'm'. */
BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
So, it runs all the notify() functions for the variables_map, m, which is a wrapper around std::map<std::string, variable_value>, and contains a map from command options (as std::strings) to variable_values (any type).
Now this answer by @Conspicuous Compiler has more context, so go read it. Looking at his answer in addition to the source code helps me.
Also (as the OP already knows, but this is for other people), here is an introductory Boost tutorial on how to use the <boost/program_options.hpp> module: https://www.boost.org/doc/libs/1_75_0/doc/html/program_options/tutorial.html. It's really kind of "hand-wavy." They don't expect you to have a clue what these particular functions really do. All they want you to know is how to follow the pattern and use the library, as they insinuate when they say:
Next, the calls to
store,parse_command_lineandnotifyfunctions causevmto contain all the options found on the command line.
(referring to this code from the example below):
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
They are doing some pretty fancy black-magic vudu in C++ as it is when you call the add_options() function.
Here is the full context of their basic tutorial example:
// Copyright Vladimir Prus 2002-2004.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
/* The simplest usage of the library.
*/
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <iostream>
#include <iterator>
using namespace std;
int main(int ac, char* av[])
{
try {
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("compression", po::value<double>(), "set compression level")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
if (vm.count("help")) {
cout << desc << "\n";
return 0;
}
if (vm.count("compression")) {
cout << "Compression level was set to "
<< vm["compression"].as<double>() << ".\n";
} else {
cout << "Compression level was not set.\n";
}
}
catch(exception& e) {
cerr << "error: " << e.what() << "\n";
return 1;
}
catch(...) {
cerr << "Exception of unknown type!\n";
}
return 0;
}
They have more examples here: https://github.com/boostorg/program_options/tree/develop/example.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Phil |
| Solution 2 |
