I wrote a small app that uses boost::program_options for command-line parsing.
I'd like to have some options that set a value if the argument is present, and alternately prints the current value if the parameter is given but no argument is present. So "set-mode" would look like:
dc-ctl --brightness 15
and "get mode" would be:
dc-ctl --brightness
brightness=15
The problem is, I don't know how to handle the second case without catching this exception:
error: required parameter is missing in 'brightness'
Is there an easy way to avoid having it throw that error? It happens as soon as the arguments are parsed.
I got a partial solution from How to accept empty value in boost::program_options which suggests using the implicit_value method on those parameters that may or may not have arguments present.
So my call to initialize the "brightness" parameter looks like this:
("brightness,b", po::value<string>()->implicit_value(""),
I then iterate over the variable map and for any argument that's a string, I check if it's empty and if so I print the current value. That code looks like this:
// check if we're just printing a feature's current value
bool gotFeature = false;
for (po::variables_map::iterator iter = vm.begin(); iter != vm.end(); ++iter)
{
/// parameter has been given with no value
if (iter->second.value().type() == typeid(string))
if (iter->second.as<string>().empty())
{
gotFeature = true;
printFeatureValue(iter->first, camera);
}
}
// this is all we're supposed to do, time to exit
if (gotFeature)
{
cleanup(dc1394, camera, cameras);
return 0;
}
UPDATE: this changes the aforementioned syntax, when using implicit values, now arguments, when given, must be of the form:
./dc-ctl -b500
instead of
./dc-ctl -b 500
Hope this is helpful to someone else.
Related
I have an if statement which needs to check for the existence of a value in a nested Option. The statement currently looks like
if my_vec.get(0).is_some() && my_vec.get(0).unwrap().is_some() {
// My True Case
} else {
// My Else Case
}
I feel like this is an amateurish way of checking if this potential nested value exists. I want to maintain safety when fetching the Option from the array as it may or may not exist, and also when unwrapping the Option itself. I tried using and_then and similar operators but haven't had any luck.
I would check the length first and access it like a regular array instead of using .get(x) unless there is some benefit in doing so (like passing it to something which expects an option).
if my_vec.len() > x && my_vec[x].is_some() {
// etc
}
Another option is to just match the value with an if let x = y or full match statement.
if let Some(Some(_)) = my_vec.get(x) {
// etc
}
The matches! macro can also be used in this situation similarly to the if let when you don't need to take a reference to the data.
if matches!(my_vec.get(x), Some(Some(_))) {
// etc
}
Or the and_then version, but personally it is probably my least favorite since it is longer and gargles the intention.
if my_vec.get(x).and_then(|y| y.as_ref()).is_some() {
// etc
}
You can pick whichever one is your favorite. They all compile down to the same thing (probably, I haven't checked).
I am trying to figure out how to assign a message field in protobuf2 in C++. Here is a small snippet of the code.
message Sub {
optional double x = 1 [[default = 46.0];
}
message Master {
optional Sub sub_message;
}
Now when I try to initialize a Master message, I got the following error:
Master msg;
msg.mutable_sub_message() = new Sub();
error: expression is not assignable
However, the following code works, and the sub_message is set to default values:
Master msg;
msg.set_sub_message(new Sub());
Can anyone kindly explain why mutable_sub_message() can not be used for assignment?
msg.mutable_sub_message() returns a pointer to the field, i.e. a Sub*. The idea is that you use that pointer to manipulate the field as you need.
Assigning a different pointer to it wouldn't change the value inside the class, it would at most change the temporary pointer that was returned, which doesn't make sense. I guess it could be made to work if mutable_sub_message returned something like a Sub*& (not even sure that syntax is right), but that's not how the library was written.
In a more practical note, calling mutable_sub_message will initialize the subfield, you don't need to do that explicitly. That means you'd usually set a nested field using
Master msg;
msg.mutable_sub_message()->set_x(4.0);
Also, it's always safe to call getters even if a field isn't set, in that case they will always return a default instance. In other words:
double use_field(const Master& msg) {
// This is always safe, and will return the default even if
// sub_message isn't set.
return msg.sub_message().x();
}
I often use -1 as the invalid value type when returning from a function, where the input yields incorrect output. For instance, writing an indexing function where the index is out of bounds, instead of throwing an exception, -1 can be returned. But when writing a function that has negative values as possible return types, this technique does not work. What is the correct way to return an invalid type value in such instances?
The technique I use mostly is to set the return type to be of type *int, and return a Pointer to NULL. But, that requires all return values to be of a pointer type, which seems like an extra overhead to the function. Is there an accepted standard for returning values in such cases?
In newer C++, I'd suggest using std::optional<>; if you don't yet have it, boost::optional<>.
One option would be to let your function take a bool& as an output parameter used to indicate if the returned value is valid.
int myFunc(bool& valid); // sets 'valid' to true if result is usable, false otherwise
Users can then do
bool valid = false;
Int result = myFunc(valid);
if (!valid) {
// Handle error
}
// Use result
Not the most pretty solution, but it does the job.
Apart from the answer I provided above, there's a very clean, continuation-passing solution (given you're non-virtual):
template<typename Success, typename Failed>
void parse( const std::string& str, Success s, Failed f )
{
auto a = start_parse(str);
if( a.problem() )
return f(); // you _might_ have an error code here
s( finish_parse(str, a) );
}
Then you might customize by:
Success:
[&i] (int i_) { i = i_; }
out(i), where out(int& output_) returns the above lambda for output_
actual code doing something useful
function to continue with
Failed:
[&i]{ i = 0; }, `[&i]{ i = nullopt; }, or any other default value
[] { throw MyFavouriteException(); }
retry logic
std::terminate()
[]{} if you don't care (or if you're 100% sure it'll succeed)
It might look a little verbose, but IMHO:
it's trivial to read
any other schematics can be mimicked, even if there's no default c'tor
easy to change as well
'you don't pay for what you don't use', can surely be optimized away
every schematic is visible and apparent from code:
for default value, caller sets it, not callee or global
std::optional<> and default value are handled the same
for exception, caller knows better what to throw
for no action, you don't have to lookup the implementation to know this
for std::terminate(), well, you know what to expect
if you 'speak' CPS, you might actually continue and save an if / catch / etc.
The only issue I see is constructor initializer lists. Any thoughts on this?
I'm currently learning C++ and practicing my Knowledge by implementing an simple AddressBook Application. I started with an Entry class and an AddressBook class which implements a STL Map to access the entries by the last names of the persons. Now I arrived at the following code:
Entry AddressBook::get_by_last_name(string last_name){
if(this->addr_map.count(last_name) != 0){
//What can I do here?
} else {
return addr_map[last_name];
}
In Scripting Languages I would just return something like -1, Error Message(A List in Python) to indicate that the Function failed. I don't want throw an exception, because it's part of the application logic. The Calling Class should be able to react to the request by printing something on the console or opening a Message Box. Now I thought about implementing the Scripting Languae Approach in C++ by introducing some kind of an Invalid State to the Class Entry. But isn't that bad practice in C++? Could it be that my whole class design is just not appropriate? I appreciate any help. Please keep in mind that I'm still learning C++.
Some quick notes about your code:
if(this->addr_map.count(last_name) != 0){
//What can I do here?
You probably wanted it the other way:
if(this->addr_map.count(last_name) == 0){
//handle error
But your real problem lies here:
return addr_map[last_name];
Two things to note here:
The operator[] for map can do 2 things: If the element exists, it returns it; If the element doesn't exist, it creaets a new (key,value) pair with the specified key and value's default constructor. Probably not what you wanted. However, if your if statement from before would have been the right way, then the latter would never happen because we would knowthe key exists before hand.
In calling count() before, you effectively tell map to try and find the element. By calling operator[], you are telling map to find it again. So, you're doing twice the work to retrieve a single value.
A better (faster) way to do this involves iterators, and the find method:
YourMap::iterator it = addr_map.find(last_name); //find the element (once)
if (it == addr_map.end()) //element not found
{
//handle error
}
return *it.second; //return element
Now, back to the problem at hand. What to do if last_name is not found?
As other answers noted:
Simplest solution would be to return a pointer (NULL if not found)
Use boost::optional.
Simply return the YourMap::iterator but it seems that you are trying to "hide" the map from the user of AddressBook so that's probably a bad idea.
throw an exception. But wait, now you'll have to first check that calling this method is 'safe' (or handle the exception when appropriate). This check requires a boolean method like lastNameExists which would have to be called before calling get_by_last_name. Of course then we'er back to square 1. We're performing 2 find operations to retrieve a single value. It's safe, but if you're doing A LOT of calls to get_by_last_name then this is potentially a good place to optimize with a different solution (besides, arguably the exception is not very constructive: What's wrong with searching for something that isn't there, huh?).
Create a dummy member for Entryindicating that is not a real Entry but that is very poor design (unmanageable, counter intuitive, wasteful - you name it).
As you can see, the first 2 solutions are by far preferable.
One dead-simple option is to change the return type to Entry* (or const Entry*) and then return either the address of the Entry if found, or NULL if not.
If you use Boost, you could return a boost::optional<Entry>, in which case your success code would be the same, but on not-found you'd say return boost::none. This is fancier, but does about the same thing as using a pointer return type.
Throwing an exception is definitely the 'correct' C++ thing to do, based on your function return type.
You might want a function like this to help you, though:
bool AddressBook::lastNameExists(const string &last_name)
{
return addr_map.count(last_name) > 0;
}
Note that your current code returns the entry 'by value' so modifying the returned entry won't update the map. Not sure if this is by accident or design...
Other answers have given various approaches, most of them valid. I didn't see this one yet:
You could add a second parameter with a default value:
Entry AddressBook::get_by_last_name(string last_name, const Entry& default_value){
if(this->addr_map.count(last_name) == 0){
return default_value;
} else {
return addr_map[last_name];
}
In this particular instance, there might not be a sensible default value for a non-existing last name, but in many situations there is.
In C++ you have several ways of signalling that an issue happened in your function.
You can return a special value which the calling code will recognize as an invalid value. This can be a NULL pointer if the function should return a pointer, or a negative value if your function returns an index in an array, or, in the case of a custom class (e.g. your Entry class) you can define a special Entry::invalid value or something similar that can be detected by the calling function.
Your calling code could look like
if ( entryInstance->get_by_last_name("foobar") != Entry::invalid)
{
// here goes the code for the case where the name is valid
} else {
// here goes the code for the case where the name is invalid
}
On the other hand you can use the C++ exceptions mechanism and make your function throw an exception. For this youcan create your own exception class (or use one defined in the standard library, deriving from std::exception). Your function will throw the exception and your calling code will have to catch it with a try...catch statement.
try
{
entryInstance->get_by_last_name("foobar")
}
catch (Exception e)
{
// here goes the code for the case where the name is invalid
}
// here goes the code for the case where the name is valid
Apart from the fact that you could have more than one entry per surname.
Eliminate the getter, and you've solved the problem, or at least shifted it elsewhere.
Tell the AddressBook to display people with given surnames. If there aren't any it can do nothing.
AddressBookRenderer renderer;
AddressBook contacts;
contacts.renderSurnames("smith", renderer);
contacts.renderCompletions("sm", renderer);
//etc
You can do what std::map (and the other containers do).
You return an iterator from your search function.
If the search does not find a value that is useful return an iterator to end().
class AddressBook
{
typedef <Your Container Type> Container;
public:
typedef Container::iterator iterator;
iterator get_by_last_name(std::string const& lastName) {return addr_map.find[lastName];}
iterator end() {return addr_map.end();}
};
Your address book is a container like object.
Not finding an item in a search is likely to happen but it does not have enough context to incorporate error handling code (As the address book could be used from lots of places and each place would have different error handling ideas).
So you must move the test for not found state out of your address book.
just like "Python" we return a marker. In C++ this is usually an iterator to end() which the calling code can check and take the appropriate action.
AddressBook& ab = getAddressBookRef();
AddressBook::iterator find = ab.get_by_last_name("cpp_hobbyist");
if (find != ab.end())
{
Entity& person *find; // Here you have a reference to your entity.
// you can now manipulate as you want.
}
else
{
// Display appropriate error message
}
I have recently started to use boost::program_options and found it to be highly convenient. That said, there is one thing missing that I was unable to code myself in a good way:
I would like to iterate over all options that have been collected in a boost::program_options::variables_map to output them on the screen. This should become a convenience function, that I can simply call to list all options that were set without the need to update the function when I add new options or for each program.
I know that I can check and output individual options, but as said above, this should become a general solution that is oblivious to the actual options. I further know that I can iterate over the contents of variables_map since it is simply an extended std::map. I could then check for the type containd in the stored boost::any variable and use .as<> to convert it back to the appropriate type. But this would mean coding a long switch block with one case for each type. And this doesn't look like good coding style to me.
So the question is, is there a better way to iterate over these options and output them?
As #Rost previously mentioned, Visitor pattern is a good choice here. To use it with PO you need to use notifiers for your options in such a way that if option is passed notifier will fill an entry in your set of boost::variant values. The set should be stored separately. After that you could iterate over your set and automatically process actions (i.e. print) on them using boost::apply_visitor.
For visitors, inherit from boost::static_visitor<>
Actually, I made Visitor and generic approach use more broad.
I created a class MyOption that holds description, boost::variant for value and other options like implicit, default and so on. I fill a vector of objects of the type MyOption in the same way like PO do for their options (see boost::po::options_add()) via templates. In the moment of passing std::string() or double() for boosts::variant initialization you fill type of the value and other things like default, implicit.
After that I used Visitor pattern to fill boost::po::options_description container since boost::po needs its own structures to parse input command line. During the filling I set notifyer for each option - if it will be passed boost::po will automatically fill my original object of MyOption.
Next you need to execute po::parse and po::notify. After that you will be able to use already filled std::vector<MyOption*> via Visitor pattern since it holds boost::variant inside.
What is good about all of this - you have to write your option type only once in the code - when filling your std::vector<MyOption*>.
PS. if using this approach you will face a problem of setting notifyer for an option with no value, refer to this topic to get a solution: boost-program-options: notifier for options with no value
PS2. Example of code:
std::vector<MyOptionDef> options;
OptionsEasyAdd(options)
("opt1", double(), "description1")
("opt2", std::string(), "description2")
...
;
po::options_descripton boost_descriptions;
AddDescriptionAndNotifyerForBoostVisitor add_decr_visitor(boost_descriptions);
// here all notifiers will be set automatically for correct work with each options' value type
for_each(options.begin(), options.end(), boost::apply_visitor(add_descr_visitor));
It's a good case to use Visitor pattern. Unfortunately boost::any doesn't support Visitor pattern like boost::variant does. Nevertheless there are some 3rd party approaches.
Another possible idea is to use RTTI: create map of type_info of known types mapped to type handler functor.
Since you are going to just print them out anyway you can grab original string representation when you parse. (likely there are compiler errors in the code, I ripped it out of my codebase and un-typedefed bunch of things)
std::vector<std::string> GetArgumentList(const std::vector<boost::program_options::option>& raw)
{
std::vector<std::string> args;
BOOST_FOREACH(const boost::program_options::option& option, raw)
{
if(option.unregistered) continue; // Skipping unknown options
if(option.value.empty())
args.push_back("--" + option.string_key));
else
{
// this loses order of positional options
BOOST_FOREACH(const std::string& value, option.value)
{
args.push_back("--" + option.string_key));
args.push_back(value);
}
}
}
return args;
}
Usage:
boost::program_options::parsed_options parsed = boost::program_options::command_line_parser( ...
std::vector<std::string> arguments = GetArgumentList(parsed.options);
// print
I was dealing with just this type of problem today. This is an old question, but perhaps this will help people who are looking for an answer.
The method I came up with is to try a bunch of as<...>() and then ignore the exception. It's not terribly pretty, but I got it to work.
In the below code block, vm is a variables_map from boost program_options. vit is an iterator over vm, making it a pair of std::string and boost::program_options::variable_value, the latter being a boost::any. I can print the name of the variable with vit->first, but vit->second isn't so easy to output because it is a boost::any, ie the original type has been lost. Some should be cast as a std::string, some as a double, and so on.
So, to cout the value of the variable, I can use this:
std::cout << vit->first << "=";
try { std::cout << vit->second.as<double>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<int>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<std::string>() << std::endl;
} catch(...) {/* do nothing */ }
try { std::cout << vit->second.as<bool>() << std::endl;
} catch(...) {/* do nothing */ }
I only have 4 types that I use to get information from the command-line/config file, if I added more types, I would have to add more lines. I'll admit that this is a bit ugly.