This is probably a really obvious question but I want to be sure about it before going on with my development.
I have a templated class something like:
template<TypeA var1, TypeB var2>
class myClass
{
//Attributes
...
//Methods
...
void checkHit(vector<Real>* path, vector<bool>* active)
{
for(int i = 0; i < N; i++)
{
//Some process
bool hit = ((var1 == Up) || (var1 == Down));
}
//...
bool flag = ((var2 == Left) || (var2 == Right));
}
}
If I create and object like
myClass obj<Up, Right>(...);
When executing the method
obj.checkHit( ... );
Will the program just check for bool hit = ((var1 == Up) and (var2 == Right) ?? In other words, will the compiler throw away the code that doesn't has to do with the template-parameters passed? What I mean is if the resulting code after compiling will be something like
template<TypeA var1, TypeB var2>
class myClass
{
//Attributes
...
//Methods
...
void checkHit(vector<Real>* path, vector<bool>* active)
{
for(int i = 0; i < N; i++)
{
//Some process
bool hit = ((var1 == Up)); //Like if I have never put "|| (var1 == Down));"
}
//...
bool flag = ((var2 == Right));
}
}
Hope the example is clear enough, I just simplified (a lot) the real code but it should be roughly equivalent. If it isn't clear just tell and I will gladly improve it.
I'm assuming your TypeA and TypeB are either enumerations or some sort of class/struct with those values defined?
That being the case, the compiler isn't going to "throw out" code here. Your conditional checks to see what the template parameters are, so if they don't match what is in the conditionals, you'll end up with a call that would basically do this:
bool hit = (0 == 1 || 1 == 2);
Depending on your optimization settings, the compiler may realize that this will always be false and just set it to false (also assuming you do something useful in the function so the compiler doesn't just turn it into a noop).
You also should pass your vectors by reference (or constant reference), and I would avoid using vector<bool>.
The example is not really clear enough, there is no "code that doesn't has to do with the template-parameters passed" because nothing depends on hit or flag, so a decent optimizer would turn checkHit into a completely empty function!
The compiler can evaluate the ((var1 == TypeA::Up) || (var2 == TypeB::Down)) condition at compile-time and a decent optimizing compiler will propagate the result of that condition to the rest of the function, removing any dead code that will never be run due due to the value of that condition.
Also, do you really want to pass these arguments by value?
void checkHit(vector<Real> path, vector<bool> active)
the Program will NOT throw away any part of the code.Template classes are only used to generalize the usage of a class .once a typeA and Type B are chosen they will all be taken as the Type A and Type B throughout the code and the rest of the code will execute in the normal way that it would without any templates
Related
I am developing a chess engine and am working on move generation. For example, here is my function for generating moves for the black knight:
/** Pseudolegal moves don't take check into account. */
std::vector<uint8_t>
generate_pseudolegal_bknight_moves(std::shared_ptr<Position> position,
uint8_t square) {
assert(VALID_SQUARE(square));
assert(position->mailbox[square] == B_KNIGHT);
uint8_t candidates[8] = {
NEXT_RANK(PREV_FILE(PREV_FILE(square))),
NEXT_RANK(NEXT_RANK(PREV_FILE(square))),
PREV_RANK(PREV_FILE(PREV_FILE(square))),
PREV_RANK(PREV_RANK(PREV_FILE(square))),
NEXT_RANK(NEXT_FILE(NEXT_FILE(square))),
NEXT_RANK(NEXT_RANK(NEXT_FILE(square))),
PREV_RANK(NEXT_FILE(NEXT_FILE(square))),
PREV_RANK(PREV_RANK(NEXT_FILE(square))),
};
std::vector<uint8_t> moves;
for (int i = 0; i < 8; i++) {
uint8_t candidate = candidates[i];
uint8_t piece = position->mailbox[candidate];
if (VALID_SQUARE(candidate) && (!IS_BLACK_PIECE(piece))) {
moves.push_back(candidate);
}
}
return moves;
}
The function for generating white knight moves is very similar, with only two terms (macros) changing:
B_KNIGHT -> W_KNIGHT, and IS_BLACK_PIECE -> IS_WHITE_PIECE.
I'd prefer not to essentially duplicate the move generation function for every piece, but have been doing it this way so far because it has the smallest runtime overhead.
I could include bool is_white or something in the args and switch terms with a ternary is_white ? W_KNIGHT : B_KNIGHT, but the conditional would add an overhead during runtime that wasn't there previously, and it doesn't seem that elegant. I was wondering if there is some compile-time feature that would help me have one function definition.
I suppose I also could use inline functions to try and reduce the amount of duplicated code, but I was wondering if there was any alternative better than that.
If you don't want overhead you can use a template parameter and if constexpr:
enum class Color { WHITE, BLACK };
template <Color C> std::vector<uint8_t>
generate_pseudolegal_knight_moves(std::shared_ptr<Position> position,
uint8_t square) {
...
if constexpr (C == Color::WHITE) {
assert(position->mailbox[square] == W_KNIGHT);
} else {
assert(position->mailbox[square] == B_KNIGHT);
}
...
}
// Call
auto moves = generate_pseudolegal_knight_moves<Color::WHITE>(...);
The standard guarantees the condition will be evaluated on compile time, and the false branch will be discarded.
I have an enum with one undefined and two user values:
class enum E
{
UNDEFINED,
VALUE1,
VALUE2
};
I want to add VALUE3 but I'm worried there's a lot of code like:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
and:
something = (val == E::VALUE1) ? a : b; // last part assumes E::VALUE2
I like that compilers warn against switch statements not handling all enumerations and wondered if there is anything similar to show all instances of the above?
I'm concerned I won't find and update all instances of the above.
Compiler is Clang
Enums are not restricted to the values you give names to. From cppreference (formatting is mine):
An enumeration is a distinct type whose value is restricted to a range of values (see below for details),
which may include several explicitly named constants ("enumerators"). The values of the constants are values of an integral type known as the underlying type of the enumeration.
The "below details" explain how the enums underlying type is determined. Out of this range we (usually) give names only to some values as in:
enum foo {A,B,C};
int main() {
foo x = static_cast<foo>(42);
}
This code is completely fine. x has an underlying value of 42. There is no name for the value but this doesn't really matter... unless you assume that it does.
That wrong assumption is made by this code:
assert(val != E::UNDEFINED);
if(val == E::VALUE1)
{
}
else
{
// Without an assert this wrongly assumes E::VALUE2
}
This code is what needs to be fixed (independent of whether you add a new named constant to the enum or not).
Now for a more serious trial to answer the question...
There is no way to get a warning when a chain of if-else does not cover all enum values. What you can do is to turn all if-else uses of the enum into errors. Consider what actually happens here:
if (x == E::VALUE1) do_something();
switch(x) {
case E::VALUE1 : return 1;
}
In the if statement we call operator==(foo,foo); its return value either is a bool or is implicitly converted to one. With the switch none of this is needed. We can make use of this to turn if-else usages of the enum into errors. Bear with me I will explain in two steps. First lets create a compiler error for if( x == E::VALUE1):
class helper {
operator bool(){ return false;}
};
helper operator==(E,E){
return {};
}
Now if (x == E::VALUE1) calls helper operator==(E,E), thats fine. Then the result is converted to bool, and that fails because the conversion is private. Using the enum in a switch is still ok and you can rely on compiler errors / warnings. The basic idea is just to have something that only fails to compile when called (in the wrong/right context). (Live Demo).
The drawback is that also all other used of operator== are broken. We can fix them by modifying the helper and the call sites:
#include <type_traits>
enum E {VALUE1};
struct helper {
bool value;
private:
operator bool(){ return false;}
};
helper operator==(E a,E b){
return {
static_cast<std::underlying_type_t<E>>(a) == static_cast<std::underlying_type_t<E>>(b)
};
}
int main() {
E x{VALUE1};
//if ( x== E::VALUE1); // ERROR
bool is_same = (x == E::VALUE1).value;
switch(x) {
case E::VALUE1 : return 1;
}
}
Yes it is a major inconvenience to have to write .value, but in this way you can turn all uses of the enum in ifs into errors while everything else will still compile. Also note that you have to make sure to cover all cases you want to catch (eg !=,<, etc).
Sometimes, an if statement can be rather complicated or long, so for the sake of readability it is better to extract complicated calls before the if.
e.g. this:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
into this
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
(provided example is not that bad, it's just for illustration... imagine other calls with multiple arguments, etc.)
But with this extraction I lost the short circuit evaluation (SCE).
Do I really lose SCE every time? Is there some scenario where the compiler is allowed to "optimize it" and still provide SCE?
Are there ways of keeping the improved readability of the second snippet without losing SCE?
One natural solution would look like this:
bool b1 = SomeCondition();
bool b2 = b1 || SomeOtherCondition();
bool b3 = b2 || SomeThirdCondition();
// any other condition
bool bn = bn_1 || SomeFinalCondition();
if (bn)
{
// do stuff
}
This has the benefits of being easy to understand, being applicable to all cases and having short circuit behaviour.
This was my initial solution: A good pattern in method calls and for-loop bodies is the following:
if (!SomeComplicatedFunctionCall())
return; // or continue
if (!SomeOtherComplicatedFunctionCall())
return; // or continue
// do stuff
One gets the same nice performance benefits of shortcircuit evaluation, but the code looks more readable.
I tend to break down conditions onto multiple lines, i.e.:
if( SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()
) {
Even when dealing with multiple operators (&&) you just need to advance indention with each pair of brackets. SCE still kicks in - no need to use variables. Writing code this way made it much more readible to me for years already. More complex example:
if( one()
||( two()> 1337
&&( three()== 'foo'
|| four()
)
)
|| five()!= 3.1415
) {
If you have long chains of conditions and what to keep some of the short-circuiting, then you could use temporary variables to combine multiple conditions. Taking your example it would be possible to do e.g.
bool b = SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
if (b && some_other_expression) { ... }
If you have a C++11 capable compiler you could use lambda expressions to combine expressions into functions, similar to the above:
auto e = []()
{
return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
};
if (e() && some_other_expression) { ... }
1) Yes, you no longer have SCE. Otherwise, you would have that
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
works one way or the other depending if there is an if statement later. Way too complex.
2) This is opinion based, but for reasonably complex expressions you can do:
if (SomeComplicatedFunctionCall()
|| OtherComplicatedFunctionCall()) {
If it ways too complex, the obvious solution is to create a function that evaluates the expression and call it.
You can also use:
bool b = someComplicatedStuff();
b = b || otherComplicatedStuff(); // it has to be: b = b || ...; b |= ...; is bitwise OR and SCE is not working then
and SCE will work.
But it's not much more readable than for example:
if (
someComplicatedStuff()
||
otherComplicatedStuff()
)
1) Do I really lose SCE every time? Is compiler is some scenario allowed to "optimize it" and still provide SCE?
I don't think such optimization is allowed; especially OtherComplicatedFunctionCall() might have some side effects.
2) What is the best practice in such situation? Is it only possibility (when I want SCE) to have all I need directly inside if and "just format it to be as readable as possible" ?
I prefer to refactor it into one function or one variable with a descriptive name; which will preserve both short circuit evaluation and readability:
bool getSomeResult() {
return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
}
...
if (getSomeResult())
{
//do stuff
}
And as we implement getSomeResult() based on SomeComplicatedFunctionCall() and OtherComplicatedFunctionCall(), we could decompose them recursively if they're still complicated.
1) Do I really lose SCE every time? Is compiler is some scenario
allowed to "optimize it" and still provide SCE?
No you don't, but it's applied differently:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
Here, the compiler won't even run OtherComplicatedFunctionCall() if SomeComplicatedFunctionCall() returns true.
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
Here, both functions will run because they have to be stored into b1 and b2. Ff b1 == true then b2 won't be evaluated (SCE). But OtherComplicatedFunctionCall() has been run already.
If b2 is used nowhere else the compiler might be smart enough to inline the function call inside the if if the function has no observable side-effects.
2) What is the best practice in such situation? Is it only possibility
(when I want SCE) to have all I need directly inside if and "just
format it to be as readable as possible" ?
That depends.
Do you need OtherComplicatedFunctionCall() to run because of side-effects or the performance hit of the function is minimal then you should use the second approach for readability. Otherwise, stick to SCE through the first approach.
Another possibility that short circuits and has the conditions in one place:
bool (* conditions [])()= {&a, &b, ...}; // list of conditions
bool conditionsHold = true;
for(int i= 0; i < sizeOf(conditions); i ++){
if (!conditions[i]()){;
conditionsHold = false;
break;
}
}
//conditionsHold is true if all conditions were met, otherwise false
You could put the loop into a function and let the function accept a list of conditions and output a boolean value.
Very strange: you are talking about readability when nobody mentions the usage of comment within the code:
if (somecomplicated_function() || // let me explain what this function does
someother_function()) // this function does something else
...
In top of that, I always preceed my functions with some comments, about the function itself, about its input and output, and sometimes I put an example, as you can see here:
/*---------------------------*/
/*! interpolates between values
* #param[in] X_axis : contains X-values
* #param[in] Y_axis : contains Y-values
* #param[in] value : X-value, input to the interpolation process
* #return[out] : the interpolated value
* #example : interpolate([2,0],[3,2],2.4) -> 0.8
*/
int interpolate(std::vector<int>& X_axis, std::vector<int>& Y_axis, int value)
Obviously the formatting to use for your comments may depend on your development environment (Visual studio, JavaDoc under Eclipse, ...)
As far as SCE is concerned, I assume by this you mean the following:
bool b1;
b1 = somecomplicated_function(); // let me explain what this function does
bool b2 = false;
if (!b1) { // SCE : if first function call is already true,
// no need to spend resources executing second function.
b2 = someother_function(); // this function does something else
}
if (b1 || b2) {
...
}
Readability is necessary if you work in a company and your code will be read by someone else. If you write a program for yourself, it is up to you if you want to sacrifice performance for the sake of comprehensible code.
This question already has answers here:
GOTO still considered harmful? [closed]
(49 answers)
Closed 8 years ago.
I had a code review recently and a debate began. Much of my code looks like this:
for (i = 1; i <= 3; i++)
{
DoubleValue = tODBCX->getDouble(KeyFieldCount + i, IsNULL, IsSuccess);
if (IsNULL)
{
LoggerDrillHole::LogToDB(LOG_ERROR, L"Survey depth, dip and azimuth values can not be NULL.", __FUNCTIONW__);
IsSuccess = false;
goto EXIT;
}
else
{
if (i == 1)
Depth = DoubleValue;
else if(i == 2)
DipDegrees = DoubleValue;
else if (i == 3)
AzimuthDegrees = DoubleValue;
}
}
The contentious goto statement sparked debate. This code is contained within a function that begins life by initializing a local boolean variable IsSuccess = true and the function finally returns IsSuccess. The EXIT strategy looks after essential tidy up code;
EXIT:
tODBCX->Close();
if (Key != 0) free(Key);
Key = 0;
if (PriorKey != 0) free(PriorKey);
PriorKey = 0;
return IsSuccess;
There were several such goto EXIT statements adjacent to setting IsSuccess = false and logging to database and so on. The comment was made that this is disruptive to the flow of the code. One should instead use a do loop (infinite loop) and break out of that loop and then process all of the required instead of using the goto statement.
I intensely disliked the infinite loop strategy, but I could get used to it if it truly improves the readability. Is there a better way?
I wanted to mark this as a duplicate of this question. Still, it is not exactly the same, even though the solution is the same:
In C++, the best solution is to use RAII and transactional code. In C, the best solution is to use goto, with following a few rules (only use for return/cleanup, do not use goto to simulate loops, etc).
See my answer in the question mentioned above (basically, the solution is to use RAII and transactional code); this will eliminate completely the need for a goto cleanup/error handling block.
There is nothing wrong with using goto here. This is one of the few situations where it is the cleanest solution. (Another example would be breaking out of an inner loop.)
Using a do { ... } while (false) loop is an artificial solution that actually reduces the readability of the code.
In C, consider breaking your code into two functions... an outer function that does common intialisation and passes down the variables the inner function needs, such that the inner function can simply return the success status knowing the outer function will clean up.
In C++ it's usually a good idea to use scope guards so destructors ensure proper clean up. Consider your:
tODBCX->Close();
If tODBCX needs to live longer than the function call - so a Close() in the destructor doesn't help - then create a helper:
struct Odbc_Access_Guard
{
Odbc_Access_Guard(ODBC& o) : odbc_(o) { }
~Odbc_Access_Guard() { odbc_.close(); }
operator ODBC&() { return odbc_; }
operator const ODBC&() const { return odbc_; }
ODBC& odbc_;
};
Then inside your function:
Odbc_Access_Guard odbc(tODBC);
odbc.xyz();
if (whatever)
return ...success expression...;
The same thing goes for your pointers: they should probably be shared pointers or guards using the logic above. Then you can return any time without having to even think about where to go for the clean up code, and wondering if it's up to date with the current variable use.
I've been messing around with C++ SDL for a few days now and I've come across an interesting problem.
SDL_Event event1;
while(SDL_WaitEvent(&event1))
{
for(size_t i = 0; i < MainMenuOptions.size();i++)
{
if(event1.button.x > MainMenuOptions.at(i).GetX() && event1.button.x < (MainMenuOptions.at(i).GetX() + MainMenuOptions.at(i).GetWidth())
&& event1.button.y > MainMenuOptions.at(i).GetY() && event1.button.y < (MainMenuOptions.at(i).GetY() + MainMenuOptions.at(i).GetHeight()))
{
break;
}
}
}
When I use break in the for loop its going to break out of the for loop instead of the while loop. How would I break out the while loop instead without using the goto statement? (the goto statement is bad programming, I heard)
The common solution is to put this stuff into its own function and return from that:
inline SDL_Event do_it()
{
SDL_Event event;
while(SDL_WaitEvent(&event))
for(std::size_t i = 0; i < MainMenuOptions.size(); ++i)
if(/*...*/)
return event;
return event; // or whatever else suits, I know too little about your code
}
There's another answer to that, and I think I should say it before everyone will downvote me.
Using a variable is certainly a "good" way to do it. However, the creating additional variable just to jump out of the loop seems a bit of overkill, right?
So yes, this time goto is perfect solution. It's perfectly clear what you are doing with it, you are not using another variable and the code remains short, maintainable and readable.
The statement goto is bad practice is mostly a remnant of the BASIC times, when it was quite the only way of changing code flow. However, now we "know better", and saying that the goto or any other construction is bad, just doesn't cut it. It can be bad for one particular problem you are trying to solve with it (and it's the case with most of the problems that people try to solve with goto). However, given the right circumstances (like here) it's OK. I don't want to start a debate here, of course. Goto is like a very powerful tool (sledgehammer, for example). It has its uses and you can't say a tool is totally bad; it's the user using it in the wrong way.
Use a variable to indicate the need to exit:
bool exit_program = false;
while( !exit_program && SDL_WaitEvent(&event1) )
{
for( /* ... */ )
{
exit_program = true;
}
}
First point: IMO, you're trying to wrap too much up into a single place, and ending up with something that's fairly difficult to understand -- somebody has to read through that entire long set of comparisons before they can understand any of what this is supposed to accomplish at all.
Second point: using an explicit loop to iterate over a standard collection is usually a mistake -- and this is no exception. The standard library already has an algorithm to accomplish the same basic thing as your loop. It's better to use that than write it again yourself.
template <class T>
bool in_range(T a, T b, T c) {
return (a > b) && (a < b+c);
}
class in_rect {
point p;
public:
in_rect(point const &p) : p(p) {}
// Not sure of the type of objects in MainMenuOptions, so just T for now.
//
bool operator()(T const &m) {
return in_range(p.x, m.GetX(), m.GetWidth())
&& in_range(p.y, m.GetY(), m.GetHeight());
}
};
SDL_Event event1;
while (SDL_WaitEvent(&event1))
if (std::any_of(MainMenuOptions.begin(), MainMenuOptions.end(),
in_rect(event1.button))
break;
Once we fix the other problems, there's simply no longer any need (or even use) for the goto. We haven't taken any steps explicitly intended to remove it, but when the other problems have been fixed (especially, replacing the loop with an appropriate algorithm), the use for it has disappeared.
I suppose I should preemptively comment on the increase in the total number of lines of code: yes, there are more lines of code. What of it? If we really wanted to, we could use the same basic approach, but instead of defining in_rect and in_range, we'd basically just take the condition from the original if statement and stuff it into a lambda. While I'm very happy that lambdas have been added to C++, in this case I'm not excited about using it. It would get rid of the goto, but in general the code would be almost as unreadable as it started out.
Simply put, the number of lines isn't a good way to measure much of anything.
A solution without additional variable and goto:
while(SDL_WaitEvent(&event1))
{
size_t i;
for(i = 0; i < MainMenuOptions.size();i++)
{
if(/* ... */)
{
break;
}
}
if (i < MainMenuOptions.size())
break;
}