Making the code cleaner [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
Sorry if this question is not suited for SO.
I have a C++ function that approximately looks like MyFun() given below.
From this function I am calling some(say around 30) other functions that returns a boolean variable (true means success and false means failure). If any of these functions returns false, I have to return false from MyFun() too. Also, I am not supposed to exit immediately (without calling the remaining functions) if an intermediate function call fails.
Currently I am doing this as given below, but feel like there could be a more neat/concise way to handle this. Any suggestion is appreciated.
Many Thanks.
bool MyFun() // fn that returns false on failure
{
bool Result = true;
if (false == AnotherFn1()) // Another fn that returns false on failure
{
Result = false;
}
if (false == AnotherFn2()) // Another fn that returns false on failure
{
Result = false;
}
// Repeat this a number of times.
.
.
.
if (false == Result)
{
cout << "Some function call failed";
}
return Result;
}

I would replace each if statement with a more coincise bitwise AND assignment:
bool MyFun() // fn that returns false on failure
{
bool Result = true;
Result &= AnotherFn1(); // Another fn that returns false on failure
Result &= AnotherFn2(); // Another fn that returns false on failure
// Repeat this a number of times.
.
.
.
if (false == Result)
{
cout << "Some function call failed";
}
return Result;
}

Use something like a std::vector of std::function. It is a lot more maintenable.
Example: http://ideone.com/0voxRl
// List all the function you want to evaluate
std::vector<std::function<bool()>> functions = {
my_func1,
my_func2,
my_func3,
my_func4
};
// Evaluate all the function returning the number of function that did fail.
unsigned long failure =
std::count_if(functions.begin(), functions.end(),
[](const std::function<bool()>& function) { return !function(); });
If you want to stop when a function fail, you just have to use std::all_of instead of std::count_if. You dissociate the control flow from the function list and that is, in my opinion, a good thing.
You can improve this by using a map of function with name as key that will allows you to output which function failed:
std::map<std::string, std::function<bool()>> function_map;

bool MyFun() // fn that returns false on failure
{
bool Result = true;
// if need to call every function, despite of the Result of the previous
Result = AnotherFn1() && Result;
Result = AnotherFn2() && Result;
// if need to avoid calling any other function after some failure
Result = Result && AnotherFn1();
Result = Result && AnotherFn2();
return Result;
}

Instead of
if (false == AnotherFn1()) // Another fn that returns false on failure
{
Result = false;
}
if (false == AnotherFn2()) // Another fn that returns false on failure
{
Result = false;
}
if (false == AnotherFn3()) // Another fn that returns false on failure
{
Result = false;
}
begin to use booleans as what they are, truth values:
if (!AnotherFn1()) // Another fn that returns false on failure
{
Result = false;
}
if (!AnotherFn2()) // Another fn that returns false on failure
{
Result = false;
}
if (!AnotherFn3()) // Another fn that returns false on failure
{
Result = false;
}
Then, all those conditions have the same code; they are basically part of one big condition:
if ( !AnotherFn1()
| !AnotherFn2()
| !AnotherFn3())
{
Result = false;
}
For your specific problem, where you want all functions be called, even if you know early you'll return false, it is important to not use the short circuiting operators && and ||. Using the eager bitwise operators | and & is really a hack, because they are bitwise and not boolean (and thus hide intent), but work in your situation iff AnotherFn? return strict bools.
You can negate what you do inside; less negations yield better code:
Result = false;
if ( AnotherFn1()
& AnotherFn2()
& AnotherFn3())
{
Result = true;
}
and then you can rid these assignments and instead return straightly:
if ( AnotherFn1()
& AnotherFn2()
& AnotherFn3())
{
return true;
}
cout << "something bad happened";
return false;
Summary
Old:
bool MyFun() // fn that returns false on failure
{
bool Result = true;
if (false == AnotherFn1()) // Another fn that returns false on failure
{
Result = false;
}
if (false == AnotherFn2()) // Another fn that returns false on failure
{
Result = false;
}
// Repeat this a number of times.
.
.
.
if (false == Result)
{
cout << "Some function call failed";
}
return Result;
}
New:
bool MyFun() // fn that returns false on failure
{
if (AnotherFn1() &
AnotherFn2() &
AnotherFn3())
{
return true;
}
cout << "Some function call failed";
return false;
}
There are more possible improvements, e.g. using exceptions instead of error codes, but don't be tempted to handle "expections" instead.

! can be used as a cleaner alternative to false
Like this:
bool MyFun() // fn that returns false on failure
{
bool Result = true;
if (!AnotherFn1()) // Another fn that returns false on failure
{
Result = false;
}
if (!AnotherFn2()) // Another fn that returns false on failure
{
Result = false;
}
// Repeat this a number of times.
.
.
.
if (!Result)
{
cout << "Some function call failed";
}
return Result;
}

how about using exceptions to handle failure:a neat exemple
the main question is, are the function call interdependant or not? can some be skipped if a previous one failed? ...

Related

C++: ScopeGuard vs return check and exception handling?

Consider these code happen in real life.
A library code has a function called log_on(), it returns false on fail, true on success, but it has too many false cases.
Before return true/false, it needs to call a callback function application specified. So it looks like:
bool log_on() {
// do something else
bool success = false;
scope_guard guard = [&success]() {
if (success) {
callback(success);
} else {
callback(false);
}
}
success = prepare_logon();
if (success) {
int rc = send_password();
if (rc == PASSWORD_ERR) {
return false;
}
}
if (!send_some_data()) return false;
success = true;
return true;
}
The purpose is too many return cases, and need to call some callbacks if true and false is returned. So someone use scopeguard to do this. Is this a good practice to replace return check with scopeguard use? And in this case, the library code is required not to throw, if user specify a function callback that will throw, so error handling is a problem?
If I had to do this, I'd move the real work into a helper function:
bool log_on_impl() { /* real work here*/ }
bool log_on() {
bool success = log_on_impl();
callback(success);
return success;
}
This way, log_on_impl could do early returns to its heart's content; the callback will still be called with the correct value.

is there a better way to make this software flow

I have several functions that try and evaluate some data. Each function returns a 1 if it can successfully evaluate the data or 0 if it can not. The functions are called one after the other but execution should stop if one returns a value of 1.
Example functions look like so:
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
... more functions ...
How would be the clearest way to organise this flow? I know I can use if statements as such:
void doSomething(void)
{
if (function1(data))
{
return;
}
if (function2(data))
{
return;
}
... more if's ...
}
But this seems long winded and has a huge number of if's that need typing. Another choice I thought of is to call the next function from the return 0 of the function like so
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function2(data);
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function3(data);
}
... more functions ...
Making calling cleaner because you only need to call function1() to evaluate as far as you need to but seems to make the code harder to maintain. If another check need to be inserted into the middle of the flow, or the order of the calls changes, then all of the functions after the new one will need to be changed to account for it.
Am I missing some smart clear c++ way of achieving this kind of program flow or is one of these methods best. I am leaning towards the if method at the moment but I feel like I am missing something.
void doSomething() {
function1(data) || function2(data) /* || ... more function calls ... */;
}
Logical-or || operator happens to have the properties you need - evaluated left to right and stops as soon as one operand is true.
I think you can make a vector of lambdas where each lambdas contains specific process on how you evaluate your data. Something like this.
std::vector<std::function<bool(std::string&)> listCheckers;
listCheckers.push_back([](std::string& p_data) -> bool { return function1(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function2(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function3(p_data); });
//...and so on...
//-----------------------------
std::string theData = "Hello I'm a Data";
//evaluate all data
bool bSuccess = false;
for(fnChecker : listCheckers){
if(fnChecker(theData)) {
bSuccess = true;
break;
}
}
if(bSuccess ) { cout << "A function has evaluated the data successfully." << endl; }
You can modify the list however you like at runtime by: external objects, config settings from file, etc...

No return evaluation in nested if

After watching carefully the following code I can't see why the compiler is warning me with "warning: control reaches end of non-void function".
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
}
else
{
return false;
}
}
I can't see where is the problem, the else statement should care for returning false in every case which the first if is not true.
Trace the code path when regIOobject::read() is true, but either of permeabilityModelPtr_->read(subDict("permeability")) or magnetizationModelPtr_->read(subDict("magnetization")) is false. In that case, you enter the top if block (excluding the possibility of entering its attached else block), but then fail to enter the nested if block:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
else
{
// First if was true, so we don't go here...
return false;
}
// End of function reached, where is the return???
}
The minimalist fix is to just remove the else { } wrapping, so any fallthrough ends up at return false;:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
// Oh, but we hit return false; so we're fine
return false;
}
Alternatively, avoid specifically mentioning true or false at all, since your function is logically just a result of anding three conditions together:
bool Foam::solidMagnetostaticModel::read()
{
// No need to use ifs or explicit references to true/false at all
return regIOobject::read() &&
permeabilityModelPtr_->read(subDict("permeability")) &&
magnetizationModelPtr_->read(subDict("magnetization"));
}
The nested if is the problem.
When that branch is not taken, there is no other paths to take
the else statement should care for returning false in every case which the first if is not true.
Correct, but what if the first if condition is true, but the second if condition is not?
That is: What if regIOobject::read() returns true, but permeabilityModelPtr_->read(subDict("permeability")) returns false?
Then the flow of control enters the first if block, does not return, but does not enter the else block (because the first condition was true), so it just falls off the end of the function without hitting a return statement.
If you want the else { return false; } part to apply to either condition, you could just naively copy/paste it:
if (COND1) {
if (COND2) {
return true;
} else {
return false;
}
} else {
return false;
}
But that's quite a bit of code duplication. A better solution is to replace the nested if by a single condition:
if (COND1 && COND2) {
return true;
} else {
return false;
}
There's still some duplication: Both branches consist of a return statement followed by some expression.
We can factor out the common parts (return) and push the condition into the expression:
return COND1 && COND2 ? true : false;
But ? true : false is redundant: If the condition is true, evaluate to true, else evaluate to false? Well, that's just what the condition itself does:
return COND1 && COND2;
Or with your concrete expressions:
return regIOobject::read()
&& permeabilityModelPtr_->read(subDict("permeability"))
&& magnetizationModelPtr_->read(subDict("magnetization"));

for_each not returning (boolean) value

I have a program to verify if an IPv4 address entered as string is in valid dotted-quad notation.
The problem I am facing is that I'm not able to return (exit) function once I detect error. As per cppreference documentation for_each returns UnaryFunction. I tried using any_of and all_of but they require me using an loop (range-based loop) inside my lambda function which I'm trying to avoid. Am I missing something or it is not possible to return value in for_each.
vector<string> ipExplode;
string ip;
bool inValidIp = false;
cout << "Server IP : ";
cin >> ip;
trim(ip);
ipExplode = explode(ip, '.');
if(not for_each(ipExplode.begin(), ipExplode.end(), [](const string& str) -> bool{
int32_t ipNum;
if(regex_search(str, regex("\\D+")))
return false;
try
{
ipNum = stoi(str);
if(ipNum < 0 or ipNum > 255)
return false;
}
catch (std::exception& ex)
{
return false;
}
}))
return false;
from for_each:
If f returns a result, the result is ignored.
i.e. there is no point in returning a value from your for_each lambda.
A good choice here is all_of, which accepts a UnaryPredicate rather than a UnaryFunction, since you want to make sure that all of the parts of the string pass the lambda successfully:
bool isValid = std::all_of(ipExplode.begin(), ipExplode.end(), [](const std::string& str) -> bool{
if(regex_search(str, regex("\\D+")))
return false;
try
{
int32_t ipNum = stoi(str);
if(ipNum < 0 or ipNum > 255)
return false;
}
catch (std::exception& ex)
{
return false;
}
return true;
});
all_of will stop iterating once an invalid part is found.
Am I missing something or it is not possible to return value in for_each.
for_each does return the UnaryFunction. But if you put a unary function to if expression, its meaningless.
In your case, a lambda without capturing can implicitly convert to a function pointer. A non-null function pointer as a boolean value is always true. Thus your
if(not for_each( /* ... */ ))
will be evaluated to false all the time.
As commentators and other answerers have already written, std::all_of is what you want here.
You shouldn't use for_each anyway. Replace it by the ranged-based for and it all becomes so much simpler and elegant. Put it all in a function and there you go:
auto is_ip_valid(const std::vector<std::string>& ipExplode)
{
for (auto&& str : ipExplode)
{
// ...
}
}

Most efficient way of evaluating a bool of all items in a vector of <Classtype*>, then returning true if all are true

I have a vector of pointers to class instances I created with multiple values in it called Record
it has a value called, when I access them I
bool recordDeleted;
bool recordOwnership;
vector<Record*> RecordsVec
I want to create a function that would do something like,
bool func()
{
for (auto it = RecordsVec.begin(); it < RecordsVec.end(); it++)
{
// check whether recordDeleted is true // or recordOwnership == true)
}
// if all are true
// return true
// else
// return false
}
what is the most efficient way to do this ?
Pretty simple:
bool allDeleted() {
return std::all_of(begin(RecordsVec), end(RecordsVec), [](Record *r) {
return r->recordDeleted;
});
}
And the same for your ownership flag, of course.