Looking to achieve a sort of dynamic expression where I can later evaluate the booleans if called.
condition &&= condition2; //not evaluated just yet
condition ||= condition3;
if (condition) //evaluated now
do this;
else
do this;
for example I am the using the same conditions throughout my code and it would be easier if I could just adjust the one statement or add more to it even when the programs running.
conditions = (x>50 && y>200) && (type == MONKEY);
conditions &&= (x<75 && y<250);
and later on in the code
if (conditions)
cout<<"Hello!";
edit: The conditions should be evaluated at the if statement.
Be very careful when working with && and &
Reason 1
Expanding the postulated (and syntactically invalid)
condition &&= condition2;
to
condition = condition && condition2;
reveals a subtlety: condition2 will not be evaluated if condition is false.
Reason 2
& and && also have differing behaviour for integral types, e.g. 0b01 & 0b10 is 0 but 0b01 && 0b10 is true (here I'm using C++14 binary literals).
Conclusion
So I'd favour the compaction
if (condition = condition && condition2){
// do this
} else {
// do this
}
where condition2 is only evaluated if condition is true
The sensible solution here is to create named functions for those conditions and call them whenever necessary.
That said ...
Is it possible [..]
Of course. To defer evaluation, just wrap your conditions in (lambda) functions. Proof of concept:
#include <functional>
#include <iostream>
template<typename F, typename G>
auto and_also (F f, G g) {
return [=]() {
bool first = f();
if (! first) return false;
return static_cast<bool>(g());
};
}
int main () {
int dummy = -1;
std::function<bool()> condition = [&](){return dummy > 0;};
condition = and_also(condition, [&](){return dummy < 42;});
dummy = 21;
if (condition()) std::cout << "in range" << std::endl;
}
In order to address the use case, you've mentioned in a comment:
Example: moving through pixels in a window and avoiding certain areas of the window.
For reasons of readability, I'd recommend you define a function, e.g., like this (pseudocode) example:
bool is_in_rect(point2i p, rect2i rect) {
// check x range
if (p.x >= rect.x1 && p.x < rect.x2)
return true;
// check y range
if (p.y >= rect.y1 && p.y < rect.y2)
return true;
return false;
}
You can add functions for specialized situations as you wish:
bool is_in_monkey_rect(point2i p, rect2i rect) {
return rect.type == MONKEY && is_in_rect(p, rect);
}
But overall I'm just interested to see if this is possible.
Other than delegating to a function, you'd probably use macros to simulate this kind of lazy evaluation. But I wouldn't recommend that.
Note that, depending on the actual nature of the problem, it might make more sense to adapt the iteration pattern, rather than iterating all the data and check every single pixel for relevance.
A common way to do something in one place, so you don't repeat yourself everywhere is to make a function.
For example,
bool special_condition(bool current_condition, int x)
{
return current_condition && (x<75 && y<250);
}
allows this whenever needed.
if (special_condition(conditions))
do_something();
else
do_something_else();
This will be evaulated when the if is encountered, however, this won't short circuit if current_condition is false when the function will still be called.
Short answer Stefan, in C++ no.
The expression is evaluated during &=.
Short circuiting expressions e.g. ignoring b if a is false in expressions such as a && b, is usually configurable in your environment and normally on.
If you still wish to do so, create an evaluation function instead.
/Anders
Related
I need to place two dependent init statements within one if condition. As a raw example:
if (bool x = false; bool y = true) std::cout << "Check!\n";
The whole expression evaluates to true, and that is the problem. Suppose I want to test a pointer in the first statement and dereference this pointer to test something else in the second statement:
if (auto ptr = ptr_to_check; auto sth_else = ptr_to_check->sth_else()) { /* do something */ }
And this one is going to crash as I can still dereference nullptr. I want to avoid nested if's as in my program there are other statements nested within this one. Can I place these two statements within one condition somehow?
When it comes to several statements within one if, only the last statement is evaluated as a condition. In this case, a ternary operator is a solution:
if (bool x = false; bool y = x ? true : false) std::cout << "Check!\n";
So, in case of pointers:
if (auto ptr = ptr_to_check; auto sth_else = ptr_to_check ? ptr_to_check->sth_else() : sth_evaluating_to_false) { /* do something */ }
In some cases it happens for me to declare a variable without knowing its value first like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
Is it the standard professional practice to assign some clearly wrong value like -1000 anyway (making potential bugs more reproducible) or it is preferred not to add the code that does nothing useful as long as there are no bugs? From one side, looks reasonable to remove randomness, from the other side, magical and even "clearly wrong" numbers somehow do not look attractive.
In many cases it is possible to declare when the value is first known, or use a ternary operator, but here we would need it nested so also rather clumsy.
Declaring inside the block would move the variable out of the scope prematurely.
Or would this case justify the usage of std::optional<int> a and assert(a) later, making sure we have the value?
EDIT: The bugs I am talking about would occur if suddenly all 3 conditions are false that should "absolutely never happen".
As far as I know the most popular and safest way is using inline lambda call. Note that the if should be exhaustive (I added SOME_DEFAULT_VALUE as a placeholder). I suppose that if you don't know what to put in final else block you should consider a few options:
using optional and putting none in the else,
throwing exception that describes the problem,
putting assert if logically this situation should never happen
const int a = [&] {
if (c1) {
return 1;
} else if (c2) {
return 2;
} else if (c3) {
return -3;
} else {
return SOME_DEFAULT_VALUE;
}
}();
do_something_with(a);
In a situation when the initialization logic duplicates somewhere you can simply extract the lambda to a named function as other answers suggest
In my opinion, the safest option, if you dont want this other value (its just useless), then it may lead to really subtle bug which may be hard to find. Therefore I would throw an expectation when any of the conditions is not met:
int get_init_value(bool c1, bool c2, bool c3) {
if (c1) { return 1; }
else if (c2) { return 2; }
else if (c3) { return -3; }
throw std::logic_error("noone of conditions to define value was met");
}
That way we avoid getting some weird values that want actually match our code, but they would compile anyways ( debugging it may take a lot of time). I consider it way better than just assigning it some clearly wrong value.
Opinion based answer!
I know the example is a simplification of a real, more complex example, but IMHO it seems nowadays this kind of design issue emerge more often, and people sometimes kinda tend to over-complicate it.
Isn't it the whole purpose of a variable to hold some value? Thus isn't having a default value for this variable also a feasible thing?
So what exactly is wrong with:
int a = -1000; // or some other value meant to used for undefined
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
It is simple and readable... No lambdas, exceptions and other stuff making the code unnecessary complicated...
Or like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
} else {
a = -1000; // default for unkown state
}
do_something_with(a);
You could introduce a constant const int undefined = -1000; and use the constant.
Or an enum if c1, c2, c3 are states in some sort (which it most likely is)...
You could rearrange the code to eliminate the variable if it is not needed elsewhere.
if (c1) {
do_something_with(1);
} else if (c2) {
do_something_with(2);
} else if (c3) {
do_something_with(-3);
}
I would introduce a default value. I'm usually using MAX value of the type for this.
Shortest you can do this with the ternary operator like this:
#include <climits>
int a = c1 ? 1 : c2 ? 2 : c3 ? -3 : INT_MAX;
do_something_with(a);
I understand your real code is much more complicated than the outline presented, but IMHO the main problem here is
should we do_something_with(a) at all if a is undefined,
rather than
what the initial value should be.
And the solution might be adding explicitly some status flag like a_is_defined to the actual parameter a instead of using magic constans.
int a = 0;
bool a_is_defined = false;
When you set them both according to c... conditions and pass them to do_something() you'll be able to make a clear distinction between a specific if(a_is_defined) {...} path and a default (error handling?) else {...}.
Or even provide separate routines to explicitly handle both paths one level earlier: if(a_is_defined) do_someting_with(a); else do_something_else();.
In embedded C/C++ programming is quite common to write for loops of this type:
...
for(int16_t i=0; i<5; i++)
{
if(true == unlockSIM(simPinNumber))
return true;
wait_ms(1000);
}
return false;
...
or like this while() loop:
bool CGps::waitGpsFix(int8_t fixVal)
{
int16_t iRunStatus=0, iFixStatus=0;
_timeWaitGpsFix = CSysTick::instance().set(TIME_TO_WAIT_GPS);
while(1)
{
bool bRet = _pGsm->GPSstatus(&iRunStatus, &iFixStatus);
if( (true == bRet) && (1 == iRunStatus) && (iFixStatus >= fixVal) )
return true;
if(CSysTick::instance().isElapsed(_timeWaitGpsFix))
return false;
wait_ms(500);
}
return false;
}
//---------------------------------------------------------------------------
is there any well known good pattern useful to don't write each time so many lines but just a function or method call?
For the for loop, you could use a function template that accepts the function (must return a boolean) and return when succeeded. For the while loop, things get more complicated, but I guess that lambdas could be used as true and false conditions.
For loop:
#include <iostream>
template<int retries, int wait_time, typename FUNC, typename ...Args>
bool retry(FUNC& f, Args &&... args)
{
for (int i = 0; i < retries; ++i)
{
if (f(std::forward<Args>(args)...)) return true;
if (i < retries - 1)
{
std::cout << "waiting " << wait_time << "\n";
}
}
return false;
}
bool func(int i)
{
return (i > 0);
}
bool func2(int i, int j)
{
return (i > j);
}
int main()
{
bool result = retry<5, 500>(func, 0);
std::cout << result << "\n";
result = retry<5, 500>(func, 1);
std::cout << result << "\n";
result = retry<5, 500>(func2, 1, 2);
std::cout << result << "\n";
result = retry<5, 500>(func2, 1, 0);
std::cout << result << "\n";
}
See example in coliru
This is simple enough with the execute-around idiom, which executes a given piece of code in an environment/set of circumstances controlled by the function the piece of code is passed in to. Here, we'll simply be calling the piece of code in a loop once every n milliseconds, either for a set amount of time, or for a set number of times.
Since you're working in an embedded environment and seem to be using a set of timing mechanisms different from that provided by <chrono> and <thread>, I've tried to adjust my answer so you can use the methods you seem to have access to to do the same thing. These are the functions I've used in my solution:
// similar functions to what you seem to have access to
namespace timing{
// interval defined as some arbitrary type
interval getInterval(int msCount);
bool intervalElapsed(interval i);
void await(interval i);
}
A note on the await function there--it takes an interval, and pauses execution until the interval has passed. It seems like the closest you can get to this might be simply waiting for the total number of milliseconds instead, though that strategy will introduce a certain amount of drift in your timings. If you can tolerate that (and given you're using it, it seems you can), then great.
The retry-for variant would look like this, given the above function signatures:
template <typename Func>
bool pollRetries(
int retryLimit,
int msInterval,
Func func){
for(int i = 0; i < retryLimit; ++i){
auto interval = timing::getInterval(msInterval);
if (func()){return true;}
timing::await(interval);
}
return false;
}
and the retry-while would look like this:
template <typename Func>
bool pollDuration(
int msLimit,
int msInterval,
Func func){
auto limit = timing::getInterval(msLimit);
while(!timing::intervalElapsed(limit)){
auto interval = timing::getInterval(msInterval);
if (func()){return true;}
timing::await(interval);
}
return false;
}
Live demo on Coliru
Both functions take a single functor which will be called with no arguments, and which returns either a boolean or something convertible to a boolean value. If the evaluation ever returns true, the loop will exit and the function will return true. Otherwise it'll return false at the end of the retry count or period.
Your sample code would convert to this:
retry for loop:
return pollRetries(5,1000,[simPinNumber](){
return unlockSIM(simPinNumber);
});
retry while loop:
return pollDuration(TIME_TO_WAIT_GPS, 500, [fixVal, this](){
int16_t
iRunStatus = 0,
iFixStatus = 0;
bool bRet = this->_pGsm->GPSstatus(&iRunStatus, &iFixStatus);
return bRet && (1 == iRunStatus) && (iFixStatus >= fixVal);
});
You can pass either functors or function pointers into these methods and the execution will occur, so you can also simply directly pass in lambdas to be executed. A few notes about that:
Lambdas without a capture group can be converted to function pointers with the unary + operator, allowing the template to use the function pointer instantiation of the template rather than one based off the lambda. You might want to do this because:
Every lambda in every function has an anonymous type. Passing the lambda into the template function will result in an additional template instantiation which might increase binary size.
You can also mitigate the above problem by defining your own functor class for uses that share a set of persistent state.
You might try making the timing functions into variadic templates per #stefaanv's solution. If you went this route, you could remove the capture groups from your lambdas and pass that information in manually, which would allow you to convert the lambdas into function pointers as though they were stateless.
Were most of these retry loops for a single class you could simply define the retry mechanisms as member function templates, and then subject yourself to member function pointers, thereby passing state around using the called object. I'd not recommend this though, as member function pointers are a bit of a pain to deal with, and you could get the same result by making a stateless lambda take a reference to the object, and passing in *this to the call. You'd also have to define all the bits of code as their own functions, rather than simply defining them within the function where they were used.
Some functions which calculate booleans:
bool a()
{
return trueorfalse;
}
bool b()
{
//...
}
bool c()
{
//...
}
This condition
//somewhere else
if((a()&&b()&&c()) || (a()&&b()&&!c()) )
{
doSomething();
}
can also be written as
if(a()&&b())
{
doSomething();
}
Will compilers usually optimize this away?
And what about pure boolean values:
if((a&&b&&c) || (a&&b&&!c))
{
doSomething();
}
Since the functions may have side effects, the conditional cannot be "optimized" in any way, since all the functions will have to be called (conditionally) in a well-defined manner.
If you do want optimization, you can assign the result to variables first:
const bool ba = a(), bb = b(), bc = c();
if (ba && bb && bc || ba && bb && !bc) { /* ... */ } // probably optimized to "ba && bb"
It's possible that constexpr functions introduced in C++11 will allow for optimization if they yield a constant expression, though, but I'm not sure.
You can even condense this down: In the following code, f() has to be called twice:
if (f() && false || f() && true)
{
// ...
}
No they won't. The reason why is that the optimization would be visible to the user because it would change the observable side effects. For example In your optimized version c() would never execute even though the user explicitly tried to do so. This can and will lead to bugs.
Since your premise a flawed, no, they won't.
(a()&&b()&&c()) || (a()&&b()&&!c()) definitely can't be rewritten as (a()&&b())
C (and C++) isn't a functional programming language (like Haskell).
But the problem is that it can't be refactored in that way, generally speaking!
If any of the functions have side effects that change the result of c() then the second call would possibly return a different result from the first one.
Not only that, but due to short-circuit execution things could be muddied even further.
Very often in C the return value of a function gives whether the function was executed successfully of not. For example calling a graphics routine, converting a file. Think how often you use pointers to change something external to the function. Or call another function that outputs something. As someone said this isn't functional programming.
If the compiler is able to determine that foo() changes and does nothing then it may by all means simplify it but I would NOT count on it.
Here is a very simple example
bool foo()
{
std::cout << "this needs to be printed each time foo() is called, even though its called in a logical expression\n";
return true;
}
int main()
{
if ((foo() && !(foo()) || foo() && !(foo())))
return 0;
return 1;
}
Edit any boolean algebra of variables should be simplified.
assume this following function:
int binaryTree::findHeight(node *n) {
if (n == NULL) {
return 0;
} else {
return 1 + max(findHeight(n->left), findHeight(n->right));
}
}
Pretty standard recursive treeHeight function for a given binary search tree binaryTree. Now, I was helping a friend (he's taking an algorithms course), and I ran into some weird issue with this function that I couldn't 100% explain to him.
With max being defined as max(a,b) ((a)>(b)?(a):(b)) (which happens to be the max definition in windef.h), the recursive function freaks out (it runs something like n^n times where n is the tree height). This obviously makes checking the height of a tree with 3000 elements take very, very long.
However, if max is defined via templating, like std does it, everything is okay. So using std::max fixed his problem. I just want to know why.
Also, why does the countLeaves function work fine, using the same programmatic recursion?
int binaryTree::countLeaves(node *n) {
if (n == NULL) {
return 0;
} else if (n->left == NULL && n->right == NULL) {
return 1;
} else {
return countLeaves(n->left) + countLeaves(n->right);
}
}
Is it because in returning the ternary function, the values a => countLeaves(n->left) and b => countLeaves(n->right) were recursively double called simply because they were the resultants?
Thank you!
The question was answered below
I just wanted to link some literature on the subject for future reference:
http://www.boostpro.com/tmpbook/preprocessor.html
http://msdn.microsoft.com/en-us/library/z3f89ch8.aspx
The main difference between the two implementations being:
#define max(i, j) (((i) > (j)) ? (i) : (j))
vs
template<class T> T max (T i, T j) { return ((i > j) ? i : j) }
Thank you all!
Macros are expanded by the preprocessor, before the compiler gets to see the code. This means that, for example, macro parameters might be evaluated more than once.
With your macro, you're going to end up with something akin to:
int binaryTree::findHeight(node *n) {
if (n == NULL) {
return 0;
} else {
return 1 + (findHeight(n->left) > findHeight(n->right)) ? // call once...
findHeight(n->left) : findHeight(n->right); // and ouch
}
}
As you can see, it's going to evaluate both functions, then one more an additional time. This is why macros can be evil.
You can disable the macro by defining NOMINMAX prior to including the Windows headers. Then use the function in <algorithm> instead.
If he must use the macro, he'll have to store the calculations in a variable:
int binaryTree::findHeight(node *n) {
if (n == NULL) {
return 0;
} else {
const int leftHeight = findHeight(n->left);
const int rightHeight = findHeight(n->right);
return 1 + max(leftHeight, rightHeight);
}
}
With a function, each call will be evaluated prior to calling the function. That is, it's somewhat like the previous code block. It evaluates the function's arguments, gets the results, then passes those into the std::max function. There are no repeated evaluations.
That max macro evaluates the arguments twice - and since your argument is a recursive function call, that's probably the source of the perf problem.
It's because of the definition of max. You're making 3 calls to findHeight() instead of 2.
a better option would be to declare a function with following signature:
int max(int, int)
This will prevent the recursive expansion of macro.