Related
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!
Currently I am having a function which has two arguments of type enums, the function requires to compare both and do particular task
example:
void set_Test_Status(Tests TestName, Status TestStatus)
{
switch(TestName)
{
case Tests::Test1:
{
switch(TestStatus)
{
case TestStatus::St1:
//Rest of Code
}
}
//Rest of Code
}
}
is it a good programming practice? or is there any alternative method or style of coding that i should be aware of? Thank you!
Edit:
Finally after trial and error, I did this. First i saw the maximum and minimum items in each enums, In my case TestName were 6 and TestStatus had 3. I created 3 functions setStatusRunning(Tests TestName), setStatusSelected(Tests TestName) and setStatusFinished(Tests TestName) and in set_Test_status, using switch(TestName) i check which function should be called and then called the appropriate functions. The reason i had to make set_Test_Status in the first place was to make easy for other classes, since i made set_Test_Status public and the other 3 as private.
It is truly a matter of opinion as having nested switch statements is valid c++ code. Some may not have problems with it while others may argue that it can be confusing.
My advice would be on the lines of this; if the code blocks within the case statements are short such as 1-2 lines and they are fairly easy to read and follow, then there should be nothing wrong with it. However, if the code is quite cumbersome and the nested switch statements spans well over 50 to 100+ lines then I would suggest refining your code and make functions out of them.
Examples:
// should be okay
unsigned int outerSwitch = someValue();
unsigned int innerSwitch = someOtherValue();
switch ( outerSwitch ) {
case 1: {
switch ( innerSwitch ) {
case 1 : {
// 1 or 2 lines okay;
}
case 2 : {
// 1 or 2 lines okay;
}
case 3 : {
// 1 or 2 lines okay;
}
default : {
}
} // inner switch when outer switch case = 1
}
case 2: {
// Same as case 1
}
case 3: {
// Same as case 1
}
default: {
}
} // outer switch
But as you have seen above with just 3 cases to the outer and inner; it gets very long very quickly and I haven't even expanded them all. So this can be frowned upon.
You can have a single switch as others have suggested that calls a specific function to that switch then within that function it has its own switch statement like this:
unsigned int someFuncA( unsigned int someVal ) {
switch ( someVal ) {
case 1 : {
// do this
// return that;
}
case 2: {
// ... etc.
}
} // switch
}
unsigned int someFuncB( int someVal ) {
// similar to someFuncA();
}
unsigned int someFuncC( int someVal ) {
// similar to someFuncA();
}
unsigned int switchValue = someValue();
unsigned int innerValue = someOtherFunction();
unsigned int temp = 0;
switch( switchValue ) {
case 1 : {
temp = someFuncA( innerValue );
// either return temp, break, continue, or fall through
}
case 2 : {
temp = someFuncB( innerValue );
// same as above
case 3 : {
temp = someFuncC( innerValue );
// same as above
}
default : {
// default stuff here
}
} // switch
Comparing the two you will see that the 2nd version is easier to read and less cumbersome than the 1st. Yes the first version is valid legal C++ code, but is frowned upon because of how messy it can easily and quickly get. So where ever you can; turn that code into a function that is designed to do just that one thing.
EDIT
Another possibility is to design specific functions to do a task and as you said that your function takes 2 different enumeration values, you can look up the concept of functions that are designed to take bit flags. You will see this kind of code quite a bit in windows programming as well as OpenGL.
Another option is this: consider that fact you have an outer control switch, and inner control switch. Even if you have multiple cases, each case is independent with a specific unique ID. The same can be said for the inner switch cases. Knowing this you can create an associative mapping of all the statements in a combined matter using std::multimap<unsigned, unsigned> testCases and with this lookup table you can have it in a single statement with independent function calls to each map entry. cppreference : std::multimap
Your map might look like this:
testCases[1][1];
testCases[1][2];
testCases[1][3];
testCases[2][1];
testCases[2][2];
testCases[2][3];
testCases[3][1];
testCases[3][2];
testCases[3][3];
Where each index of the map is the logic or calculation you want to perform.
It can be quite confusing for someone reading the code-- indentation helps, but it can still be difficult to follow where the case and switch statements start and end. Most IDEs have support for finding a matching brace, but finding a matching break isn't generally a thing, so it can be difficult to even see where a case statement ends. (And technically case doesn't define scope whereas braces do, so it doesn't even have an end.)
If you get misaligned braces or accidentally mismatch where they should be, you can have odd things happen. Languages like Ada try to prevent that with strongly typed English-language specifiers.
If you are doing a lot of sub-switches, I would put them into another function and call it with the information it needs, then you could do a switch statement inside the method which is more modular, separate scope and clear what is going on.
A good practice to keep code concise is to do only one thing in a function. Using a switch already is a smell that your function is going to do different things. It all depend of your specific case.
One thing to look at is: is it coherent to manage all these cases in one class. Should you have one class per possibility, with an interface forcing to implement a function, instead of doing all the possibilities in a switch case.
In case you want to keep the switch, a good practice would be to not put code in it other than the switch. Each case just calls a function. This will already make stuff more readable.
Finally, are you using all the cases? If no, you code could be more clear by just implementing the pairs of values that you need:
if(TestName == Tests::Test1 && TestStatus == TestStatus::St1)
{
doThing();
}
To summarize:
This might be a smell that your code needs to be split in more classes to have only one responsibility per class (too many if and/or too many switches ar a sign of that). If you are sure that you need a switch, keep it as simple and clear as possible
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.
In a situation where a variable could have two different values, and you do something if its one, something differnent if its the other, would you just do:
if(myVariable == FIRST_POSSIBLE_VALUE) { ... }
else { ... }
or would you do:
if(myVariable == FIRST_POSSIBLE_VALUE) { ... }
else if (myVariable == SECOND_POSSIBLE_VALUE) { ... }
for clarity, in a situation where a reader wouldn't necessarily be able to tell that they do the same thing (but the else if does a "needless" expression)?
So what would you do?
Thanks!
EDIT: There is actually about a lot more different options for something like this: ternary operator, if-else, if-elseif, if-elseif-else, -if-else(with assert), switch. Each one has its place, but its hard to decide..
I always prefer just plain else when there is no other possible state of the variable(ie, checking for null and all that). I may add a comment saying what the variable is if it isn't the first conditional, but that is only in cases where its like
if(color==red){
....
}else{ //our theme only allows for red and yellow, so the color must be yellow.
....
}
Also, this saves some time for the processor cause it won't have to check a useless variable(or worse in OOP, where checking that variable can take quite a few dereferences, function calls, and memory reads)
I never do something like
if(file.is_open==1){
....
}else if(file.is_open==0){
....
}
as is_open is a boolean, it is pointless to specify that because the only option left is 0, also this can save a little bit of typing when you must refactor your code to use is_open() instead, as now you only must change one line instead of two.
and 'else if' statements I think should be turned to switches if there is more than 1 'else if', unless of course the language makes it impossible(such as how C can't handle strings in switches)
Else is a default. Meaning that there are either a large number of possibilities for the data, or that it is unexpected data.
I go by the basic rule: If there is a parameter that can be met, use else if, and if there isn't, use else. I normally use else's for errors.
I only use the if-else for boolean checks, that means that if the expression doesn't match there only can be the else. Or i want to take everything with the else: think of it like default.
If you want to check enumeration or something, you should try check this via switch statement, if possible in your language.
In Java it's not possible to use a switch for Strings. So you could use something like this:
if(string.equals("foo")) {
// first case
} else if(string.equals("bar")) {
// second case
} else {
throw IllegalArgumentException(" ... ");
// or log it
}
If you're not sure that your check can't be extended, you should if you can provide an default way.
Isn't this what assert was made for?
if (condition1) { ... }
else { assert(condition2); }
This can be expanded for three-state logic, too.
if (condition1) { ... }
elsif (condition2) { ... }
else { assert(condition3); }
Using assert makes your code readable, easy to maintain, and clear. That being said, asserts and comments are almost interchangeable.
Sometimes the condition of the else statement is very obvious. For example
if(user.IsNew) { } else { /*in this case user.IsNew != true*/ }
But in some other cases the else isn't that obvious and it is better to clarify the else condition. This is also more future proof in case some other possible conditions are added.
Furthermore you are able to insert an exception in the (last) else to inform about unimplemented cases. This can be very useful when the for example backend and frontend are separated and somebody adds a new value to an enumerator (or when using text keys a new key is introduced) you will receive an error when the new value is first used. When not using if else if you won't see what happened and that could make debugging pretty hard.
if(user.SelectedStyle == Styles.Red) {
} else if(user.SelectedStyle == Styles.Basic) {
} else {
throw new Exception("Not implemented");
}
In the case above a new Style (for example Style.Blue) will cause your application to throw an exception.
It's really a matter of style and your own mental view of the world. The glass is BOTH half empty and half full, but you can get the darnedest arguments going about it.
If the boolean tests are all of the same type, a switch statement is best.
If not, I'd recommend leaving out the additional test but insert a comment about the operational meaning of falling through into that last statement. See Gertjan's comment, above.
When your input can be clearly separate into distinct cases, I feel it is mostly nicer to explicitly state what those cases are, for example if you are expecting 'n' to be a number between 0 and 100, and you have 3 cases:
if (n >= 0 && n < 30) {
case1();
} else if (n >=30 && n < 70) {
case2();
} else if (n >=70 && n < 100) {
case3();
}
in some situations the 'else' case is good for error checking
} else {
error("n should be between 0 and 100");
}
if your data is checked for erroneous values earlier, then there may be a case to use else for the final case, to provide a small performance improvement in languages like C:
} else { // (n >= 70 && n < 100)
case3();
}
but this is only necessary due to some languages inability to express the domain of a function, in languages where the domain can be expressed clearly, the optimiser should add this performance benefit for you, allowing you to be specific in your code, and making it easier to add more cases later
... of course this is an art, not a science, and in some cases you can't follow the hard-and-fast rule, I frequently find myself writing code like:
if (p == NULL) {
doSomething();
} else {
doSomethingElse();
}
...justified by the fact that is very obvious and implicit from the first if condition what the else is used for.
else was invented and is used for good reason. Where you use it should be dictated by the logic that you trying to achieve, not a contrived sense of style.
Some argue that it is more self-documenting by using explicit conditions in an else if; however, this may lead to gaps in logic with default or catch all conditions.
Also, some say that it is easier to modify in the future. This argument is bunk. Using design patterns and writing modular code is something that is easier to modify in the future, writing one line shouldn't qualify for these kinds of statements.
It depends on the situation. Do you only want to take action if certain criteria are met, or is there a special case for one value and another set of logic for any other value?