I've only been programming for a short while and have yet to find a way to write branching code that covers every possible configuration of two or more boolean values without any redundant if-statements.
For example, a table showing all possible outcomes may look like this:
true false
---------------------
true | Thing A | Thing B |
---------------------
false | Thing C | Thing D |
---------------------
Yet the only code that I can think of to program things A though D is as follows:
if(boolean1) {
if(boolean2)
ThingA();
else
ThingB();
}
else if (boolean2)
ThingC();
else
ThingD();
Is there any way to write this without having to write a check for boolean2 twice? I am aware that only one check can run for one iteration of this code, but in a situation where there are more than two boolean values to worry about, this approach could become quite cumbersome.
What you can do is to create a mask using bit-shifts and introduce a switch
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstdint>
using namespace std;
int main() {
bool bArray[2];
for (size_t i = 0 ; i < 2 ; i++) {
cin >> bArray[i];
}
uint32_t mask = 0;
mask = bArray[0];
mask = mask << 1;
mask = mask ^ bArray[1];
switch(mask) {
case 0:
cout << "bot false" << endl;
break;
case 1:
cout << "first false, second true" << endl;
break;
case 2:
cout << "first true, second false" << endl;
break;
case 3:
cout << "both true" << endl;
break;
}
return 0;
}
You can make it very elegant using the new C++11 extension, where you can overload literal operator ""_ and e.g. replace case 2: with "10"_bin2int in a similar way to how hashes are created in
There is a full working example for such a switch here
http://dev.krzaq.cc/switch-on-strings-with-c11/
Using the information from above, the most elegant solution I can think of looks like this. Note how the literals are evaluated compile-time. You need a compiler which supports string-literals to compile this
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cstdint>
using namespace std;
constexpr uint32_t basis = 0;
constexpr uint32_t bin2int_compile_time(char const* str,
uint32_t last_value = basis) {
return *str ?
bin2int_compile_time(str+1,(last_value << 1) ^ ((uint8_t)*str)-48) :
last_value;
}
constexpr uint32_t operator "" _bin2int(char const* p, size_t) {
return bin2int_compile_time(p);
}
uint32_t bool2int(const bool* bools, const size_t length) {
uint32_t mask = bools[0];
for (size_t i = 1 ; i < length ; i++) {
mask = mask << 1;
mask = mask ^ bools[i];
}
return mask;
}
int main() {
const size_t nBooleans = 2;
bool bArray[nBooleans];
for (size_t i = 0 ; i < nBooleans ; i++) {
cin >> bArray[i];
}
uint32_t mask = bool2int(bArray, nBooleans);
switch(mask) {
case "00"_bin2int:
cout << "both false" << endl;
break;
case "01"_bin2int:
cout << "first false, second true" << endl;
break;
case "10"_bin2int:
cout << "first true, second false" << endl;
break;
case "11"_bin2int:
cout << "both true" << endl;
break;
default:
break;
}
return 0;
}