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.
Related
I want to use the nlohmann JSON library in order to read options from a JSON file. Specifying options is optional, as reflected in the constructor in my code example. I'm assuming the JSON structure is an object in its root.
Unfortunately, I'm unable to use these options, because it is unclear to me how I can force the JSON structure to be an object. What is worse, merely initializing a member variable with a JSON object {} (magically?) turns it into an array [{}].
#include <cstdlib>
#include <iostream>
#include <nlohmann/json.hpp>
class Example {
public:
explicit Example(const nlohmann::json& options = nlohmann::json::object())
: m_options{options}
{
std::clog << options << '\n' << m_options << '\n';
}
private:
nlohmann::json m_options;
};
auto main() -> int
{
Example x;
Example y{nlohmann::json::object()};
return EXIT_SUCCESS;
}
This results in the following output. Notice that we have to perform some ceremony in order to use an empty object as the default value (= empty settings), with = nlohmann::json::object(). Also notice that the settings object changes its type as soon as we initialize the member value (!):
{}
[{}]
My use use case is quite straightforward, but I'm unable to extract settings, unless I explicitly check whether the settings are an array or an object.
Another thing that worries me is that incorrect code compiles without warning, e.g., code in which I use x.value("y") on a JSON array x containing an object with key "y". Only at run time do I discover that I should have done x.at(0).value("y") instead.
In brief, the whole situation is quite surprising to me. I must be missing something / I must be using this library in an unintended way?
nlohman is a very "modern" library, it uses a lot of features in C++. And that might make it harder to read and understand the code. But it is very flexible.
This short introduction might help
Introduction to nlohmann json
Parse text to json object is done like
constexpr std::string_view stringJson = R"({"k1": "v1"})";
nlohmann::json j = nlohmann::json::parse( stringJson.begin(), stringJson.end() );
I have 3 structs : Student, Citizen, Employee. I want user to be able to choose what struct they want to work with (std::vector of structs, actually). Since there's no way to define type at runtime, I created all 3 vectors, but will use only one of them (depending on the user's choice), others will stay empty:
std::vector<Student> container_student;
std::vector<Citizen> container_citizen;
std::vector<Employee> container_employee;
auto containers = make_tuple(container_student, container_citizen, container_employee);
std::cout << "Enter:\n0 to operate \"Student\" struct\n1 to operate \"Citizen\" struct\n2 to operate \"Employee\" struct\n";
std::cin >> container_type;
auto container = std::get<container_type>(containers);
But I get No matching function for call to 'get', even though container_type is an int and containers is a tuple.
Edit: understandable, auto can't make magic and I still try to make container's type to depend on runtime. But even if I try to use std::get<container_type>(containers) (probably define would help) instead of container in functions etc., I get the same error, which is not understandable.
Unfortunately, what you're proposing isn't possible in C++. The C++ typing and template system works at compile-time, where information read in from the user isn't available. As a result, anything passed into a template's angle braces needs to be determinable at compile-time. In your case, the number the user enters, indicating which option they want to select, is only knowable at runtime.
There are some routes you could take to achieve the same result, though. For example, one option would be to do something like this:
if (container_type == 0) {
auto container = std::get<0>(containers);
/* ... */
} else if (container_type == 1) {
auto container = std::get<1>(containers);
/* ... */
} /* etc */
Here, all the template angle braces are worked out at compile-time. (Then again, if this is what you're going to be doing, you wouldn't need the tuple at all. ^_^)
Another option would be to use templates, like this:
template <typename T> void doSomething(std::vector<T>& container) {
/* Put your code here */
}
/* Then, back in main... */
if (container_type == 0) {
doSomething(container_student);
} else if (container_type == 1) {
doSomething(container_citizen);
} /* etc */
This still requires you to insert some code to map from integer types to the functions you want to call, but it leaves you the freedom to have a container variable (the one in doSomething) that you can treat generically at that point.
It's basically the Fundamental Theorem of Software Engineering in action - all problems can be solved by adding another layer of indirection. :-)
Hope this helps!
In go a common way to do error handling and still return a value is to use tuples.
I was wondering if doing the same in C++ using std::tie would be a good idea when exceptions are not applicable.
like
std::tie(errorcode, data) = loadData();
if(errorcode)
...//error handling
Are there any downsides to doing so (performance or otherwise)? I suppose with return value optimization it doesn't really make a difference but maybe I'm wrong.
One potential problematic case that I could see is the use in a cross-compiler API but that's not specific to this use.
The current way I do this is
errorcode = loadData(&data);
if(errorcode)
...//error handling
but that allows to pass in a value for data.
The errorcode itself is something that is already defined and that I can't change.
Edit: I'm using/have to use C++11
Sometimes output parameters are very handy. Suppose that loadData returns std::vector<T> and is called in a loop:
std::pair<ErrorCode, std::vector<T>> loadData();
for (...) {
ErrorCode errorcode;
std::vector<T> data;
std::tie(errorcode, data) = loadData();
}
In this case loadData will have to allocate memory on each iteration. However, if you pass data as the output parameter, previously allocated space can be reused:
ErrorCode loadData(std::vector<T>&);
std::vector<T> data;
for (...) {
ErrorCode errorcode = loadData(data);
}
If the above is of no concern, then you might want to take a look at expected<T, E>. It represents either
a value of type T, the expected value type; or
a value of type E, an error type used when an unexpected outcome occurred.
With expected, loadData() signature might look like:
expected<Data, ErrorCode> loadData();
C++11 implementation is available: https://github.com/TartanLlama/expected
There are multiple competing strategies for error handling. I will not go into it, as it is beyond the scope of the question, but error handling by return error codes is only one option. Consider alternatives like std::optional or exceptions, which are both common in C++, but not in Go.
If you have a function that is intended to return a Go-style error code plus value, then your std::tie solution is perfectly fine in C++11 or C+14, although in C++17, you would prefer structured bindings instead.
Are there any downsides to doing so (performance or otherwise)?
Yes. With tie, a copy or move of the returned values is required that would not be required if you avoid tie:
auto result = loadData();
if (std::get<0>(result))
...//error handling
Of course, if you would later copy or move the data somewhere else anyway, like in
data = std::move(std::get<1>(result));
then use tie because it is shorter.
I have a function that returns a custom class structure, but how should I handle the cases where I wish to inform the user that the function has failed, as in return false.
My function looks something like this:
Cell CSV::Find(std::string segment) {
Cell result;
// Search code here.
return result;
}
So when succesful, it returns the proper result, but how should I handle the case when it could fail?
I thought about adding a boolean method inside Cell to check what ever Cell.data is empty or not (Cell.IsEmpty()). But am I thinking this issue in a way too complicated way?
There are three general approaches:
Use exceptions. This is what's in Bathsheba's answer.
Return std::optional<Cell> (or some other type which may or may not hold an actual Cell).
Return bool, and add a Cell & parameter.
Which of these is best depends on how you intend this function to be used. If the primary use case is passing a valid segment, then by all means use exceptions.
If part of the design of this function is that it can be used to tell if a segment is valid, exceptions aren't appropriate, and my preferred choice would be std::optional<Cell>. This may not be available on your standard library implementation yet (it's a C++17 feature); if not, boost::optional<Cell> may be useful (as mentioned in Richard Hodges's answer).
In the comments, instead of std::optional<Cell>, user You suggested expected<Cell, error> (not standard C++, but proposed for a future standard, and implementable outside of the std namespace until then). This may be a good option to add some indication on why no Cell could be found for the segment parameter passed in, if there are multiple possible reasons.
The third option I include mainly for completeness. I do not recommend it. It's a popular and generally good pattern in other languages.
Is this function a query, which could validly not find the cell, or is it an imperative, where the cell is expected to be found?
If the former, return an optional (or nullable pointer to) the cell.
If the latter, throw an exception if not found.
Former:
boost::optional<Cell> CSV::Find(std::string segment) {
boost::optional<Cell> result;
// Search code here.
return result;
}
Latter:
as you have it.
And of course there is the c++17 variant-based approach:
#include <variant>
#include <string>
struct CellNotFound {};
struct Cell {};
using CellFindResult = std::variant<CellNotFound, Cell>;
CellFindResult Find(std::string segment) {
CellFindResult result { CellNotFound {} };
// Search code here.
return result;
}
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
void cellsAndStuff()
{
std::visit(overloaded
{
[&](CellNotFound)
{
// the not-found code
},
[&](Cell c)
{
// code on cell found
}
}, Find("foo"));
}
The C++ way of dealing with abject failures is to define an exception class of the form:
struct CSVException : std::exception{};
In your function you then throw one of those in the failure branch:
Cell CSV::Find(std::string segment) {
Cell result;
// Search code here.
if (fail) throw CSVException();
return result;
}
You then handle the fail case with a try catch block at the calling site.
If however the "fail" branch is normal behaviour (subjective indeed but only you can be the judge of normality), then do indeed imbue some kind of failure indicator inside Cell, or perhaps even change the return type to std::optional<Cell>.
If you can use C++17, another approach would be to use an std::optional type as your return value. That's a wrapper that may or may not contain a value. The caller can then check whether your function actually returned a value and handle the case where it didn't.
std::optional<Cell> CSV::Find(std::string segment) {
Cell result;
// Search code here.
return result;
}
void clientCode() {
auto cell = CSV::Find("foo");
if (cell)
// do stuff when found
else
// handle not found
}
A further option is using multiple return values:
std::pair<Cell, bool> CSV::Find(std::string segment) {
Cell result;
// Search code here.
return {result, found};
}
// ...
auto cell = CSV::Find("foo");
if (cell->second)
// do stuff with cell->first
The boolean flag says whether the requested Cell was found or not.
PROs
well known approach (e.g. std::map::insert);
quite direct: value and success indicator are return values of the function.
CONs
obscureness of first and second which requires to always remember the relative positions of values within the pairs. C++17 structured bindings / if statement with initializer partially resolve this issue:
if (auto [result, found] = CSV::Find("foo"); found)
// do stuff with `result`
possible loss of safety (the calling code has to check if there is a result value, before using it).
Details
Returning multiple values from functions in C++
C++ Error Handling - downside of using std::pair or std::tuple for returning error codes and function returns
For parsing, it is generally better to avoid std::string and instead use std::string_view; if C++17 is not available, minimally functional versions can be whipped up easily enough.
Furthermore, it is also important to track not only what was parsed but also the remainder.
There are two possibilities to track the remainder:
taking a mutable argument (by reference),
returning the remainder.
I personally prefer the latter, as in case of errors it guarantees that the caller has in its hands a unmodified value which is useful for error-reporting.
Then, you need to examine what potential errors can occur, and what recovery mechanisms you wish for. This will inform the design.
For example, if you wish to be able to parse ill-formed CSV documents, then it is reasonable that Cell be able to represent ill-formed CSV cells, in which case the interface is rather simple:
std::pair<Cell, std::string_view> consume_cell(std::string_view input) noexcept;
Where the function always advances and the Cell may contain either a proper cell, or an ill-formed one.
On the other hand, if you only wish to support well-formed CSV documents, then it is reasonable to signal errors via exceptions and that Cell only be able to hold actual cells:
std::pair<std::optional<Cell>, std::string_view> consume_cell(...);
And finally, you need to think about how to signal end of row conditions. It may a simple marker on Cell, though at this point I personally prefer to create an iterator as it presents a more natural interface since a row is a range of Cell.
The C++ interface for iterators is a bit clunky (as you need an "end", and the end is unknown before parsing), however I recommend sticking to it to be able to use the iterator with for loops. If you wish to depart from it, though, at least make it work easily with while, such as std::optional<Cell> cell; while ((cell = row.next())) { ... }.
I have looked into this, but it's not what I wanted: Convert string to variable name or variable type
I have code that reads an ini file, stores data in a QHash table, and checks the values of the hash key, (see below) if a value is "1" it's added to World.
Code Examples:
World theWorld;
AgentMove AgentMovement(&theWorld);
if(rules.value("AgentMovement") == "1")
theWorld.addRule(&AgentMovement);
INI file:
AgentMovement=1
What I want to do is, dynamically read from the INI file and set a reference to a hard coded variable.
for(int j = 0; j < ck.size(); j++)
if(rules.value(ck[j]) == "1")
theWorld.addRule("&" + ck[j]);
^
= &AgentMovement
How would you make a string into a reference as noted above?
This is a common theme in programming: A value which can only be one of a set (could be an enum, one of a finite set of ints, or a set of possible string values, or even a number of buttons in a GUI) is used as a criteria to perform some kind of action. The simplistic approach is to use a switch (for atomic types) or an if/else chain for complex types. That is what you are currently doing, and there is nothing wrong with it as such:
if(rules.value(ck[j]) == "1") theWorld.addRule(&AgentMovement);
else if(rules.value(ck[j]) == "2") theWorld.addRule(&AgentEat);
else if(rules.value(ck[j]) == "3") theWorld.addRule(&AgentSleep);
// etc.
else error("internal error: weird rules value %s\n", rules.value(ck[j]));
The main advantages of this pattern are in my experience that it is crystal clear: anybody, including you in a year, understands immediately what's going on and can see immediately which criteria leads to which action. It is also trivial to debug which can be a surprising advantage: You can break at a specific action, and only at that action.
The main disadvantage is maintainability. If the same criteria (enum or whatever) is used to switch between different things in various places, all these places have to be maintained, for example when a new enum value is added. An action may come with a sound, an icon, a state change, a log message, and so on. If these do not happen at the same time (in the same switch), you'll end up switching multiple times over the action enum (or if/then/else over the string values). In that case it's better to bundle all information connected to an action in a data structure and put the structures in a map/hash table with the actions as keys. All the switches collapse to single calls. The compile-time initialization of such a map could look like this:
struct ActionDataT { Rule rule; Icon icon; Sound sound; };
map<string, AcionDataT> actionMap
= {
{"1", {AgentMovement, moveIcon, moveSound} }
{"2", {AgentEat, eatIcon, eatSound } } ,
//
};
The usage would be like
for(int j = 0; j < ck.size(); j++)
theWorld.addRule(actionMap[rules.value(ck[j])].rule);
And elsewhere, for example:
if(actionFinished(action)) removeIcon(actionMap[action].icon);
This is fairly elegant. It demonstrates two principles of software design: 1. "All problems in computer science can be solved by another level of indirection" (David Wheeler), and 2. There is often a choice between more data or more code. The simplistic approach is code-oriented, the map approach is data oriented.
The data-centrist approach is indispensable if switches occur in more than one situation, because coding them out each time would be a maintenance nightmare.
Note that with the data-centrist approach none of the places where an action is used has to be touched when a new action is added. This is essential. The mechanism resembles (in principle and implementation, actually) the call of a virtual member function. The calling code doesn't know and isn't really interested in what is actually done. Responsibility is transferred to the object. The calling code may perform actions later in the life cycle of a program which didn't exist when it was written. By contrast, compare it to a program with many explicit switches where every single use must be examined when an action is added.
The indirection involved in the data-centrist approach is its disadvantage though, and the only problem which cannot be solved by another level of indirection, as Wheeler remarked. The code becomes more abstract and hence less obvious and harder to debug.
You have to provide the mapping from the names to the object by yourself. I would wrap it into a class, something like this:
template <typename T>
struct ObjectMap {
void addObject(std::string name,T* obj){
m[name] = obj;
}
T& getRef(std::string name) const {
auto x = m.find(name);
if (x != m.end() ) { return *(x->second);}
else { return dummy; }
}
private:
std::map<std::string,T*> m;
T dummy;
}
The problem with this approach is that you have to decide what to do if an object is requested that is actually not in the map. A reference always has to reference something (in contrast to a pointer that can be 0). I decided to return the reference to a dummy object. However, you might want to consider to use pointers instead of references. Another option might be to throw an error in case the object is not in the map.