How to improve logic to check whether 4 boolean values match some cases











up vote
99
down vote

favorite
23












I have four bool values:



bool bValue1;
bool bValue2;
bool bValue3;
bool bValue4;


The acceptable values are:



         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true | true | true
bValue2: true | true | false
bValue3: true | true | false
bValue4: true | false | false


So, for example, this scenario is not acceptable:



bValue1: false
bValue2: true
bValue3: true
bValue4: true


At the moment I have come up with this if statement to detect bad scenarios:



if(((bValue4 && (!bValue3 || !bValue2 || !bValue1)) ||
((bValue3 && (!bValue2 || !bValue1)) ||
(bValue2 && !bValue1) ||
(!bValue1 && !bValue2 && !bValue3 && !bValue4))
{
// There is some error
}


Can that statement logic be improved/simplified?










share|improve this question




















  • 8




    I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
    – Zdeslav Vojkovic
    Dec 3 at 10:16








  • 3




    if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
    – mch
    Dec 3 at 10:17








  • 14




    what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
    – user463035818
    Dec 3 at 10:57






  • 6




    Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
    – Hardik Modha
    Dec 3 at 12:29








  • 5




    FYI en.wikipedia.org/wiki/Karnaugh_map
    – 00__00__00
    Dec 5 at 14:43















up vote
99
down vote

favorite
23












I have four bool values:



bool bValue1;
bool bValue2;
bool bValue3;
bool bValue4;


The acceptable values are:



         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true | true | true
bValue2: true | true | false
bValue3: true | true | false
bValue4: true | false | false


So, for example, this scenario is not acceptable:



bValue1: false
bValue2: true
bValue3: true
bValue4: true


At the moment I have come up with this if statement to detect bad scenarios:



if(((bValue4 && (!bValue3 || !bValue2 || !bValue1)) ||
((bValue3 && (!bValue2 || !bValue1)) ||
(bValue2 && !bValue1) ||
(!bValue1 && !bValue2 && !bValue3 && !bValue4))
{
// There is some error
}


Can that statement logic be improved/simplified?










share|improve this question




















  • 8




    I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
    – Zdeslav Vojkovic
    Dec 3 at 10:16








  • 3




    if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
    – mch
    Dec 3 at 10:17








  • 14




    what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
    – user463035818
    Dec 3 at 10:57






  • 6




    Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
    – Hardik Modha
    Dec 3 at 12:29








  • 5




    FYI en.wikipedia.org/wiki/Karnaugh_map
    – 00__00__00
    Dec 5 at 14:43













up vote
99
down vote

favorite
23









up vote
99
down vote

favorite
23






23





I have four bool values:



bool bValue1;
bool bValue2;
bool bValue3;
bool bValue4;


The acceptable values are:



         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true | true | true
bValue2: true | true | false
bValue3: true | true | false
bValue4: true | false | false


So, for example, this scenario is not acceptable:



bValue1: false
bValue2: true
bValue3: true
bValue4: true


At the moment I have come up with this if statement to detect bad scenarios:



if(((bValue4 && (!bValue3 || !bValue2 || !bValue1)) ||
((bValue3 && (!bValue2 || !bValue1)) ||
(bValue2 && !bValue1) ||
(!bValue1 && !bValue2 && !bValue3 && !bValue4))
{
// There is some error
}


Can that statement logic be improved/simplified?










share|improve this question















I have four bool values:



bool bValue1;
bool bValue2;
bool bValue3;
bool bValue4;


The acceptable values are:



         Scenario 1 | Scenario 2 | Scenario 3
bValue1: true | true | true
bValue2: true | true | false
bValue3: true | true | false
bValue4: true | false | false


So, for example, this scenario is not acceptable:



bValue1: false
bValue2: true
bValue3: true
bValue4: true


At the moment I have come up with this if statement to detect bad scenarios:



if(((bValue4 && (!bValue3 || !bValue2 || !bValue1)) ||
((bValue3 && (!bValue2 || !bValue1)) ||
(bValue2 && !bValue1) ||
(!bValue1 && !bValue2 && !bValue3 && !bValue4))
{
// There is some error
}


Can that statement logic be improved/simplified?







c++ if-statement






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 3 at 14:44









Dukeling

44.6k1060105




44.6k1060105










asked Dec 3 at 10:13









Andrew Truckle

5,45142246




5,45142246








  • 8




    I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
    – Zdeslav Vojkovic
    Dec 3 at 10:16








  • 3




    if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
    – mch
    Dec 3 at 10:17








  • 14




    what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
    – user463035818
    Dec 3 at 10:57






  • 6




    Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
    – Hardik Modha
    Dec 3 at 12:29








  • 5




    FYI en.wikipedia.org/wiki/Karnaugh_map
    – 00__00__00
    Dec 5 at 14:43














  • 8




    I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
    – Zdeslav Vojkovic
    Dec 3 at 10:16








  • 3




    if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
    – mch
    Dec 3 at 10:17








  • 14




    what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
    – user463035818
    Dec 3 at 10:57






  • 6




    Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
    – Hardik Modha
    Dec 3 at 12:29








  • 5




    FYI en.wikipedia.org/wiki/Karnaugh_map
    – 00__00__00
    Dec 5 at 14:43








8




8




I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
– Zdeslav Vojkovic
Dec 3 at 10:16






I would use a table instead of complex if statement. Additionally, as these are boolean flags, you can model each scenario as a constant and check against it.
– Zdeslav Vojkovic
Dec 3 at 10:16






3




3




if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
– mch
Dec 3 at 10:17






if (!((bValue1 && bValue2 && bValue3) || (bValue1 && !bValue2 && !bValue3 && !bValue4)))
– mch
Dec 3 at 10:17






14




14




what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
– user463035818
Dec 3 at 10:57




what are the scenarios actually? Often things get much simpler if you just give stuff proper names, eg bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
– user463035818
Dec 3 at 10:57




6




6




Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
– Hardik Modha
Dec 3 at 12:29






Using meaningful names, you can extract each complex condition into a method and call that method in if condition. It would be much more readable and maintainable. e.g. Take a look at the example provided in the link.refactoring.guru/decompose-conditional
– Hardik Modha
Dec 3 at 12:29






5




5




FYI en.wikipedia.org/wiki/Karnaugh_map
– 00__00__00
Dec 5 at 14:43




FYI en.wikipedia.org/wiki/Karnaugh_map
– 00__00__00
Dec 5 at 14:43












30 Answers
30






active

oldest

votes

















up vote
182
down vote



accepted










I would aim for readability: you have just 3 scenario, deal with them with 3 separate ifs:



bool valid = false;
if (bValue1 && bValue2 && bValue3 && bValue4)
valid = true; //scenario 1
else if (bValue1 && bValue2 && bValue3 && !bValue4)
valid = true; //scenario 2
else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
valid = true; //scenario 3


Easy to read and debug, IMHO. Also, you can assign a variable whichScenario while proceeding with the if.



With just 3 scenarios, I would not go with something such "if the first 3 values are true I can avoid check the forth value": it's going to make your code harder to read and maintain.



Not an elegant solution maybe surely, but in this case is ok: easy and readable.



If your logic gets more complicated, throw away that code and consider using something more to store different available scenarios (as Zladeck is suggesting).



I really love the first suggestion given in this answer: easy to read, not error prone, maintainable



(Almost) off topic:



I don't write lot of answers here at StackOverflow. It's really funny that the above accepted answer is by far the most appreciated answer in my history (never had more than 5-10 upvotes before I think) while actually is not what I usually think is the "right" way to do it.



But simplicity is often "the right way to do it", many people seems to think this and I should think it more than I do :)






share|improve this answer



















  • 8




    Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
    – gsamaras
    Dec 3 at 10:34








  • 1




    sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
    – Gian Paolo
    Dec 3 at 10:49






  • 4




    This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
    – Leushenko
    Dec 3 at 11:13








  • 3




    I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
    – Martijn
    Dec 3 at 14:36






  • 2




    FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
    – Dancrumb
    Dec 3 at 19:48


















up vote
105
down vote













I would aim for simplicity and readability.



bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

if (scenario1 || scenario2 || scenario3) {
// Do whatever.
}


Make sure to replace the names of the scenarios as well as the names of the flags with something descriptive. If it makes sense for your specific problem, you could consider this alternative:



bool scenario1or2 = bValue1 && bValue2 && bValue3;
bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

if (scenario1or2 || scenario3) {
// Do whatever.
}


What's important here is not predicate logic. It's describing your domain and clearly expressing your intent. The key here is to give all inputs and intermediary variables good names. If you can't find good variable names, it may be a sign that you are describing the problem in the wrong way.






share|improve this answer



















  • 3




    +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
    – RedFilter
    Dec 4 at 15:47






  • 2




    Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
    – Andrew Truckle
    Dec 5 at 5:28






  • 1




    +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
    – Andreas
    Dec 5 at 13:07


















up vote
96
down vote













We can use a Karnaugh map and reduce your scenarios to a logical equation.
I have used the Online Karnaugh map solver with circuit for 4 variables.



enter image description here



This yields:



enter image description here



Changing A, B, C, D to bValue1, bValue2, bValue3, bValue4, this is nothing but:



bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4


So your if statement becomes:



if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
{
// There is some error
}



  • Karnaugh Maps are particularly useful when you have many variables and many conditions which should evaluate true.

  • After reducing the true scenarios to a logical equation, adding relevant comments indicating the true scenarios is good practice.






share|improve this answer



















  • 91




    Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
    – Zdeslav Vojkovic
    Dec 3 at 11:00






  • 20




    @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
    – P.W
    Dec 3 at 11:05






  • 10




    I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
    – Zdeslav Vojkovic
    Dec 3 at 11:09






  • 7




    I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
    – Maciej Piechotka
    Dec 3 at 11:31






  • 25




    @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
    – Dukeling
    Dec 3 at 14:21




















up vote
52
down vote













The real question here is: what happens when another developer (or even author) must change this code few months later.



I would suggest modelling this as bit flags:



const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
const int SCENARIO_2 = 0x0E; // 0b1110
const int SCENARIO_3 = 0x08; // 0b1000

bool bValue1 = true;
bool bValue2 = false;
bool bValue3 = false;
bool bValue4 = false;

// boolean -> int conversion is covered by standard and produces 0/1
int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
std::cout << (match ? "ok" : "error");


If there are many more scenarios or more flags, a table approach is more readable and extensible than using flags. Supporting a new scenario requires just another row in the table.



int scenarios[3][4] = {
{true, true, true, true},
{true, true, true, false},
{true, false, false, false},
};

int main()
{
bool bValue1 = true;
bool bValue2 = false;
bool bValue3 = true;
bool bValue4 = true;
bool match = false;

// depending on compiler, prefer std::size()/_countof instead of magic value of 4
for (int i = 0; i < 4 && !match; ++i) {
auto current = scenarios[i];
match = bValue1 == current[0] &&
bValue2 == current[1] &&
bValue3 == current[2] &&
bValue4 == current[3];
}

std::cout << (match ? "ok" : "error");
}





share|improve this answer



















  • 4




    Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
    – Adam Zahran
    Dec 3 at 10:35






  • 6




    IMO, table is the best approach as it scales better with additional scenarios and flags.
    – Zdeslav Vojkovic
    Dec 3 at 10:44










  • I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
    – Gian Paolo
    Dec 3 at 12:52








  • 4




    If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
    – Dukeling
    Dec 3 at 14:25








  • 2




    I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
    – Konrad Rudolph
    Dec 3 at 22:25




















up vote
22
down vote













My previous answer is already the accepted answer, I add something here that I think is both readable, easy and in this case open to future modifications:



Starting with @ZdeslavVojkovic answer (which I find quite good), I came up with this:



#include <iostream>
#include <set>

//using namespace std;

int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
{
return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
}
bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
{
std::set<int> validScenarios;
validScenarios.insert(GetScenarioInt(true, true, true, true));
validScenarios.insert(GetScenarioInt(true, true, true, false));
validScenarios.insert(GetScenarioInt(true, false, false, false));

int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

return validScenarios.find(currentScenario) != validScenarios.end();
}

int main()
{
std::cout << IsValidScenario(true, true, true, false) << "n"; // expected = true;
std::cout << IsValidScenario(true, true, false, false) << "n"; // expected = false;

return 0;
}


See it at work here



Well, that's the "elegant and maintainable" (IMHO) solution I usually aim to, but really, for the OP case, my previous "bunch of ifs" answer fits better the OP requirements, even if it's not elegant nor maintainable.






share|improve this answer






























    up vote
    16
    down vote













    I would also like to submit an other approach.



    My idea is to convert the bools into an integer and then compare using variadic templates:



    unsigned bitmap_from_bools(bool b) {
    return b;
    }
    template<typename... args>
    unsigned bitmap_from_bools(bool b, args... pack) {
    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
    }

    int main() {
    bool bValue1;
    bool bValue2;
    bool bValue3;
    bool bValue4;

    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
    //bad scenario
    }
    }


    Notice how this system can support up to 32 bools as input. replacing the unsigned with unsigned long long (or uint64_t) increases support to 64 cases.
    If you dont like the if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u), you could also use yet another variadic template method:



    bool equals_any(unsigned target, unsigned compare) {
    return target == compare;
    }
    template<typename... args>
    bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
    }

    int main() {
    bool bValue1;
    bool bValue2;
    bool bValue3;
    bool bValue4;

    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
    //bad scenario
    }
    }





    share|improve this answer



















    • 3




      Thanks for sharing your alternative approach.
      – Andrew Truckle
      Dec 3 at 12:39






    • 1




      I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
      – Konrad Rudolph
      Dec 3 at 22:29












    • yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
      – Stack Danny
      Dec 4 at 7:57










    • I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
      – MooseBoys
      Dec 5 at 15:38












    • @MooseBoys yes, you're right. Thanks
      – Stack Danny
      Dec 5 at 15:42


















    up vote
    13
    down vote













    Here's a simplified version:



    if (bValue1&&(bValue2==bValue3)&&(bValue2||!bValue4)) {
    // acceptable
    } else {
    // not acceptable
    }


    Note, of course, this solution is more obfuscated than the original one, its meaning may be harder to understand.





    Update: MSalters in the comments found an even simpler expression:



    if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...





    share|improve this answer



















    • 1




      Yes, but hard to understand. But thanks for suggestion.
      – Andrew Truckle
      Dec 3 at 10:58










    • I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
      – Oliv
      Dec 3 at 11:07








    • 1




      @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
      – geza
      Dec 3 at 11:12






    • 1




      simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
      – Zdeslav Vojkovic
      Dec 3 at 11:16






    • 1




      @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
      – geza
      Dec 4 at 18:53


















    up vote
    9
    down vote













    I'm not seeing any answers saying to name the scenarios, though the OP's solution does exactly that.



    To me it is best to encapsulate the comment of what each scenario is into either a variable name or function name. You're more likely to ignore a comment than a name, and if your logic changes in the future you're more likely to change a name than a comment. You can't refactor a comment.



    If you plan on reusing these scenarios outside of your function (or might want to), then make a function that says what it evaluates (constexpr/noexcept optional but recommended):



    constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
    { return b1 && b2 && b3 && b4; }

    constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
    { return b1 && b2 && b3 && !b4; }

    constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
    { return b1 && !b2 && !b3 && !b4; }


    Make these class methods if possible (like in OP's solution). You can use variables inside of your function if you don't think you'll reuse the logic:



    const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
    const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
    const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;


    The compiler will most likely sort out that if bValue1 is false then all scenarios are false. Don't worry about making it fast, just correct and readable. If you profile your code and find this to be a bottleneck because the compiler generated sub-optimal code at -O2 or higher then try to rewrite it.






    share|improve this answer























    • I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
      – Dirk Herrmann
      Dec 3 at 23:53


















    up vote
    8
    down vote













    I am only providing my answer here as in the comments someone suggested to show my solution. I want to thank everyone for their insights.



    In the end I opted to add three new "scenario" boolean methods:



    bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
    {
    return (INCLUDE_ITEM1(pEntry) &&
    !INCLUDE_ITEM2(pEntry) &&
    !INCLUDE_ITEM3(pEntry) &&
    !INCLUDE_ITEM4(pEntry));
    }

    bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
    {
    return (INCLUDE_ITEM1(pEntry) &&
    INCLUDE_ITEM2(pEntry) &&
    INCLUDE_ITEM3(pEntry) &&
    INCLUDE_ITEM4(pEntry));
    }

    bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
    {
    return (INCLUDE_ITEM1(pEntry) &&
    INCLUDE_ITEM2(pEntry) &&
    INCLUDE_ITEM3(pEntry) &&
    !INCLUDE_ITEM4(pEntry));
    }


    Then I was able to apply those my my validation routine like this:



    if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
    {
    ; Error
    }


    In my live application the 4 bool values are actually extracted from a DWORD which has 4 values encoded into it.



    Thanks again everyone.






    share|improve this answer

















    • 1




      Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
      – Hardik Modha
      Dec 3 at 13:04






    • 1




      @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
      – Andrew Truckle
      Dec 3 at 13:06










    • Well, Sounds good then. :)
      – Hardik Modha
      Dec 3 at 13:10




















    up vote
    8
    down vote













    Consider translating your tables as directly as possible into your program. Drive the program based off the table, instead of mimicing it with logic.



    template<class T0>
    auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
    for (auto&& x:il)
    if (x==t0) return true;
    return false;
    }


    now



    if (is_any_of(
    std::make_tuple(bValue1, bValue2, bValue3, bValue4),
    {
    {true, true, true, true},
    {true, true, true, false},
    {true, false, false, false}
    }
    ))


    this directly as possible encodes your truth table into the compiler.



    Live example.



    You could also use std::any_of directly:



    using entry = std::array<bool, 4>;
    constexpr entry acceptable =
    {
    {true, true, true, true},
    {true, true, true, false},
    {true, false, false, false}
    };
    if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
    return entry{bValue1, bValue2, bValue3, bValue4} == x;
    }) {
    }


    the compiler can inline the code, and eliminate any iteration and build its own logic for you. Meanwhile, your code reflects exactly how you concieved of the problem.






    share|improve this answer























    • The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
      – Gian Paolo
      Dec 4 at 22:03












    • Interesting alternative. 👍
      – Andrew Truckle
      Dec 5 at 5:24


















    up vote
    7
    down vote













    A C/C++ way



    bool scenario[3][4] = {{true, true, true, true}, 
    {true, true, true, false},
    {true, false, false, false}};

    bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
    {
    bool temp = {bValue1, bValue2, bValue3, bValue4};
    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
    {
    if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
    return true;
    }
    return false;
    }


    This approach is scalable as if the number of valid conditions grow, you easily just add more of them to scenario list.






    share|improve this answer





















    • Thank you for your answer.
      – Andrew Truckle
      Dec 3 at 12:36










    • I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
      – MSalters
      Dec 3 at 15:43










    • @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
      – hessam hedieh
      Dec 3 at 16:01












    • Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
      – Konrad Rudolph
      Dec 3 at 22:27










    • @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
      – MSalters
      Dec 4 at 10:25


















    up vote
    7
    down vote













    It's easy to notice that first two scenarios are similar - they share most of the conditions. If you want to select in which scenario you are at the moment, you could write it like this (it's a modified @gian-paolo's solution):



    bool valid = false;
    if(bValue1 && bValue2 && bValue3)
    {
    if (bValue4)
    valid = true; //scenario 1
    else if (!bValue4)
    valid = true; //scenario 2
    }
    else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
    valid = true; //scenario 3


    Going further, you can notice, that first boolean needs to be always true, which is an entry condition, so you can end up with:



    bool valid = false;
    if(bValue1)
    {
    if(bValue2 && bValue3)
    {
    if (bValue4)
    valid = true; //scenario 1
    else if (!bValue4)
    valid = true; //scenario 2
    }
    else if (!bValue2 && !bValue3 && !bValue4)
    valid = true; //scenario 3
    }


    Even more, you can now clearly see, that bValue2 and bValue3 are somewhat connected - you could extract their state to some external functions or variables with more appropriate name (this is not always easy or appropriate though):



    bool valid = false;
    if(bValue1)
    {
    bool bValue1and2 = bValue1 && bValue2;
    bool notBValue1and2 = !bValue2 && !bValue3;
    if(bValue1and2)
    {
    if (bValue4)
    valid = true; //scenario 1
    else if (!bValue4)
    valid = true; //scenario 2
    }
    else if (notBValue1and2 && !bValue4)
    valid = true; //scenario 3
    }


    Doing it this way have some advantages and disadvantages:




    • conditions are smaller, so it's easier to reason about them,

    • it's easier to do nice renaming to make these conditions more understandable,

    • but, they require to understand the scope,

    • moreover it's more rigid


    If you predict that there will be changes to the above logic, you should use more straightforward approach as presented by @gian-paolo.



    Otherwise, if these conditions are well established, and are kind of "solid rules" that will never change, consider my last code snippet.






    share|improve this answer




























      up vote
      6
      down vote













      A slight variation on @GianPaolo's fine answer, which some may find easier to read:



      bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
      {
      return (v1 && v2 && v3 && v4) // scenario 1
      || (v1 && v2 && v3 && !v4) // scenario 2
      || (v1 && !v2 && !v3 && !v4); // scenario 3
      }

      if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
      {
      // ...
      }





      share|improve this answer




























        up vote
        6
        down vote













        Every answer is overly complex and difficult to read. The best solution to this is a switch() statement. It is both readable and makes adding/modifying additional cases simple. Compilers are good at optimising switch() statements too.



        switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
        {
        case 0b1111:
        // scenario 1
        break;

        case 0b0111:
        // scenario 2
        break;

        case 0b0001:
        // scenario 3
        break;

        default:
        // fault condition
        break;
        }


        You can of course use constants and OR them together in the case statements for even greater readability.






        share|improve this answer























        • Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
          – Simon F
          Dec 6 at 14:17


















        up vote
        5
        down vote













        I would also use shortcut variables for clarity. As noted earlier scenario 1 equals to scenario 2, because the value of bValue4 doesn't influence the truth of those two scenarios.



        bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
        bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)


        then your expression beomes:



        if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
        {
        // do something
        }
        else
        {
        // There is some error
        }


        Giving meaningful names to MAJORTRUE and MAJORFALSE variables (as well as actually to bValue* vars) would help a lot with readability and maintenance.






        share|improve this answer




























          up vote
          5
          down vote













          As suggested by mch, you could do:



          if(!((bValue1 && bValue2 && bValue3) || 
          (bValue1 && !bValue2 && !bValue3 && !bValue4))
          )


          where the first line covers the two first good cases, and the second line covers the last one.



          Live Demo, where I played around and it passes your cases.






          share|improve this answer






























            up vote
            5
            down vote













            Focus on readability of the problem, not the specific "if" statement.



            While this will produce more lines of code, and some may consider it either overkill or unnecessary. I'd suggest that abstracting your scenarios from the specific booleans is the best way to maintain readability.



            By splitting things into classes (feel free to just use functions, or whatever other tool you prefer) with understandable names - we can much more easily show the meanings behind each scenario. More importantly, in a system with many moving parts - it is easier to maintain and join into your existing systems (again, despite how much extra code is involed).



            #include <iostream>
            #include <vector>
            using namespace std;

            // These values would likely not come from a single struct in real life
            // Instead, they may be references to other booleans in other systems
            struct Values
            {
            bool bValue1; // These would be given better names in reality
            bool bValue2; // e.g. bDidTheCarCatchFire
            bool bValue3; // and bDidTheWindshieldFallOff
            bool bValue4;
            };

            class Scenario
            {
            public:
            Scenario(Values& values)
            : mValues(values) {}

            virtual operator bool() = 0;

            protected:
            Values& mValues;
            };

            // Names as examples of things that describe your "scenarios" more effectively
            class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
            {
            public:
            Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

            virtual operator bool()
            {
            return mValues.bValue1
            && mValues.bValue2
            && mValues.bValue3
            && mValues.bValue4;
            }
            };

            class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
            {
            public:
            Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

            virtual operator bool()
            {
            return mValues.bValue1
            && mValues.bValue2
            && mValues.bValue3
            && !mValues.bValue4;
            }
            };

            class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
            {
            public:
            Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

            virtual operator bool()
            {
            return mValues.bValue1
            && !mValues.bValue2
            && !mValues.bValue3
            && !mValues.bValue4;
            }
            };

            Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
            {
            for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
            {
            if (**it)
            {
            return *it;
            }
            }
            return NULL;
            }

            int main() {
            Values values = {true, true, true, true};
            std::vector<Scenario*> scenarios = {
            new Scenario1_TheCarWasNotDamagedAtAll(values),
            new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
            new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
            };

            Scenario* matchingScenario = findMatchingScenario(scenarios);

            if(matchingScenario)
            {
            std::cout << matchingScenario << " was a match" << std::endl;
            }
            else
            {
            std::cout << "No match" << std::endl;
            }

            // your code goes here
            return 0;
            }





            share|improve this answer

















            • 5




              At some point, verbosity starts to harm readability. I think this goes too far.
              – JollyJoker
              Dec 3 at 13:01






            • 2




              @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
              – Bilkokuya
              Dec 3 at 13:30


















            up vote
            4
            down vote













            I am denoting a, b, c, d for clarity, and A, B, C, D for complements



            bValue1 = a (!A)
            bValue2 = b (!B)
            bValue3 = c (!C)
            bValue4 = d (!D)


            Equation



            1 = abcd + abcD + aBCD
            = a (bcd + bcD + BCD)
            = a (bc + BCD)
            = a (bcd + D (b ^C))


            Use any equations that suits you.






            share|improve this answer




























              up vote
              4
              down vote













              Doing bitwise operation looks very clean and understandable.



              int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
              if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
              {
              //satisfying condition
              }





              share|improve this answer





















              • The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                – xtofl
                Dec 5 at 7:25


















              up vote
              4
              down vote













              It depends on what they represent.



              For example if 1 is a key, and 2 and 3 are two people who must agree (except if they agree on NOT they need a third person - 4 - to confirm) the most readable might be:



              1 &&
              (
              (2 && 3)
              ||
              ((!2 && !3) && !4)
              )


              by popular request:



              Key &&
              (
              (Alice && Bob)
              ||
              ((!Alice && !Bob) && !Charlie)
              )





              share|improve this answer



















              • 2




                You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                – jxh
                Dec 3 at 22:45






              • 1




                @jxh Those are the numbers OP used. I just removed the bValue.
                – ispiro
                Dec 3 at 23:26










              • @jxh I hope it's better now.
                – ispiro
                Dec 5 at 7:49


















              up vote
              3
              down vote













              If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
              {
              // you have a problem
              }



              • b1 must always be true

              • b2 must always equal b3

              • and b4 cannot be false
                if b2 (and b3) are true


              simple






              share|improve this answer




























                up vote
                3
                down vote













                Just a personal preference over the accepted answer, but I would write:



                bool valid = false;
                // scenario 1
                valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
                // scenario 2
                valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
                // scenario 3
                valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);





                share|improve this answer




























                  up vote
                  2
                  down vote













                  First, assuming you can only modify the scenario check, I would focus on readability and just wrap the check in a function so that you can just call if(ScenarioA()).





                  Now, assuming you actually want/need to optimize this, I would recommend converting the tightly linked Booleans into constant integers, and using bit operators on them



                  public class Options {
                  public const bool A = 2; // 0001
                  public const bool B = 4; // 0010
                  public const bool C = 16;// 0100
                  public const bool D = 32;// 1000
                  //public const bool N = 2^n; (up to n=32)
                  }

                  ...

                  public isScenario3(int options) {
                  int s3 = Options.A | Options.B | Options.C;
                  // for true if only s3 options are set
                  return options == s3;
                  // for true if s3 options are set
                  // return options & s3 == s3
                  }


                  This makes expressing the scenarios as easy as listing what is part of it, allows you to use a switch statement to jump to the right condition, and confuse fellow developers who have not seen this before. (C# RegexOptions uses this pattern for setting flags, I don't know if there is a c++ library example)






                  share|improve this answer





















                  • In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                    – Andrew Truckle
                    Dec 5 at 5:30


















                  up vote
                  2
                  down vote













                  Nested ifs could be easier to read for some people. Here is my version



                  bool check(int bValue1, int bValue2, int bValue3, int bValue4)
                  {
                  if (bValue1)
                  {
                  if (bValue2)
                  {
                  // scenario 1-2
                  return bValue3;
                  }
                  else
                  {
                  // scenario 3
                  return !bValue3 && !bValue4;
                  }
                  }

                  return false;
                  }





                  share|improve this answer





















                  • Another interesting variation. Thank you.
                    – Andrew Truckle
                    Dec 5 at 17:14










                  • Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                    – Dnomyar96
                    Dec 6 at 10:57












                  • @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                    – sardok
                    Dec 6 at 11:14


















                  up vote
                  1
                  down vote













                  You won't have to worry about invalid combinations of boolean flags if you get rid of the boolean flags.




                  The acceptable values are:



                           Scenario 1 | Scenario 2 | Scenario 3
                  bValue1: true | true | true
                  bValue2: true | true | false
                  bValue3: true | true | false
                  bValue4: true | false | false



                  You clearly have three states (scenarios). It'd be better to model that and to derive the boolean properties from those states, not the other way around.



                  enum State
                  {
                  scenario1,
                  scenario2,
                  scenario3,
                  };

                  inline bool isValue1(State s)
                  {
                  // (Well, this is kind of silly. Do you really need this flag?)
                  return true;
                  }

                  inline bool isValue2(State s)
                  {
                  switch (s)
                  {
                  case scenario1:
                  case scenario2:
                  return true;
                  case scenario3:
                  return false;
                  }
                  }

                  inline bool isValue3(State s)
                  {
                  // (This is silly too. Do you really need this flag?)
                  return isValue2(s);
                  }

                  inline bool isValue4(State s)
                  {
                  switch (s)
                  {
                  case scenario1:
                  return true;
                  case scenario2:
                  case scenario3:
                  return false;
                  }
                  }


                  This is definitely more code than in Gian Paolo's answer, but depending on your situation, this could be much more maintainable:




                  • There is a central set of functions to modify if additional boolean properties or scenarios are added.


                    • Adding properties requires adding only a single function.

                    • If adding a scenario, enabling compiler warnings about unhandled enum cases in switch statements will catch property-getters that don't handle that scenario.



                  • If you need to modify the boolean properties dynamically, you don't need to re-validate their combinations everywhere. Instead of toggling individual boolean flags (which could result in invalid combinations of flags), you instead would have a state machine that transitions from one scenario to another.


                  This approach also has the side benefit of being very efficient.






                  share|improve this answer






























                    up vote
                    0
                    down vote













                    My 2 cents: declare a variable sum (integer) so that



                    if(bValue1)
                    {
                    sum=sum+1;
                    }
                    if(bValue2)
                    {
                    sum=sum+2;
                    }
                    if(bValue3)
                    {
                    sum=sum+4;
                    }
                    if(bValue4)
                    {
                    sum=sum+8;
                    }


                    Check sum against the conditions you want and that's it.
                    This way you can add easily more conditions in the future keeping it quite straightforward to read.






                    share|improve this answer




























                      up vote
                      0
                      down vote













                      Several correct answers have been given to this question, but I would take a different view: if the code looks too complicated, something isn't quite right. The code will be difficult to debug and more likely to be "one-use-only".



                      In real life, when we find a situation like this:



                               Scenario 1 | Scenario 2 | Scenario 3
                      bValue1: true | true | true
                      bValue2: true | true | false
                      bValue3: true | true | false
                      bValue4: true | false | false


                      When four states are connected by such a precise pattern, we are dealing with the configuration of some "entity" in our model.



                      An extreme metaphor is how we would describe a "human beings" in a model, if we were not aware of their existence as unitary entities with components connected into specific degrees of freedom: we would have to describe independent states of of "torsoes", "arms", "legs" and "head" which would make it complicated to make sense of the system described. An immediate result would be unnaturally complicated boolean expressions.



                      Obviously, the way to reduce complexity is abstraction and a tool of choice in c++ is the object paradigm.



                      So the question is: why is there such a pattern? What is this and what does it represent?



                      Since we don't know the answer, we can fall back on a mathematical abstraction: the array: we have three scenarios, each of which is now an array.



                                      0   1   2   3
                      Scenario 1: T T T T
                      Scenario 2: T T T F
                      Scenario 3: T F F F


                      At which point you have your initial configuration. as an array. E.g. std::array has an equality operator:



                      At which point your syntax becomes:



                      if( myarray == scenario1 ) {
                      // arrays contents are the same

                      }
                      else if ( myarray == scenario2 ) {
                      // arrays contents are the same

                      }

                      else if ( myarray == scenario3 ) {
                      // arrays contents are the same

                      }
                      else {
                      // not the same

                      }


                      Just as the answer by Gian Paolo, it short, clear and easily verifiable/debuggable. In this case, we have delegated the details of the boolean expressions to the compiler.






                      share|improve this answer






























                        up vote
                        0
                        down vote













                        The accepted answer is fine when you've only got 3 cases, and where the logic for each is simple.



                        But if the logic for each case were more complicated, or there are many more cases, a far better option is to use the chain-of-responsibility design pattern.



                        You create a BaseValidator which contains a reference to a BaseValidator and a method to validate and a method to call the validation on the referenced validator.



                        class BaseValidator {
                        BaseValidator* nextValidator;

                        public:
                        BaseValidator() {
                        nextValidator = 0;
                        }

                        void link(BaseValidator validator) {
                        if (nextValidator) {
                        nextValidator->link(validator);
                        } else {
                        nextValidator = validator;
                        }
                        }

                        bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
                        if (nextValidator) {
                        return nextValidator->validate(v1, v2, v3, v4);
                        }

                        return false;
                        }

                        virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
                        return false;
                        }
                        }


                        Then you create a number of subclasses which inherit from the BaseValidator, overriding the validate method with the logic necessary for each validator.



                        class Validator1: public BaseValidator {
                        public:
                        bool validate(bool v1, bool v2, bool v3, bool v4) {
                        if (v1 && v2 && v3 && v4) {
                        return true;
                        }

                        return nextValidator->callLinkedValidator(v1, v2, v3, v4);
                        }
                        }


                        Then using it is simple, instantiate each of your validators, and set each of them to be the root of the others:



                        Validator1 firstValidator = new Validator1();
                        Validator2 secondValidator = new Validator2();
                        Validator3 thirdValidator = new Validator3();
                        firstValidator.link(secondValidator);
                        firstValidator.link(thirdValidator);
                        if (firstValidator.validate(value1, value2, value3, value4)) { ... }


                        In essence, each validation case has its own class which is responsible for (a) determining if the validation matches that case, and (b) sending the validation to someone else in the chain if it is not.



                        Please note that I am not familiar with C++. I've tried to match the syntax from some examples I found online, but if this does not work, treat it more like pseudocode. I also have a complete working Python example below that can be used as a basis if preferred.



                        class BaseValidator:
                        def __init__(self):
                        self.nextValidator = 0

                        def link(self, validator):
                        if (self.nextValidator):
                        self.nextValidator.link(validator)
                        else:
                        self.nextValidator = validator

                        def callLinkedValidator(self, v1, v2, v3, v4):
                        if (self.nextValidator):
                        return self.nextValidator.validate(v1, v2, v3, v4)

                        return False

                        def validate(self, v1, v2, v3, v4):
                        return False

                        class Validator1(BaseValidator):
                        def validate(self, v1, v2, v3, v4):
                        if (v1 and v2 and v3 and v4):
                        return True
                        return self.callLinkedValidator(v1, v2, v3, v4)

                        class Validator2(BaseValidator):
                        def validate(self, v1, v2, v3, v4):
                        if (v1 and v2 and v3 and not v4):
                        return True
                        return self.callLinkedValidator(v1, v2, v3, v4)

                        class Validator3(BaseValidator):
                        def validate(self, v1, v2, v3, v4):
                        if (v1 and not v2 and not v3 and not v4):
                        return True
                        return self.callLinkedValidator(v1, v2, v3, v4)

                        firstValidator = Validator1()
                        secondValidator = Validator2()
                        thirdValidator = Validator3()
                        firstValidator.link(secondValidator)
                        firstValidator.link(thirdValidator)
                        print(firstValidator.validate(False, False, True, False))


                        Again, you may find this overkill for your specific example, but it creates much cleaner code if you end up with a far more complicated set of cases that need to be met.






                        share|improve this answer




























                          up vote
                          -2
                          down vote













                          A simple approach is finding the answer that you think are acceptable.



                          Yes = (boolean1 && boolean2 && boolean3 && boolean4) + + ...



                          Now if possible simplify the equation using boolean algebra.



                          like in this case, acceptable1 and 2 combine to (boolean1 && boolean2 && boolean3).



                          Hence the final answer is:



                          (boolean1 && boolean2 && boolean3) || 
                          ((boolean1 && !boolean2 && !boolean3 && !boolean4)





                          share|improve this answer






























                            up vote
                            -3
                            down vote













                            use bit field:



                            unoin {
                            struct {
                            bool b1: 1;
                            bool b2: 1;
                            bool b3: 1;
                            bool b4: 1;
                            } b;
                            int i;
                            } u;

                            // set:
                            u.b.b1=true;
                            ...

                            // test
                            if (u.i == 0x0f) {...}
                            if (u.i == 0x0e) {...}
                            if (u.i == 0x08) {...}


                            PS:



                            That's a big pity to CPPers'. But, UB is not my worry, check it at http://coliru.stacked-crooked.com/a/2b556abfc28574a1.






                            share|improve this answer



















                            • 2




                              This causes UB due to accessing an inactive union field.
                              – HolyBlackCat
                              Dec 4 at 13:44










                            • Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                              – Swift - Friday Pie
                              Dec 4 at 13:45












                            • I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                              – supercat
                              Dec 4 at 19:35











                            Your Answer






                            StackExchange.ifUsing("editor", function () {
                            StackExchange.using("externalEditor", function () {
                            StackExchange.using("snippets", function () {
                            StackExchange.snippets.init();
                            });
                            });
                            }, "code-snippets");

                            StackExchange.ready(function() {
                            var channelOptions = {
                            tags: "".split(" "),
                            id: "1"
                            };
                            initTagRenderer("".split(" "), "".split(" "), channelOptions);

                            StackExchange.using("externalEditor", function() {
                            // Have to fire editor after snippets, if snippets enabled
                            if (StackExchange.settings.snippets.snippetsEnabled) {
                            StackExchange.using("snippets", function() {
                            createEditor();
                            });
                            }
                            else {
                            createEditor();
                            }
                            });

                            function createEditor() {
                            StackExchange.prepareEditor({
                            heartbeatType: 'answer',
                            convertImagesToLinks: true,
                            noModals: true,
                            showLowRepImageUploadWarning: true,
                            reputationToPostImages: 10,
                            bindNavPrevention: true,
                            postfix: "",
                            imageUploader: {
                            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                            allowUrls: true
                            },
                            onDemand: true,
                            discardSelector: ".discard-answer"
                            ,immediatelyShowMarkdownHelp:true
                            });


                            }
                            });














                            draft saved

                            draft discarded


















                            StackExchange.ready(
                            function () {
                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53591559%2fhow-to-improve-logic-to-check-whether-4-boolean-values-match-some-cases%23new-answer', 'question_page');
                            }
                            );

                            Post as a guest















                            Required, but never shown

























                            30 Answers
                            30






                            active

                            oldest

                            votes








                            30 Answers
                            30






                            active

                            oldest

                            votes









                            active

                            oldest

                            votes






                            active

                            oldest

                            votes








                            up vote
                            182
                            down vote



                            accepted










                            I would aim for readability: you have just 3 scenario, deal with them with 3 separate ifs:



                            bool valid = false;
                            if (bValue1 && bValue2 && bValue3 && bValue4)
                            valid = true; //scenario 1
                            else if (bValue1 && bValue2 && bValue3 && !bValue4)
                            valid = true; //scenario 2
                            else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                            valid = true; //scenario 3


                            Easy to read and debug, IMHO. Also, you can assign a variable whichScenario while proceeding with the if.



                            With just 3 scenarios, I would not go with something such "if the first 3 values are true I can avoid check the forth value": it's going to make your code harder to read and maintain.



                            Not an elegant solution maybe surely, but in this case is ok: easy and readable.



                            If your logic gets more complicated, throw away that code and consider using something more to store different available scenarios (as Zladeck is suggesting).



                            I really love the first suggestion given in this answer: easy to read, not error prone, maintainable



                            (Almost) off topic:



                            I don't write lot of answers here at StackOverflow. It's really funny that the above accepted answer is by far the most appreciated answer in my history (never had more than 5-10 upvotes before I think) while actually is not what I usually think is the "right" way to do it.



                            But simplicity is often "the right way to do it", many people seems to think this and I should think it more than I do :)






                            share|improve this answer



















                            • 8




                              Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                              – gsamaras
                              Dec 3 at 10:34








                            • 1




                              sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                              – Gian Paolo
                              Dec 3 at 10:49






                            • 4




                              This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                              – Leushenko
                              Dec 3 at 11:13








                            • 3




                              I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                              – Martijn
                              Dec 3 at 14:36






                            • 2




                              FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                              – Dancrumb
                              Dec 3 at 19:48















                            up vote
                            182
                            down vote



                            accepted










                            I would aim for readability: you have just 3 scenario, deal with them with 3 separate ifs:



                            bool valid = false;
                            if (bValue1 && bValue2 && bValue3 && bValue4)
                            valid = true; //scenario 1
                            else if (bValue1 && bValue2 && bValue3 && !bValue4)
                            valid = true; //scenario 2
                            else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                            valid = true; //scenario 3


                            Easy to read and debug, IMHO. Also, you can assign a variable whichScenario while proceeding with the if.



                            With just 3 scenarios, I would not go with something such "if the first 3 values are true I can avoid check the forth value": it's going to make your code harder to read and maintain.



                            Not an elegant solution maybe surely, but in this case is ok: easy and readable.



                            If your logic gets more complicated, throw away that code and consider using something more to store different available scenarios (as Zladeck is suggesting).



                            I really love the first suggestion given in this answer: easy to read, not error prone, maintainable



                            (Almost) off topic:



                            I don't write lot of answers here at StackOverflow. It's really funny that the above accepted answer is by far the most appreciated answer in my history (never had more than 5-10 upvotes before I think) while actually is not what I usually think is the "right" way to do it.



                            But simplicity is often "the right way to do it", many people seems to think this and I should think it more than I do :)






                            share|improve this answer



















                            • 8




                              Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                              – gsamaras
                              Dec 3 at 10:34








                            • 1




                              sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                              – Gian Paolo
                              Dec 3 at 10:49






                            • 4




                              This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                              – Leushenko
                              Dec 3 at 11:13








                            • 3




                              I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                              – Martijn
                              Dec 3 at 14:36






                            • 2




                              FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                              – Dancrumb
                              Dec 3 at 19:48













                            up vote
                            182
                            down vote



                            accepted







                            up vote
                            182
                            down vote



                            accepted






                            I would aim for readability: you have just 3 scenario, deal with them with 3 separate ifs:



                            bool valid = false;
                            if (bValue1 && bValue2 && bValue3 && bValue4)
                            valid = true; //scenario 1
                            else if (bValue1 && bValue2 && bValue3 && !bValue4)
                            valid = true; //scenario 2
                            else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                            valid = true; //scenario 3


                            Easy to read and debug, IMHO. Also, you can assign a variable whichScenario while proceeding with the if.



                            With just 3 scenarios, I would not go with something such "if the first 3 values are true I can avoid check the forth value": it's going to make your code harder to read and maintain.



                            Not an elegant solution maybe surely, but in this case is ok: easy and readable.



                            If your logic gets more complicated, throw away that code and consider using something more to store different available scenarios (as Zladeck is suggesting).



                            I really love the first suggestion given in this answer: easy to read, not error prone, maintainable



                            (Almost) off topic:



                            I don't write lot of answers here at StackOverflow. It's really funny that the above accepted answer is by far the most appreciated answer in my history (never had more than 5-10 upvotes before I think) while actually is not what I usually think is the "right" way to do it.



                            But simplicity is often "the right way to do it", many people seems to think this and I should think it more than I do :)






                            share|improve this answer














                            I would aim for readability: you have just 3 scenario, deal with them with 3 separate ifs:



                            bool valid = false;
                            if (bValue1 && bValue2 && bValue3 && bValue4)
                            valid = true; //scenario 1
                            else if (bValue1 && bValue2 && bValue3 && !bValue4)
                            valid = true; //scenario 2
                            else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                            valid = true; //scenario 3


                            Easy to read and debug, IMHO. Also, you can assign a variable whichScenario while proceeding with the if.



                            With just 3 scenarios, I would not go with something such "if the first 3 values are true I can avoid check the forth value": it's going to make your code harder to read and maintain.



                            Not an elegant solution maybe surely, but in this case is ok: easy and readable.



                            If your logic gets more complicated, throw away that code and consider using something more to store different available scenarios (as Zladeck is suggesting).



                            I really love the first suggestion given in this answer: easy to read, not error prone, maintainable



                            (Almost) off topic:



                            I don't write lot of answers here at StackOverflow. It's really funny that the above accepted answer is by far the most appreciated answer in my history (never had more than 5-10 upvotes before I think) while actually is not what I usually think is the "right" way to do it.



                            But simplicity is often "the right way to do it", many people seems to think this and I should think it more than I do :)







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 8 at 21:48

























                            answered Dec 3 at 10:29









                            Gian Paolo

                            3,2352925




                            3,2352925








                            • 8




                              Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                              – gsamaras
                              Dec 3 at 10:34








                            • 1




                              sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                              – Gian Paolo
                              Dec 3 at 10:49






                            • 4




                              This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                              – Leushenko
                              Dec 3 at 11:13








                            • 3




                              I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                              – Martijn
                              Dec 3 at 14:36






                            • 2




                              FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                              – Dancrumb
                              Dec 3 at 19:48














                            • 8




                              Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                              – gsamaras
                              Dec 3 at 10:34








                            • 1




                              sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                              – Gian Paolo
                              Dec 3 at 10:49






                            • 4




                              This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                              – Leushenko
                              Dec 3 at 11:13








                            • 3




                              I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                              – Martijn
                              Dec 3 at 14:36






                            • 2




                              FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                              – Dancrumb
                              Dec 3 at 19:48








                            8




                            8




                            Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                            – gsamaras
                            Dec 3 at 10:34






                            Damn, simplicity is a virtue. I think this is the best answer, far better than mine or any other obfuscating technique! Bravo!
                            – gsamaras
                            Dec 3 at 10:34






                            1




                            1




                            sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                            – Gian Paolo
                            Dec 3 at 10:49




                            sure @hessamhedieh, it's ok only for a small number of available scenario. as I said, if things get more complicated, better look for something else
                            – Gian Paolo
                            Dec 3 at 10:49




                            4




                            4




                            This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                            – Leushenko
                            Dec 3 at 11:13






                            This can be simplified further by stacking all conditions into the initializer for valid and separating them with ||, rather than mutating valid within separate statement blocks. I can't put an example in the comment but you can vertically align the || operators along the left to make this very clear; the individual conditions are already parenthesized as much as they need to be (for if) so you don't need to add any characters to the expressions beyond what is already there.
                            – Leushenko
                            Dec 3 at 11:13






                            3




                            3




                            I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                            – Martijn
                            Dec 3 at 14:36




                            I'd've wrapped it in a if($bValue1) as that always has to be true, technically allowing some minor performance improvement (though we're talking about negligable amounts here).
                            – Martijn
                            Dec 3 at 14:36




                            2




                            2




                            FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                            – Dancrumb
                            Dec 3 at 19:48




                            FWIW: there are only 2 scenarios: the first 2 are the same scenario and do not depend on bValue4
                            – Dancrumb
                            Dec 3 at 19:48












                            up vote
                            105
                            down vote













                            I would aim for simplicity and readability.



                            bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
                            bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1 || scenario2 || scenario3) {
                            // Do whatever.
                            }


                            Make sure to replace the names of the scenarios as well as the names of the flags with something descriptive. If it makes sense for your specific problem, you could consider this alternative:



                            bool scenario1or2 = bValue1 && bValue2 && bValue3;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1or2 || scenario3) {
                            // Do whatever.
                            }


                            What's important here is not predicate logic. It's describing your domain and clearly expressing your intent. The key here is to give all inputs and intermediary variables good names. If you can't find good variable names, it may be a sign that you are describing the problem in the wrong way.






                            share|improve this answer



















                            • 3




                              +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                              – RedFilter
                              Dec 4 at 15:47






                            • 2




                              Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                              – Andrew Truckle
                              Dec 5 at 5:28






                            • 1




                              +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                              – Andreas
                              Dec 5 at 13:07















                            up vote
                            105
                            down vote













                            I would aim for simplicity and readability.



                            bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
                            bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1 || scenario2 || scenario3) {
                            // Do whatever.
                            }


                            Make sure to replace the names of the scenarios as well as the names of the flags with something descriptive. If it makes sense for your specific problem, you could consider this alternative:



                            bool scenario1or2 = bValue1 && bValue2 && bValue3;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1or2 || scenario3) {
                            // Do whatever.
                            }


                            What's important here is not predicate logic. It's describing your domain and clearly expressing your intent. The key here is to give all inputs and intermediary variables good names. If you can't find good variable names, it may be a sign that you are describing the problem in the wrong way.






                            share|improve this answer



















                            • 3




                              +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                              – RedFilter
                              Dec 4 at 15:47






                            • 2




                              Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                              – Andrew Truckle
                              Dec 5 at 5:28






                            • 1




                              +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                              – Andreas
                              Dec 5 at 13:07













                            up vote
                            105
                            down vote










                            up vote
                            105
                            down vote









                            I would aim for simplicity and readability.



                            bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
                            bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1 || scenario2 || scenario3) {
                            // Do whatever.
                            }


                            Make sure to replace the names of the scenarios as well as the names of the flags with something descriptive. If it makes sense for your specific problem, you could consider this alternative:



                            bool scenario1or2 = bValue1 && bValue2 && bValue3;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1or2 || scenario3) {
                            // Do whatever.
                            }


                            What's important here is not predicate logic. It's describing your domain and clearly expressing your intent. The key here is to give all inputs and intermediary variables good names. If you can't find good variable names, it may be a sign that you are describing the problem in the wrong way.






                            share|improve this answer














                            I would aim for simplicity and readability.



                            bool scenario1 = bValue1 && bValue2 && bValue3 && bValue4;
                            bool scenario2 = bValue1 && bValue2 && bValue3 && !bValue4;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1 || scenario2 || scenario3) {
                            // Do whatever.
                            }


                            Make sure to replace the names of the scenarios as well as the names of the flags with something descriptive. If it makes sense for your specific problem, you could consider this alternative:



                            bool scenario1or2 = bValue1 && bValue2 && bValue3;
                            bool scenario3 = bValue1 && !bValue2 && !bValue3 && !bValue4;

                            if (scenario1or2 || scenario3) {
                            // Do whatever.
                            }


                            What's important here is not predicate logic. It's describing your domain and clearly expressing your intent. The key here is to give all inputs and intermediary variables good names. If you can't find good variable names, it may be a sign that you are describing the problem in the wrong way.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 11 at 14:47

























                            answered Dec 4 at 13:22









                            Anders

                            5,44463052




                            5,44463052








                            • 3




                              +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                              – RedFilter
                              Dec 4 at 15:47






                            • 2




                              Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                              – Andrew Truckle
                              Dec 5 at 5:28






                            • 1




                              +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                              – Andreas
                              Dec 5 at 13:07














                            • 3




                              +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                              – RedFilter
                              Dec 4 at 15:47






                            • 2




                              Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                              – Andrew Truckle
                              Dec 5 at 5:28






                            • 1




                              +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                              – Andreas
                              Dec 5 at 13:07








                            3




                            3




                            +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                            – RedFilter
                            Dec 4 at 15:47




                            +1 I am surprised there are 0 upvotes here. The solution is short, self-documenting (no comments needed), and easy to modify with little chance of introducing bugs. A clear favourite.
                            – RedFilter
                            Dec 4 at 15:47




                            2




                            2




                            Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                            – Andrew Truckle
                            Dec 5 at 5:28




                            Thanks for this. In my solution that I provided as an answer I also took onboard what you said. The only different being that I moved the scenarios into methods.
                            – Andrew Truckle
                            Dec 5 at 5:28




                            1




                            1




                            +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                            – Andreas
                            Dec 5 at 13:07




                            +1 This is what I would have done as well. Just like @RedFilter points out, and in contrast to the accepted answer, this is self-documenting. Giving the scenarios their own names in a separate step is much more readable.
                            – Andreas
                            Dec 5 at 13:07










                            up vote
                            96
                            down vote













                            We can use a Karnaugh map and reduce your scenarios to a logical equation.
                            I have used the Online Karnaugh map solver with circuit for 4 variables.



                            enter image description here



                            This yields:



                            enter image description here



                            Changing A, B, C, D to bValue1, bValue2, bValue3, bValue4, this is nothing but:



                            bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4


                            So your if statement becomes:



                            if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
                            {
                            // There is some error
                            }



                            • Karnaugh Maps are particularly useful when you have many variables and many conditions which should evaluate true.

                            • After reducing the true scenarios to a logical equation, adding relevant comments indicating the true scenarios is good practice.






                            share|improve this answer



















                            • 91




                              Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:00






                            • 20




                              @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                              – P.W
                              Dec 3 at 11:05






                            • 10




                              I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:09






                            • 7




                              I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                              – Maciej Piechotka
                              Dec 3 at 11:31






                            • 25




                              @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                              – Dukeling
                              Dec 3 at 14:21

















                            up vote
                            96
                            down vote













                            We can use a Karnaugh map and reduce your scenarios to a logical equation.
                            I have used the Online Karnaugh map solver with circuit for 4 variables.



                            enter image description here



                            This yields:



                            enter image description here



                            Changing A, B, C, D to bValue1, bValue2, bValue3, bValue4, this is nothing but:



                            bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4


                            So your if statement becomes:



                            if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
                            {
                            // There is some error
                            }



                            • Karnaugh Maps are particularly useful when you have many variables and many conditions which should evaluate true.

                            • After reducing the true scenarios to a logical equation, adding relevant comments indicating the true scenarios is good practice.






                            share|improve this answer



















                            • 91




                              Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:00






                            • 20




                              @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                              – P.W
                              Dec 3 at 11:05






                            • 10




                              I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:09






                            • 7




                              I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                              – Maciej Piechotka
                              Dec 3 at 11:31






                            • 25




                              @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                              – Dukeling
                              Dec 3 at 14:21















                            up vote
                            96
                            down vote










                            up vote
                            96
                            down vote









                            We can use a Karnaugh map and reduce your scenarios to a logical equation.
                            I have used the Online Karnaugh map solver with circuit for 4 variables.



                            enter image description here



                            This yields:



                            enter image description here



                            Changing A, B, C, D to bValue1, bValue2, bValue3, bValue4, this is nothing but:



                            bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4


                            So your if statement becomes:



                            if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
                            {
                            // There is some error
                            }



                            • Karnaugh Maps are particularly useful when you have many variables and many conditions which should evaluate true.

                            • After reducing the true scenarios to a logical equation, adding relevant comments indicating the true scenarios is good practice.






                            share|improve this answer














                            We can use a Karnaugh map and reduce your scenarios to a logical equation.
                            I have used the Online Karnaugh map solver with circuit for 4 variables.



                            enter image description here



                            This yields:



                            enter image description here



                            Changing A, B, C, D to bValue1, bValue2, bValue3, bValue4, this is nothing but:



                            bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4


                            So your if statement becomes:



                            if(!(bValue1 && bValue2 && bValue3 || bValue1 && !bValue2 && !bValue3 && !bValue4))
                            {
                            // There is some error
                            }



                            • Karnaugh Maps are particularly useful when you have many variables and many conditions which should evaluate true.

                            • After reducing the true scenarios to a logical equation, adding relevant comments indicating the true scenarios is good practice.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 4 at 6:01

























                            answered Dec 3 at 10:38









                            P.W

                            10.3k2742




                            10.3k2742








                            • 91




                              Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:00






                            • 20




                              @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                              – P.W
                              Dec 3 at 11:05






                            • 10




                              I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:09






                            • 7




                              I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                              – Maciej Piechotka
                              Dec 3 at 11:31






                            • 25




                              @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                              – Dukeling
                              Dec 3 at 14:21
















                            • 91




                              Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:00






                            • 20




                              @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                              – P.W
                              Dec 3 at 11:05






                            • 10




                              I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                              – Zdeslav Vojkovic
                              Dec 3 at 11:09






                            • 7




                              I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                              – Maciej Piechotka
                              Dec 3 at 11:31






                            • 25




                              @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                              – Dukeling
                              Dec 3 at 14:21










                            91




                            91




                            Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                            – Zdeslav Vojkovic
                            Dec 3 at 11:00




                            Though technically correct, this code requires a lot of comments in order to be edited by another developer few months later.
                            – Zdeslav Vojkovic
                            Dec 3 at 11:00




                            20




                            20




                            @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                            – P.W
                            Dec 3 at 11:05




                            @ZdeslavVojkovic: I would just add a comment with the equation. //!(ABC + AB'C'D') (By K-Map logic). That would be a good time for the developer to learn K-Maps if he doesn't already know them.
                            – P.W
                            Dec 3 at 11:05




                            10




                            10




                            I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                            – Zdeslav Vojkovic
                            Dec 3 at 11:09




                            I agree with that, but IMO the problem is that it doesn't map clearly to the problem domain, i.e. how each condition maps to specific scenario which makes it hard to change/extend. What happens when there are E and F conditions and 4 new scenarios? How long it takes to update this if statement correctly? How does code review check if it is ok or not? The problem is not with the technical side but with "business" side.
                            – Zdeslav Vojkovic
                            Dec 3 at 11:09




                            7




                            7




                            I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                            – Maciej Piechotka
                            Dec 3 at 11:31




                            I think you can factor out A: ABC + AB'C'D' = A(BC + B'C'D') (this can be even factored to A(B ^ C)'(C + D') though I'd be careful with calling this 'simplification').
                            – Maciej Piechotka
                            Dec 3 at 11:31




                            25




                            25




                            @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                            – Dukeling
                            Dec 3 at 14:21






                            @P.W That comment seems about as understandable as the code, and is thus a bit pointless. A better comment would explain how you actually came up with that equation, i.e. that the statement should trigger for TTTT, TTTF and TFFF. At that point you might as well just write those three conditions in the code instead and not need an explanation at all.
                            – Dukeling
                            Dec 3 at 14:21












                            up vote
                            52
                            down vote













                            The real question here is: what happens when another developer (or even author) must change this code few months later.



                            I would suggest modelling this as bit flags:



                            const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
                            const int SCENARIO_2 = 0x0E; // 0b1110
                            const int SCENARIO_3 = 0x08; // 0b1000

                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = false;
                            bool bValue4 = false;

                            // boolean -> int conversion is covered by standard and produces 0/1
                            int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                            bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
                            std::cout << (match ? "ok" : "error");


                            If there are many more scenarios or more flags, a table approach is more readable and extensible than using flags. Supporting a new scenario requires just another row in the table.



                            int scenarios[3][4] = {
                            {true, true, true, true},
                            {true, true, true, false},
                            {true, false, false, false},
                            };

                            int main()
                            {
                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = true;
                            bool bValue4 = true;
                            bool match = false;

                            // depending on compiler, prefer std::size()/_countof instead of magic value of 4
                            for (int i = 0; i < 4 && !match; ++i) {
                            auto current = scenarios[i];
                            match = bValue1 == current[0] &&
                            bValue2 == current[1] &&
                            bValue3 == current[2] &&
                            bValue4 == current[3];
                            }

                            std::cout << (match ? "ok" : "error");
                            }





                            share|improve this answer



















                            • 4




                              Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                              – Adam Zahran
                              Dec 3 at 10:35






                            • 6




                              IMO, table is the best approach as it scales better with additional scenarios and flags.
                              – Zdeslav Vojkovic
                              Dec 3 at 10:44










                            • I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                              – Gian Paolo
                              Dec 3 at 12:52








                            • 4




                              If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                              – Dukeling
                              Dec 3 at 14:25








                            • 2




                              I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                              – Konrad Rudolph
                              Dec 3 at 22:25

















                            up vote
                            52
                            down vote













                            The real question here is: what happens when another developer (or even author) must change this code few months later.



                            I would suggest modelling this as bit flags:



                            const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
                            const int SCENARIO_2 = 0x0E; // 0b1110
                            const int SCENARIO_3 = 0x08; // 0b1000

                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = false;
                            bool bValue4 = false;

                            // boolean -> int conversion is covered by standard and produces 0/1
                            int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                            bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
                            std::cout << (match ? "ok" : "error");


                            If there are many more scenarios or more flags, a table approach is more readable and extensible than using flags. Supporting a new scenario requires just another row in the table.



                            int scenarios[3][4] = {
                            {true, true, true, true},
                            {true, true, true, false},
                            {true, false, false, false},
                            };

                            int main()
                            {
                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = true;
                            bool bValue4 = true;
                            bool match = false;

                            // depending on compiler, prefer std::size()/_countof instead of magic value of 4
                            for (int i = 0; i < 4 && !match; ++i) {
                            auto current = scenarios[i];
                            match = bValue1 == current[0] &&
                            bValue2 == current[1] &&
                            bValue3 == current[2] &&
                            bValue4 == current[3];
                            }

                            std::cout << (match ? "ok" : "error");
                            }





                            share|improve this answer



















                            • 4




                              Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                              – Adam Zahran
                              Dec 3 at 10:35






                            • 6




                              IMO, table is the best approach as it scales better with additional scenarios and flags.
                              – Zdeslav Vojkovic
                              Dec 3 at 10:44










                            • I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                              – Gian Paolo
                              Dec 3 at 12:52








                            • 4




                              If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                              – Dukeling
                              Dec 3 at 14:25








                            • 2




                              I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                              – Konrad Rudolph
                              Dec 3 at 22:25















                            up vote
                            52
                            down vote










                            up vote
                            52
                            down vote









                            The real question here is: what happens when another developer (or even author) must change this code few months later.



                            I would suggest modelling this as bit flags:



                            const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
                            const int SCENARIO_2 = 0x0E; // 0b1110
                            const int SCENARIO_3 = 0x08; // 0b1000

                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = false;
                            bool bValue4 = false;

                            // boolean -> int conversion is covered by standard and produces 0/1
                            int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                            bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
                            std::cout << (match ? "ok" : "error");


                            If there are many more scenarios or more flags, a table approach is more readable and extensible than using flags. Supporting a new scenario requires just another row in the table.



                            int scenarios[3][4] = {
                            {true, true, true, true},
                            {true, true, true, false},
                            {true, false, false, false},
                            };

                            int main()
                            {
                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = true;
                            bool bValue4 = true;
                            bool match = false;

                            // depending on compiler, prefer std::size()/_countof instead of magic value of 4
                            for (int i = 0; i < 4 && !match; ++i) {
                            auto current = scenarios[i];
                            match = bValue1 == current[0] &&
                            bValue2 == current[1] &&
                            bValue3 == current[2] &&
                            bValue4 == current[3];
                            }

                            std::cout << (match ? "ok" : "error");
                            }





                            share|improve this answer














                            The real question here is: what happens when another developer (or even author) must change this code few months later.



                            I would suggest modelling this as bit flags:



                            const int SCENARIO_1 = 0x0F; // 0b1111 if using c++14
                            const int SCENARIO_2 = 0x0E; // 0b1110
                            const int SCENARIO_3 = 0x08; // 0b1000

                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = false;
                            bool bValue4 = false;

                            // boolean -> int conversion is covered by standard and produces 0/1
                            int scenario = bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                            bool match = scenario == SCENARIO_1 || scenario == SCENARIO_2 || scenario == SCENARIO_3;
                            std::cout << (match ? "ok" : "error");


                            If there are many more scenarios or more flags, a table approach is more readable and extensible than using flags. Supporting a new scenario requires just another row in the table.



                            int scenarios[3][4] = {
                            {true, true, true, true},
                            {true, true, true, false},
                            {true, false, false, false},
                            };

                            int main()
                            {
                            bool bValue1 = true;
                            bool bValue2 = false;
                            bool bValue3 = true;
                            bool bValue4 = true;
                            bool match = false;

                            // depending on compiler, prefer std::size()/_countof instead of magic value of 4
                            for (int i = 0; i < 4 && !match; ++i) {
                            auto current = scenarios[i];
                            match = bValue1 == current[0] &&
                            bValue2 == current[1] &&
                            bValue3 == current[2] &&
                            bValue4 == current[3];
                            }

                            std::cout << (match ? "ok" : "error");
                            }






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Dec 5 at 5:36









                            Andrew Truckle

                            5,45142246




                            5,45142246










                            answered Dec 3 at 10:33









                            Zdeslav Vojkovic

                            12.5k1836




                            12.5k1836








                            • 4




                              Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                              – Adam Zahran
                              Dec 3 at 10:35






                            • 6




                              IMO, table is the best approach as it scales better with additional scenarios and flags.
                              – Zdeslav Vojkovic
                              Dec 3 at 10:44










                            • I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                              – Gian Paolo
                              Dec 3 at 12:52








                            • 4




                              If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                              – Dukeling
                              Dec 3 at 14:25








                            • 2




                              I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                              – Konrad Rudolph
                              Dec 3 at 22:25
















                            • 4




                              Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                              – Adam Zahran
                              Dec 3 at 10:35






                            • 6




                              IMO, table is the best approach as it scales better with additional scenarios and flags.
                              – Zdeslav Vojkovic
                              Dec 3 at 10:44










                            • I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                              – Gian Paolo
                              Dec 3 at 12:52








                            • 4




                              If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                              – Dukeling
                              Dec 3 at 14:25








                            • 2




                              I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                              – Konrad Rudolph
                              Dec 3 at 22:25










                            4




                            4




                            Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                            – Adam Zahran
                            Dec 3 at 10:35




                            Not the most maintainable but definitely simplifies the if condition. So leaving a few comments around the bitwise operations will be an absolute necessity here imo.
                            – Adam Zahran
                            Dec 3 at 10:35




                            6




                            6




                            IMO, table is the best approach as it scales better with additional scenarios and flags.
                            – Zdeslav Vojkovic
                            Dec 3 at 10:44




                            IMO, table is the best approach as it scales better with additional scenarios and flags.
                            – Zdeslav Vojkovic
                            Dec 3 at 10:44












                            I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                            – Gian Paolo
                            Dec 3 at 12:52






                            I like your first solution, easy to read and open to modification. I would make 2 improvements: 1: assign values to scenarioX with an explicit indication of boolean values used, e.g. SCENARIO_2 = true << 3 | true << 2 | true << 1 | false; 2: avoid SCENARIO_X variables and then store all available scenarios in a <std::set<int>. Adding a scenario is going to be just something as mySet.insert( true << 3 | false << 2 | true << 1 | false; maybe a little overkill for just 3 scenario, OP accepted the quick, dirty and easy solution I suggested in my answer.
                            – Gian Paolo
                            Dec 3 at 12:52






                            4




                            4




                            If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                            – Dukeling
                            Dec 3 at 14:25






                            If you're using C++14 or higher, I'd suggest instead using binary literals for the first solution - 0b1111, 0b1110 and 0b1000 is much clearer. You can probably also simplify this a bit using the standard library (std::find?).
                            – Dukeling
                            Dec 3 at 14:25






                            2




                            2




                            I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                            – Konrad Rudolph
                            Dec 3 at 22:25






                            I find that binary literals here would be a minimal requirement to make the first code clean. In its current form it’s completely cryptic. Descriptive identifiers might help but I’m not even sure about that. In fact, the bit operations to produce the scenario value strike me as unnecessarily error-prone.
                            – Konrad Rudolph
                            Dec 3 at 22:25












                            up vote
                            22
                            down vote













                            My previous answer is already the accepted answer, I add something here that I think is both readable, easy and in this case open to future modifications:



                            Starting with @ZdeslavVojkovic answer (which I find quite good), I came up with this:



                            #include <iostream>
                            #include <set>

                            //using namespace std;

                            int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                            {
                            return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                            }
                            bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                            {
                            std::set<int> validScenarios;
                            validScenarios.insert(GetScenarioInt(true, true, true, true));
                            validScenarios.insert(GetScenarioInt(true, true, true, false));
                            validScenarios.insert(GetScenarioInt(true, false, false, false));

                            int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

                            return validScenarios.find(currentScenario) != validScenarios.end();
                            }

                            int main()
                            {
                            std::cout << IsValidScenario(true, true, true, false) << "n"; // expected = true;
                            std::cout << IsValidScenario(true, true, false, false) << "n"; // expected = false;

                            return 0;
                            }


                            See it at work here



                            Well, that's the "elegant and maintainable" (IMHO) solution I usually aim to, but really, for the OP case, my previous "bunch of ifs" answer fits better the OP requirements, even if it's not elegant nor maintainable.






                            share|improve this answer



























                              up vote
                              22
                              down vote













                              My previous answer is already the accepted answer, I add something here that I think is both readable, easy and in this case open to future modifications:



                              Starting with @ZdeslavVojkovic answer (which I find quite good), I came up with this:



                              #include <iostream>
                              #include <set>

                              //using namespace std;

                              int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                              {
                              return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                              }
                              bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                              {
                              std::set<int> validScenarios;
                              validScenarios.insert(GetScenarioInt(true, true, true, true));
                              validScenarios.insert(GetScenarioInt(true, true, true, false));
                              validScenarios.insert(GetScenarioInt(true, false, false, false));

                              int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

                              return validScenarios.find(currentScenario) != validScenarios.end();
                              }

                              int main()
                              {
                              std::cout << IsValidScenario(true, true, true, false) << "n"; // expected = true;
                              std::cout << IsValidScenario(true, true, false, false) << "n"; // expected = false;

                              return 0;
                              }


                              See it at work here



                              Well, that's the "elegant and maintainable" (IMHO) solution I usually aim to, but really, for the OP case, my previous "bunch of ifs" answer fits better the OP requirements, even if it's not elegant nor maintainable.






                              share|improve this answer

























                                up vote
                                22
                                down vote










                                up vote
                                22
                                down vote









                                My previous answer is already the accepted answer, I add something here that I think is both readable, easy and in this case open to future modifications:



                                Starting with @ZdeslavVojkovic answer (which I find quite good), I came up with this:



                                #include <iostream>
                                #include <set>

                                //using namespace std;

                                int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                {
                                return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                                }
                                bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                {
                                std::set<int> validScenarios;
                                validScenarios.insert(GetScenarioInt(true, true, true, true));
                                validScenarios.insert(GetScenarioInt(true, true, true, false));
                                validScenarios.insert(GetScenarioInt(true, false, false, false));

                                int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

                                return validScenarios.find(currentScenario) != validScenarios.end();
                                }

                                int main()
                                {
                                std::cout << IsValidScenario(true, true, true, false) << "n"; // expected = true;
                                std::cout << IsValidScenario(true, true, false, false) << "n"; // expected = false;

                                return 0;
                                }


                                See it at work here



                                Well, that's the "elegant and maintainable" (IMHO) solution I usually aim to, but really, for the OP case, my previous "bunch of ifs" answer fits better the OP requirements, even if it's not elegant nor maintainable.






                                share|improve this answer














                                My previous answer is already the accepted answer, I add something here that I think is both readable, easy and in this case open to future modifications:



                                Starting with @ZdeslavVojkovic answer (which I find quite good), I came up with this:



                                #include <iostream>
                                #include <set>

                                //using namespace std;

                                int GetScenarioInt(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                {
                                return bValue1 << 3 | bValue2 << 2 | bValue3 << 1 | bValue4;
                                }
                                bool IsValidScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                {
                                std::set<int> validScenarios;
                                validScenarios.insert(GetScenarioInt(true, true, true, true));
                                validScenarios.insert(GetScenarioInt(true, true, true, false));
                                validScenarios.insert(GetScenarioInt(true, false, false, false));

                                int currentScenario = GetScenarioInt(bValue1, bValue2, bValue3, bValue4);

                                return validScenarios.find(currentScenario) != validScenarios.end();
                                }

                                int main()
                                {
                                std::cout << IsValidScenario(true, true, true, false) << "n"; // expected = true;
                                std::cout << IsValidScenario(true, true, false, false) << "n"; // expected = false;

                                return 0;
                                }


                                See it at work here



                                Well, that's the "elegant and maintainable" (IMHO) solution I usually aim to, but really, for the OP case, my previous "bunch of ifs" answer fits better the OP requirements, even if it's not elegant nor maintainable.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Dec 8 at 16:16

























                                answered Dec 3 at 13:43









                                Gian Paolo

                                3,2352925




                                3,2352925






















                                    up vote
                                    16
                                    down vote













                                    I would also like to submit an other approach.



                                    My idea is to convert the bools into an integer and then compare using variadic templates:



                                    unsigned bitmap_from_bools(bool b) {
                                    return b;
                                    }
                                    template<typename... args>
                                    unsigned bitmap_from_bools(bool b, args... pack) {
                                    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
                                    //bad scenario
                                    }
                                    }


                                    Notice how this system can support up to 32 bools as input. replacing the unsigned with unsigned long long (or uint64_t) increases support to 64 cases.
                                    If you dont like the if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u), you could also use yet another variadic template method:



                                    bool equals_any(unsigned target, unsigned compare) {
                                    return target == compare;
                                    }
                                    template<typename... args>
                                    bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
                                    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
                                    //bad scenario
                                    }
                                    }





                                    share|improve this answer



















                                    • 3




                                      Thanks for sharing your alternative approach.
                                      – Andrew Truckle
                                      Dec 3 at 12:39






                                    • 1




                                      I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                      – Konrad Rudolph
                                      Dec 3 at 22:29












                                    • yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                      – Stack Danny
                                      Dec 4 at 7:57










                                    • I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                      – MooseBoys
                                      Dec 5 at 15:38












                                    • @MooseBoys yes, you're right. Thanks
                                      – Stack Danny
                                      Dec 5 at 15:42















                                    up vote
                                    16
                                    down vote













                                    I would also like to submit an other approach.



                                    My idea is to convert the bools into an integer and then compare using variadic templates:



                                    unsigned bitmap_from_bools(bool b) {
                                    return b;
                                    }
                                    template<typename... args>
                                    unsigned bitmap_from_bools(bool b, args... pack) {
                                    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
                                    //bad scenario
                                    }
                                    }


                                    Notice how this system can support up to 32 bools as input. replacing the unsigned with unsigned long long (or uint64_t) increases support to 64 cases.
                                    If you dont like the if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u), you could also use yet another variadic template method:



                                    bool equals_any(unsigned target, unsigned compare) {
                                    return target == compare;
                                    }
                                    template<typename... args>
                                    bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
                                    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
                                    //bad scenario
                                    }
                                    }





                                    share|improve this answer



















                                    • 3




                                      Thanks for sharing your alternative approach.
                                      – Andrew Truckle
                                      Dec 3 at 12:39






                                    • 1




                                      I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                      – Konrad Rudolph
                                      Dec 3 at 22:29












                                    • yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                      – Stack Danny
                                      Dec 4 at 7:57










                                    • I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                      – MooseBoys
                                      Dec 5 at 15:38












                                    • @MooseBoys yes, you're right. Thanks
                                      – Stack Danny
                                      Dec 5 at 15:42













                                    up vote
                                    16
                                    down vote










                                    up vote
                                    16
                                    down vote









                                    I would also like to submit an other approach.



                                    My idea is to convert the bools into an integer and then compare using variadic templates:



                                    unsigned bitmap_from_bools(bool b) {
                                    return b;
                                    }
                                    template<typename... args>
                                    unsigned bitmap_from_bools(bool b, args... pack) {
                                    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
                                    //bad scenario
                                    }
                                    }


                                    Notice how this system can support up to 32 bools as input. replacing the unsigned with unsigned long long (or uint64_t) increases support to 64 cases.
                                    If you dont like the if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u), you could also use yet another variadic template method:



                                    bool equals_any(unsigned target, unsigned compare) {
                                    return target == compare;
                                    }
                                    template<typename... args>
                                    bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
                                    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
                                    //bad scenario
                                    }
                                    }





                                    share|improve this answer














                                    I would also like to submit an other approach.



                                    My idea is to convert the bools into an integer and then compare using variadic templates:



                                    unsigned bitmap_from_bools(bool b) {
                                    return b;
                                    }
                                    template<typename... args>
                                    unsigned bitmap_from_bools(bool b, args... pack) {
                                    return (bitmap_from_bools(b) << sizeof...(pack)) | bitmap_from_bools(pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u) {
                                    //bad scenario
                                    }
                                    }


                                    Notice how this system can support up to 32 bools as input. replacing the unsigned with unsigned long long (or uint64_t) increases support to 64 cases.
                                    If you dont like the if (summary != 0b1111u && summary != 0b1110u && summary != 0b1000u), you could also use yet another variadic template method:



                                    bool equals_any(unsigned target, unsigned compare) {
                                    return target == compare;
                                    }
                                    template<typename... args>
                                    bool equals_any(unsigned target, unsigned compare, args... compare_pack) {
                                    return equals_any(target, compare) ? true : equals_any(target, compare_pack...);
                                    }

                                    int main() {
                                    bool bValue1;
                                    bool bValue2;
                                    bool bValue3;
                                    bool bValue4;

                                    unsigned summary = bitmap_from_bools(bValue1, bValue2, bValue3, bValue4);

                                    if (!equals_any(summary, 0b1111u, 0b1110u, 0b1000u)) {
                                    //bad scenario
                                    }
                                    }






                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Dec 5 at 15:42

























                                    answered Dec 3 at 11:28









                                    Stack Danny

                                    1,070319




                                    1,070319








                                    • 3




                                      Thanks for sharing your alternative approach.
                                      – Andrew Truckle
                                      Dec 3 at 12:39






                                    • 1




                                      I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                      – Konrad Rudolph
                                      Dec 3 at 22:29












                                    • yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                      – Stack Danny
                                      Dec 4 at 7:57










                                    • I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                      – MooseBoys
                                      Dec 5 at 15:38












                                    • @MooseBoys yes, you're right. Thanks
                                      – Stack Danny
                                      Dec 5 at 15:42














                                    • 3




                                      Thanks for sharing your alternative approach.
                                      – Andrew Truckle
                                      Dec 3 at 12:39






                                    • 1




                                      I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                      – Konrad Rudolph
                                      Dec 3 at 22:29












                                    • yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                      – Stack Danny
                                      Dec 4 at 7:57










                                    • I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                      – MooseBoys
                                      Dec 5 at 15:38












                                    • @MooseBoys yes, you're right. Thanks
                                      – Stack Danny
                                      Dec 5 at 15:42








                                    3




                                    3




                                    Thanks for sharing your alternative approach.
                                    – Andrew Truckle
                                    Dec 3 at 12:39




                                    Thanks for sharing your alternative approach.
                                    – Andrew Truckle
                                    Dec 3 at 12:39




                                    1




                                    1




                                    I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                    – Konrad Rudolph
                                    Dec 3 at 22:29






                                    I love this approach, except for the main function’s name: “from bool … to what?” — Why not explicitly, bitmap_from_bools, or bools_to_bitmap?
                                    – Konrad Rudolph
                                    Dec 3 at 22:29














                                    yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                    – Stack Danny
                                    Dec 4 at 7:57




                                    yes @KonradRudolph, I couldn't think of a better name, except maybe bools_to_unsigned. Bitmap is a good keyword; edited.
                                    – Stack Danny
                                    Dec 4 at 7:57












                                    I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                    – MooseBoys
                                    Dec 5 at 15:38






                                    I think you want summary!= 0b1111u &&.... a != b || a != c is always true if b != c
                                    – MooseBoys
                                    Dec 5 at 15:38














                                    @MooseBoys yes, you're right. Thanks
                                    – Stack Danny
                                    Dec 5 at 15:42




                                    @MooseBoys yes, you're right. Thanks
                                    – Stack Danny
                                    Dec 5 at 15:42










                                    up vote
                                    13
                                    down vote













                                    Here's a simplified version:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2||!bValue4)) {
                                    // acceptable
                                    } else {
                                    // not acceptable
                                    }


                                    Note, of course, this solution is more obfuscated than the original one, its meaning may be harder to understand.





                                    Update: MSalters in the comments found an even simpler expression:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...





                                    share|improve this answer



















                                    • 1




                                      Yes, but hard to understand. But thanks for suggestion.
                                      – Andrew Truckle
                                      Dec 3 at 10:58










                                    • I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                      – Oliv
                                      Dec 3 at 11:07








                                    • 1




                                      @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                      – geza
                                      Dec 3 at 11:12






                                    • 1




                                      simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                      – Zdeslav Vojkovic
                                      Dec 3 at 11:16






                                    • 1




                                      @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                      – geza
                                      Dec 4 at 18:53















                                    up vote
                                    13
                                    down vote













                                    Here's a simplified version:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2||!bValue4)) {
                                    // acceptable
                                    } else {
                                    // not acceptable
                                    }


                                    Note, of course, this solution is more obfuscated than the original one, its meaning may be harder to understand.





                                    Update: MSalters in the comments found an even simpler expression:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...





                                    share|improve this answer



















                                    • 1




                                      Yes, but hard to understand. But thanks for suggestion.
                                      – Andrew Truckle
                                      Dec 3 at 10:58










                                    • I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                      – Oliv
                                      Dec 3 at 11:07








                                    • 1




                                      @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                      – geza
                                      Dec 3 at 11:12






                                    • 1




                                      simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                      – Zdeslav Vojkovic
                                      Dec 3 at 11:16






                                    • 1




                                      @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                      – geza
                                      Dec 4 at 18:53













                                    up vote
                                    13
                                    down vote










                                    up vote
                                    13
                                    down vote









                                    Here's a simplified version:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2||!bValue4)) {
                                    // acceptable
                                    } else {
                                    // not acceptable
                                    }


                                    Note, of course, this solution is more obfuscated than the original one, its meaning may be harder to understand.





                                    Update: MSalters in the comments found an even simpler expression:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...





                                    share|improve this answer














                                    Here's a simplified version:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2||!bValue4)) {
                                    // acceptable
                                    } else {
                                    // not acceptable
                                    }


                                    Note, of course, this solution is more obfuscated than the original one, its meaning may be harder to understand.





                                    Update: MSalters in the comments found an even simpler expression:



                                    if (bValue1&&(bValue2==bValue3)&&(bValue2>=bValue4)) ...






                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Dec 3 at 16:25

























                                    answered Dec 3 at 10:40









                                    geza

                                    12.4k32775




                                    12.4k32775








                                    • 1




                                      Yes, but hard to understand. But thanks for suggestion.
                                      – Andrew Truckle
                                      Dec 3 at 10:58










                                    • I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                      – Oliv
                                      Dec 3 at 11:07








                                    • 1




                                      @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                      – geza
                                      Dec 3 at 11:12






                                    • 1




                                      simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                      – Zdeslav Vojkovic
                                      Dec 3 at 11:16






                                    • 1




                                      @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                      – geza
                                      Dec 4 at 18:53














                                    • 1




                                      Yes, but hard to understand. But thanks for suggestion.
                                      – Andrew Truckle
                                      Dec 3 at 10:58










                                    • I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                      – Oliv
                                      Dec 3 at 11:07








                                    • 1




                                      @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                      – geza
                                      Dec 3 at 11:12






                                    • 1




                                      simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                      – Zdeslav Vojkovic
                                      Dec 3 at 11:16






                                    • 1




                                      @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                      – geza
                                      Dec 4 at 18:53








                                    1




                                    1




                                    Yes, but hard to understand. But thanks for suggestion.
                                    – Andrew Truckle
                                    Dec 3 at 10:58




                                    Yes, but hard to understand. But thanks for suggestion.
                                    – Andrew Truckle
                                    Dec 3 at 10:58












                                    I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                    – Oliv
                                    Dec 3 at 11:07






                                    I compared compilers ability to simplify expression with your simplification as a reference: compiler explorer. gcc did not find your optimal version but its solution is still good. Clang and MSVC don't seem to perform any boolean expression simplification.
                                    – Oliv
                                    Dec 3 at 11:07






                                    1




                                    1




                                    @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                    – geza
                                    Dec 3 at 11:12




                                    @AndrewTruckle: note, that if you needed a more readable version, then please say so. You've said "simplified", yet you accept an even more verbose version than your original one.
                                    – geza
                                    Dec 3 at 11:12




                                    1




                                    1




                                    simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                    – Zdeslav Vojkovic
                                    Dec 3 at 11:16




                                    simple is indeed a vague term. Many people understand it in this context as simpler for developer to understand and not for the compiler to generate code, so more verbose can indeed be simpler.
                                    – Zdeslav Vojkovic
                                    Dec 3 at 11:16




                                    1




                                    1




                                    @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                    – geza
                                    Dec 4 at 18:53




                                    @IsmaelMiguel: when a logic formula is optimized for number of terms, the original meaning is usually lost. But one can put a comment around it, so it is clear what it does. Even, for the accepted answer, a comment would not harm.
                                    – geza
                                    Dec 4 at 18:53










                                    up vote
                                    9
                                    down vote













                                    I'm not seeing any answers saying to name the scenarios, though the OP's solution does exactly that.



                                    To me it is best to encapsulate the comment of what each scenario is into either a variable name or function name. You're more likely to ignore a comment than a name, and if your logic changes in the future you're more likely to change a name than a comment. You can't refactor a comment.



                                    If you plan on reusing these scenarios outside of your function (or might want to), then make a function that says what it evaluates (constexpr/noexcept optional but recommended):



                                    constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && b4; }

                                    constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && !b4; }

                                    constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && !b2 && !b3 && !b4; }


                                    Make these class methods if possible (like in OP's solution). You can use variables inside of your function if you don't think you'll reuse the logic:



                                    const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
                                    const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
                                    const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;


                                    The compiler will most likely sort out that if bValue1 is false then all scenarios are false. Don't worry about making it fast, just correct and readable. If you profile your code and find this to be a bottleneck because the compiler generated sub-optimal code at -O2 or higher then try to rewrite it.






                                    share|improve this answer























                                    • I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                      – Dirk Herrmann
                                      Dec 3 at 23:53















                                    up vote
                                    9
                                    down vote













                                    I'm not seeing any answers saying to name the scenarios, though the OP's solution does exactly that.



                                    To me it is best to encapsulate the comment of what each scenario is into either a variable name or function name. You're more likely to ignore a comment than a name, and if your logic changes in the future you're more likely to change a name than a comment. You can't refactor a comment.



                                    If you plan on reusing these scenarios outside of your function (or might want to), then make a function that says what it evaluates (constexpr/noexcept optional but recommended):



                                    constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && b4; }

                                    constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && !b4; }

                                    constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && !b2 && !b3 && !b4; }


                                    Make these class methods if possible (like in OP's solution). You can use variables inside of your function if you don't think you'll reuse the logic:



                                    const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
                                    const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
                                    const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;


                                    The compiler will most likely sort out that if bValue1 is false then all scenarios are false. Don't worry about making it fast, just correct and readable. If you profile your code and find this to be a bottleneck because the compiler generated sub-optimal code at -O2 or higher then try to rewrite it.






                                    share|improve this answer























                                    • I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                      – Dirk Herrmann
                                      Dec 3 at 23:53













                                    up vote
                                    9
                                    down vote










                                    up vote
                                    9
                                    down vote









                                    I'm not seeing any answers saying to name the scenarios, though the OP's solution does exactly that.



                                    To me it is best to encapsulate the comment of what each scenario is into either a variable name or function name. You're more likely to ignore a comment than a name, and if your logic changes in the future you're more likely to change a name than a comment. You can't refactor a comment.



                                    If you plan on reusing these scenarios outside of your function (or might want to), then make a function that says what it evaluates (constexpr/noexcept optional but recommended):



                                    constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && b4; }

                                    constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && !b4; }

                                    constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && !b2 && !b3 && !b4; }


                                    Make these class methods if possible (like in OP's solution). You can use variables inside of your function if you don't think you'll reuse the logic:



                                    const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
                                    const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
                                    const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;


                                    The compiler will most likely sort out that if bValue1 is false then all scenarios are false. Don't worry about making it fast, just correct and readable. If you profile your code and find this to be a bottleneck because the compiler generated sub-optimal code at -O2 or higher then try to rewrite it.






                                    share|improve this answer














                                    I'm not seeing any answers saying to name the scenarios, though the OP's solution does exactly that.



                                    To me it is best to encapsulate the comment of what each scenario is into either a variable name or function name. You're more likely to ignore a comment than a name, and if your logic changes in the future you're more likely to change a name than a comment. You can't refactor a comment.



                                    If you plan on reusing these scenarios outside of your function (or might want to), then make a function that says what it evaluates (constexpr/noexcept optional but recommended):



                                    constexpr bool IsScenario1(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && b4; }

                                    constexpr bool IsScenario2(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && b2 && b3 && !b4; }

                                    constexpr bool IsScenario3(bool b1, bool b2, bool b3, bool b4) noexcept
                                    { return b1 && !b2 && !b3 && !b4; }


                                    Make these class methods if possible (like in OP's solution). You can use variables inside of your function if you don't think you'll reuse the logic:



                                    const auto is_scenario_1 = bValue1 && bValue2 && bValue3 && bValue4;
                                    const auto is_scenario_2 = bvalue1 && bvalue2 && bValue3 && !bValue4;
                                    const auto is_scenario_3 = bValue1 && !bValue2 && !bValue3 && !bValue4;


                                    The compiler will most likely sort out that if bValue1 is false then all scenarios are false. Don't worry about making it fast, just correct and readable. If you profile your code and find this to be a bottleneck because the compiler generated sub-optimal code at -O2 or higher then try to rewrite it.







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Dec 4 at 5:08









                                    Andrew Truckle

                                    5,45142246




                                    5,45142246










                                    answered Dec 3 at 23:13









                                    Erroneous

                                    490410




                                    490410












                                    • I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                      – Dirk Herrmann
                                      Dec 3 at 23:53


















                                    • I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                      – Dirk Herrmann
                                      Dec 3 at 23:53
















                                    I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                    – Dirk Herrmann
                                    Dec 3 at 23:53




                                    I like this slightly more than Gian Paolo's (already nice) solution: It avoids control flow and the use of a variable that is overwritten - more functional style.
                                    – Dirk Herrmann
                                    Dec 3 at 23:53










                                    up vote
                                    8
                                    down vote













                                    I am only providing my answer here as in the comments someone suggested to show my solution. I want to thank everyone for their insights.



                                    In the end I opted to add three new "scenario" boolean methods:



                                    bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    !INCLUDE_ITEM2(pEntry) &&
                                    !INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }


                                    Then I was able to apply those my my validation routine like this:



                                    if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
                                    {
                                    ; Error
                                    }


                                    In my live application the 4 bool values are actually extracted from a DWORD which has 4 values encoded into it.



                                    Thanks again everyone.






                                    share|improve this answer

















                                    • 1




                                      Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                      – Hardik Modha
                                      Dec 3 at 13:04






                                    • 1




                                      @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                      – Andrew Truckle
                                      Dec 3 at 13:06










                                    • Well, Sounds good then. :)
                                      – Hardik Modha
                                      Dec 3 at 13:10

















                                    up vote
                                    8
                                    down vote













                                    I am only providing my answer here as in the comments someone suggested to show my solution. I want to thank everyone for their insights.



                                    In the end I opted to add three new "scenario" boolean methods:



                                    bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    !INCLUDE_ITEM2(pEntry) &&
                                    !INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }


                                    Then I was able to apply those my my validation routine like this:



                                    if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
                                    {
                                    ; Error
                                    }


                                    In my live application the 4 bool values are actually extracted from a DWORD which has 4 values encoded into it.



                                    Thanks again everyone.






                                    share|improve this answer

















                                    • 1




                                      Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                      – Hardik Modha
                                      Dec 3 at 13:04






                                    • 1




                                      @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                      – Andrew Truckle
                                      Dec 3 at 13:06










                                    • Well, Sounds good then. :)
                                      – Hardik Modha
                                      Dec 3 at 13:10















                                    up vote
                                    8
                                    down vote










                                    up vote
                                    8
                                    down vote









                                    I am only providing my answer here as in the comments someone suggested to show my solution. I want to thank everyone for their insights.



                                    In the end I opted to add three new "scenario" boolean methods:



                                    bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    !INCLUDE_ITEM2(pEntry) &&
                                    !INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }


                                    Then I was able to apply those my my validation routine like this:



                                    if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
                                    {
                                    ; Error
                                    }


                                    In my live application the 4 bool values are actually extracted from a DWORD which has 4 values encoded into it.



                                    Thanks again everyone.






                                    share|improve this answer












                                    I am only providing my answer here as in the comments someone suggested to show my solution. I want to thank everyone for their insights.



                                    In the end I opted to add three new "scenario" boolean methods:



                                    bool CChristianLifeMinistryValidationDlg::IsFirstWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    !INCLUDE_ITEM2(pEntry) &&
                                    !INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsSecondWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    INCLUDE_ITEM4(pEntry));
                                    }

                                    bool CChristianLifeMinistryValidationDlg::IsOtherWeekStudentItems(CChristianLifeMinistryEntry *pEntry)
                                    {
                                    return (INCLUDE_ITEM1(pEntry) &&
                                    INCLUDE_ITEM2(pEntry) &&
                                    INCLUDE_ITEM3(pEntry) &&
                                    !INCLUDE_ITEM4(pEntry));
                                    }


                                    Then I was able to apply those my my validation routine like this:



                                    if (!IsFirstWeekStudentItems(pEntry) && !IsSecondWeekStudentItems(pEntry) && !IsOtherWeekStudentItems(pEntry))
                                    {
                                    ; Error
                                    }


                                    In my live application the 4 bool values are actually extracted from a DWORD which has 4 values encoded into it.



                                    Thanks again everyone.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Dec 3 at 13:01









                                    Andrew Truckle

                                    5,45142246




                                    5,45142246








                                    • 1




                                      Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                      – Hardik Modha
                                      Dec 3 at 13:04






                                    • 1




                                      @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                      – Andrew Truckle
                                      Dec 3 at 13:06










                                    • Well, Sounds good then. :)
                                      – Hardik Modha
                                      Dec 3 at 13:10
















                                    • 1




                                      Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                      – Hardik Modha
                                      Dec 3 at 13:04






                                    • 1




                                      @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                      – Andrew Truckle
                                      Dec 3 at 13:06










                                    • Well, Sounds good then. :)
                                      – Hardik Modha
                                      Dec 3 at 13:10










                                    1




                                    1




                                    Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                    – Hardik Modha
                                    Dec 3 at 13:04




                                    Thanks for sharing the solution. :) It's actually better than the complex if conditions hell. Maybe you can still name INCLUDE_ITEM1 etc in a better way and you are all good. :)
                                    – Hardik Modha
                                    Dec 3 at 13:04




                                    1




                                    1




                                    @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                    – Andrew Truckle
                                    Dec 3 at 13:06




                                    @HardikModha Well, technically they are "Student items" and the flag is to indicate if they are to be "included". So I think the name, albeit sounding generic, is actually meaningful in this context. :)
                                    – Andrew Truckle
                                    Dec 3 at 13:06












                                    Well, Sounds good then. :)
                                    – Hardik Modha
                                    Dec 3 at 13:10






                                    Well, Sounds good then. :)
                                    – Hardik Modha
                                    Dec 3 at 13:10












                                    up vote
                                    8
                                    down vote













                                    Consider translating your tables as directly as possible into your program. Drive the program based off the table, instead of mimicing it with logic.



                                    template<class T0>
                                    auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
                                    for (auto&& x:il)
                                    if (x==t0) return true;
                                    return false;
                                    }


                                    now



                                    if (is_any_of(
                                    std::make_tuple(bValue1, bValue2, bValue3, bValue4),
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    }
                                    ))


                                    this directly as possible encodes your truth table into the compiler.



                                    Live example.



                                    You could also use std::any_of directly:



                                    using entry = std::array<bool, 4>;
                                    constexpr entry acceptable =
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    };
                                    if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
                                    return entry{bValue1, bValue2, bValue3, bValue4} == x;
                                    }) {
                                    }


                                    the compiler can inline the code, and eliminate any iteration and build its own logic for you. Meanwhile, your code reflects exactly how you concieved of the problem.






                                    share|improve this answer























                                    • The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                      – Gian Paolo
                                      Dec 4 at 22:03












                                    • Interesting alternative. 👍
                                      – Andrew Truckle
                                      Dec 5 at 5:24















                                    up vote
                                    8
                                    down vote













                                    Consider translating your tables as directly as possible into your program. Drive the program based off the table, instead of mimicing it with logic.



                                    template<class T0>
                                    auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
                                    for (auto&& x:il)
                                    if (x==t0) return true;
                                    return false;
                                    }


                                    now



                                    if (is_any_of(
                                    std::make_tuple(bValue1, bValue2, bValue3, bValue4),
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    }
                                    ))


                                    this directly as possible encodes your truth table into the compiler.



                                    Live example.



                                    You could also use std::any_of directly:



                                    using entry = std::array<bool, 4>;
                                    constexpr entry acceptable =
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    };
                                    if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
                                    return entry{bValue1, bValue2, bValue3, bValue4} == x;
                                    }) {
                                    }


                                    the compiler can inline the code, and eliminate any iteration and build its own logic for you. Meanwhile, your code reflects exactly how you concieved of the problem.






                                    share|improve this answer























                                    • The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                      – Gian Paolo
                                      Dec 4 at 22:03












                                    • Interesting alternative. 👍
                                      – Andrew Truckle
                                      Dec 5 at 5:24













                                    up vote
                                    8
                                    down vote










                                    up vote
                                    8
                                    down vote









                                    Consider translating your tables as directly as possible into your program. Drive the program based off the table, instead of mimicing it with logic.



                                    template<class T0>
                                    auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
                                    for (auto&& x:il)
                                    if (x==t0) return true;
                                    return false;
                                    }


                                    now



                                    if (is_any_of(
                                    std::make_tuple(bValue1, bValue2, bValue3, bValue4),
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    }
                                    ))


                                    this directly as possible encodes your truth table into the compiler.



                                    Live example.



                                    You could also use std::any_of directly:



                                    using entry = std::array<bool, 4>;
                                    constexpr entry acceptable =
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    };
                                    if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
                                    return entry{bValue1, bValue2, bValue3, bValue4} == x;
                                    }) {
                                    }


                                    the compiler can inline the code, and eliminate any iteration and build its own logic for you. Meanwhile, your code reflects exactly how you concieved of the problem.






                                    share|improve this answer














                                    Consider translating your tables as directly as possible into your program. Drive the program based off the table, instead of mimicing it with logic.



                                    template<class T0>
                                    auto is_any_of( T0 const& t0, std::initializer_list<T0> il ) {
                                    for (auto&& x:il)
                                    if (x==t0) return true;
                                    return false;
                                    }


                                    now



                                    if (is_any_of(
                                    std::make_tuple(bValue1, bValue2, bValue3, bValue4),
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    }
                                    ))


                                    this directly as possible encodes your truth table into the compiler.



                                    Live example.



                                    You could also use std::any_of directly:



                                    using entry = std::array<bool, 4>;
                                    constexpr entry acceptable =
                                    {
                                    {true, true, true, true},
                                    {true, true, true, false},
                                    {true, false, false, false}
                                    };
                                    if (std::any_of( begin(acceptable), end(acceptable), [&](auto&&x){
                                    return entry{bValue1, bValue2, bValue3, bValue4} == x;
                                    }) {
                                    }


                                    the compiler can inline the code, and eliminate any iteration and build its own logic for you. Meanwhile, your code reflects exactly how you concieved of the problem.







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Dec 4 at 20:04

























                                    answered Dec 4 at 19:55









                                    Yakk - Adam Nevraumont

                                    181k19188368




                                    181k19188368












                                    • The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                      – Gian Paolo
                                      Dec 4 at 22:03












                                    • Interesting alternative. 👍
                                      – Andrew Truckle
                                      Dec 5 at 5:24


















                                    • The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                      – Gian Paolo
                                      Dec 4 at 22:03












                                    • Interesting alternative. 👍
                                      – Andrew Truckle
                                      Dec 5 at 5:24
















                                    The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                    – Gian Paolo
                                    Dec 4 at 22:03






                                    The first version is so easy to read and so maintenable, I really like it. The second one is harder to read, at least for me, and requires a c++ skill level maybe over the average, surely over my one. Not something everyone is able to write. Just learned somethin new, thanks
                                    – Gian Paolo
                                    Dec 4 at 22:03














                                    Interesting alternative. 👍
                                    – Andrew Truckle
                                    Dec 5 at 5:24




                                    Interesting alternative. 👍
                                    – Andrew Truckle
                                    Dec 5 at 5:24










                                    up vote
                                    7
                                    down vote













                                    A C/C++ way



                                    bool scenario[3][4] = {{true, true, true, true}, 
                                    {true, true, true, false},
                                    {true, false, false, false}};

                                    bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                    {
                                    bool temp = {bValue1, bValue2, bValue3, bValue4};
                                    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
                                    {
                                    if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
                                    return true;
                                    }
                                    return false;
                                    }


                                    This approach is scalable as if the number of valid conditions grow, you easily just add more of them to scenario list.






                                    share|improve this answer





















                                    • Thank you for your answer.
                                      – Andrew Truckle
                                      Dec 3 at 12:36










                                    • I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                      – MSalters
                                      Dec 3 at 15:43










                                    • @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                      – hessam hedieh
                                      Dec 3 at 16:01












                                    • Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                      – Konrad Rudolph
                                      Dec 3 at 22:27










                                    • @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                      – MSalters
                                      Dec 4 at 10:25















                                    up vote
                                    7
                                    down vote













                                    A C/C++ way



                                    bool scenario[3][4] = {{true, true, true, true}, 
                                    {true, true, true, false},
                                    {true, false, false, false}};

                                    bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                    {
                                    bool temp = {bValue1, bValue2, bValue3, bValue4};
                                    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
                                    {
                                    if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
                                    return true;
                                    }
                                    return false;
                                    }


                                    This approach is scalable as if the number of valid conditions grow, you easily just add more of them to scenario list.






                                    share|improve this answer





















                                    • Thank you for your answer.
                                      – Andrew Truckle
                                      Dec 3 at 12:36










                                    • I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                      – MSalters
                                      Dec 3 at 15:43










                                    • @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                      – hessam hedieh
                                      Dec 3 at 16:01












                                    • Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                      – Konrad Rudolph
                                      Dec 3 at 22:27










                                    • @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                      – MSalters
                                      Dec 4 at 10:25













                                    up vote
                                    7
                                    down vote










                                    up vote
                                    7
                                    down vote









                                    A C/C++ way



                                    bool scenario[3][4] = {{true, true, true, true}, 
                                    {true, true, true, false},
                                    {true, false, false, false}};

                                    bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                    {
                                    bool temp = {bValue1, bValue2, bValue3, bValue4};
                                    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
                                    {
                                    if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
                                    return true;
                                    }
                                    return false;
                                    }


                                    This approach is scalable as if the number of valid conditions grow, you easily just add more of them to scenario list.






                                    share|improve this answer












                                    A C/C++ way



                                    bool scenario[3][4] = {{true, true, true, true}, 
                                    {true, true, true, false},
                                    {true, false, false, false}};

                                    bool CheckScenario(bool bValue1, bool bValue2, bool bValue3, bool bValue4)
                                    {
                                    bool temp = {bValue1, bValue2, bValue3, bValue4};
                                    for(int i = 0 ; i < sizeof(scenario) / sizeof(scenario[0]); i++)
                                    {
                                    if(memcmp(temp, scenario[i], sizeof(temp)) == 0)
                                    return true;
                                    }
                                    return false;
                                    }


                                    This approach is scalable as if the number of valid conditions grow, you easily just add more of them to scenario list.







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Dec 3 at 10:42









                                    hessam hedieh

                                    1656




                                    1656












                                    • Thank you for your answer.
                                      – Andrew Truckle
                                      Dec 3 at 12:36










                                    • I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                      – MSalters
                                      Dec 3 at 15:43










                                    • @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                      – hessam hedieh
                                      Dec 3 at 16:01












                                    • Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                      – Konrad Rudolph
                                      Dec 3 at 22:27










                                    • @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                      – MSalters
                                      Dec 4 at 10:25


















                                    • Thank you for your answer.
                                      – Andrew Truckle
                                      Dec 3 at 12:36










                                    • I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                      – MSalters
                                      Dec 3 at 15:43










                                    • @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                      – hessam hedieh
                                      Dec 3 at 16:01












                                    • Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                      – Konrad Rudolph
                                      Dec 3 at 22:27










                                    • @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                      – MSalters
                                      Dec 4 at 10:25
















                                    Thank you for your answer.
                                    – Andrew Truckle
                                    Dec 3 at 12:36




                                    Thank you for your answer.
                                    – Andrew Truckle
                                    Dec 3 at 12:36












                                    I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                    – MSalters
                                    Dec 3 at 15:43




                                    I'm pretty sure this is wrong, though. It assumes that the compiler uses only a single binary representation for true. A compiler which uses "anything non-zero is true" causes this code to fail. Note that true must convert to 1, it just doesn't need to be stored as such.
                                    – MSalters
                                    Dec 3 at 15:43












                                    @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                    – hessam hedieh
                                    Dec 3 at 16:01






                                    @MSalters, tnx, I get your point and I am aware of that, kinda like 2 is not equal to true but evaluates to true, my code doesnt force int 1 = true and works as long as all true's are converted to same int value, SO here is my question: Why compiler should act random on converting true to underlying int, Can you please elaborate more?
                                    – hessam hedieh
                                    Dec 3 at 16:01














                                    Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                    – Konrad Rudolph
                                    Dec 3 at 22:27




                                    Performing a memcmp to test boolean conditions is not the C++ way, and I rather doubt that it’s an established C way, either.
                                    – Konrad Rudolph
                                    Dec 3 at 22:27












                                    @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                    – MSalters
                                    Dec 4 at 10:25




                                    @hessamhedieh: The problem in your logic is "converting true to underlying int". That is not how compilers work,
                                    – MSalters
                                    Dec 4 at 10:25










                                    up vote
                                    7
                                    down vote













                                    It's easy to notice that first two scenarios are similar - they share most of the conditions. If you want to select in which scenario you are at the moment, you could write it like this (it's a modified @gian-paolo's solution):



                                    bool valid = false;
                                    if(bValue1 && bValue2 && bValue3)
                                    {
                                    if (bValue4)
                                    valid = true; //scenario 1
                                    else if (!bValue4)
                                    valid = true; //scenario 2
                                    }
                                    else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                                    valid = true; //scenario 3


                                    Going further, you can notice, that first boolean needs to be always true, which is an entry condition, so you can end up with:



                                    bool valid = false;
                                    if(bValue1)
                                    {
                                    if(bValue2 && bValue3)
                                    {
                                    if (bValue4)
                                    valid = true; //scenario 1
                                    else if (!bValue4)
                                    valid = true; //scenario 2
                                    }
                                    else if (!bValue2 && !bValue3 && !bValue4)
                                    valid = true; //scenario 3
                                    }


                                    Even more, you can now clearly see, that bValue2 and bValue3 are somewhat connected - you could extract their state to some external functions or variables with more appropriate name (this is not always easy or appropriate though):



                                    bool valid = false;
                                    if(bValue1)
                                    {
                                    bool bValue1and2 = bValue1 && bValue2;
                                    bool notBValue1and2 = !bValue2 && !bValue3;
                                    if(bValue1and2)
                                    {
                                    if (bValue4)
                                    valid = true; //scenario 1
                                    else if (!bValue4)
                                    valid = true; //scenario 2
                                    }
                                    else if (notBValue1and2 && !bValue4)
                                    valid = true; //scenario 3
                                    }


                                    Doing it this way have some advantages and disadvantages:




                                    • conditions are smaller, so it's easier to reason about them,

                                    • it's easier to do nice renaming to make these conditions more understandable,

                                    • but, they require to understand the scope,

                                    • moreover it's more rigid


                                    If you predict that there will be changes to the above logic, you should use more straightforward approach as presented by @gian-paolo.



                                    Otherwise, if these conditions are well established, and are kind of "solid rules" that will never change, consider my last code snippet.






                                    share|improve this answer

























                                      up vote
                                      7
                                      down vote













                                      It's easy to notice that first two scenarios are similar - they share most of the conditions. If you want to select in which scenario you are at the moment, you could write it like this (it's a modified @gian-paolo's solution):



                                      bool valid = false;
                                      if(bValue1 && bValue2 && bValue3)
                                      {
                                      if (bValue4)
                                      valid = true; //scenario 1
                                      else if (!bValue4)
                                      valid = true; //scenario 2
                                      }
                                      else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                                      valid = true; //scenario 3


                                      Going further, you can notice, that first boolean needs to be always true, which is an entry condition, so you can end up with:



                                      bool valid = false;
                                      if(bValue1)
                                      {
                                      if(bValue2 && bValue3)
                                      {
                                      if (bValue4)
                                      valid = true; //scenario 1
                                      else if (!bValue4)
                                      valid = true; //scenario 2
                                      }
                                      else if (!bValue2 && !bValue3 && !bValue4)
                                      valid = true; //scenario 3
                                      }


                                      Even more, you can now clearly see, that bValue2 and bValue3 are somewhat connected - you could extract their state to some external functions or variables with more appropriate name (this is not always easy or appropriate though):



                                      bool valid = false;
                                      if(bValue1)
                                      {
                                      bool bValue1and2 = bValue1 && bValue2;
                                      bool notBValue1and2 = !bValue2 && !bValue3;
                                      if(bValue1and2)
                                      {
                                      if (bValue4)
                                      valid = true; //scenario 1
                                      else if (!bValue4)
                                      valid = true; //scenario 2
                                      }
                                      else if (notBValue1and2 && !bValue4)
                                      valid = true; //scenario 3
                                      }


                                      Doing it this way have some advantages and disadvantages:




                                      • conditions are smaller, so it's easier to reason about them,

                                      • it's easier to do nice renaming to make these conditions more understandable,

                                      • but, they require to understand the scope,

                                      • moreover it's more rigid


                                      If you predict that there will be changes to the above logic, you should use more straightforward approach as presented by @gian-paolo.



                                      Otherwise, if these conditions are well established, and are kind of "solid rules" that will never change, consider my last code snippet.






                                      share|improve this answer























                                        up vote
                                        7
                                        down vote










                                        up vote
                                        7
                                        down vote









                                        It's easy to notice that first two scenarios are similar - they share most of the conditions. If you want to select in which scenario you are at the moment, you could write it like this (it's a modified @gian-paolo's solution):



                                        bool valid = false;
                                        if(bValue1 && bValue2 && bValue3)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                                        valid = true; //scenario 3


                                        Going further, you can notice, that first boolean needs to be always true, which is an entry condition, so you can end up with:



                                        bool valid = false;
                                        if(bValue1)
                                        {
                                        if(bValue2 && bValue3)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (!bValue2 && !bValue3 && !bValue4)
                                        valid = true; //scenario 3
                                        }


                                        Even more, you can now clearly see, that bValue2 and bValue3 are somewhat connected - you could extract their state to some external functions or variables with more appropriate name (this is not always easy or appropriate though):



                                        bool valid = false;
                                        if(bValue1)
                                        {
                                        bool bValue1and2 = bValue1 && bValue2;
                                        bool notBValue1and2 = !bValue2 && !bValue3;
                                        if(bValue1and2)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (notBValue1and2 && !bValue4)
                                        valid = true; //scenario 3
                                        }


                                        Doing it this way have some advantages and disadvantages:




                                        • conditions are smaller, so it's easier to reason about them,

                                        • it's easier to do nice renaming to make these conditions more understandable,

                                        • but, they require to understand the scope,

                                        • moreover it's more rigid


                                        If you predict that there will be changes to the above logic, you should use more straightforward approach as presented by @gian-paolo.



                                        Otherwise, if these conditions are well established, and are kind of "solid rules" that will never change, consider my last code snippet.






                                        share|improve this answer












                                        It's easy to notice that first two scenarios are similar - they share most of the conditions. If you want to select in which scenario you are at the moment, you could write it like this (it's a modified @gian-paolo's solution):



                                        bool valid = false;
                                        if(bValue1 && bValue2 && bValue3)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (bValue1 && !bValue2 && !bValue3 && !bValue4)
                                        valid = true; //scenario 3


                                        Going further, you can notice, that first boolean needs to be always true, which is an entry condition, so you can end up with:



                                        bool valid = false;
                                        if(bValue1)
                                        {
                                        if(bValue2 && bValue3)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (!bValue2 && !bValue3 && !bValue4)
                                        valid = true; //scenario 3
                                        }


                                        Even more, you can now clearly see, that bValue2 and bValue3 are somewhat connected - you could extract their state to some external functions or variables with more appropriate name (this is not always easy or appropriate though):



                                        bool valid = false;
                                        if(bValue1)
                                        {
                                        bool bValue1and2 = bValue1 && bValue2;
                                        bool notBValue1and2 = !bValue2 && !bValue3;
                                        if(bValue1and2)
                                        {
                                        if (bValue4)
                                        valid = true; //scenario 1
                                        else if (!bValue4)
                                        valid = true; //scenario 2
                                        }
                                        else if (notBValue1and2 && !bValue4)
                                        valid = true; //scenario 3
                                        }


                                        Doing it this way have some advantages and disadvantages:




                                        • conditions are smaller, so it's easier to reason about them,

                                        • it's easier to do nice renaming to make these conditions more understandable,

                                        • but, they require to understand the scope,

                                        • moreover it's more rigid


                                        If you predict that there will be changes to the above logic, you should use more straightforward approach as presented by @gian-paolo.



                                        Otherwise, if these conditions are well established, and are kind of "solid rules" that will never change, consider my last code snippet.







                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Dec 3 at 11:37









                                        Michał Łoś

                                        365210




                                        365210






















                                            up vote
                                            6
                                            down vote













                                            A slight variation on @GianPaolo's fine answer, which some may find easier to read:



                                            bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
                                            {
                                            return (v1 && v2 && v3 && v4) // scenario 1
                                            || (v1 && v2 && v3 && !v4) // scenario 2
                                            || (v1 && !v2 && !v3 && !v4); // scenario 3
                                            }

                                            if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
                                            {
                                            // ...
                                            }





                                            share|improve this answer

























                                              up vote
                                              6
                                              down vote













                                              A slight variation on @GianPaolo's fine answer, which some may find easier to read:



                                              bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
                                              {
                                              return (v1 && v2 && v3 && v4) // scenario 1
                                              || (v1 && v2 && v3 && !v4) // scenario 2
                                              || (v1 && !v2 && !v3 && !v4); // scenario 3
                                              }

                                              if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
                                              {
                                              // ...
                                              }





                                              share|improve this answer























                                                up vote
                                                6
                                                down vote










                                                up vote
                                                6
                                                down vote









                                                A slight variation on @GianPaolo's fine answer, which some may find easier to read:



                                                bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
                                                {
                                                return (v1 && v2 && v3 && v4) // scenario 1
                                                || (v1 && v2 && v3 && !v4) // scenario 2
                                                || (v1 && !v2 && !v3 && !v4); // scenario 3
                                                }

                                                if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
                                                {
                                                // ...
                                                }





                                                share|improve this answer












                                                A slight variation on @GianPaolo's fine answer, which some may find easier to read:



                                                bool any_of_three_scenarios(bool v1, bool v2, bool v3, bool v4)
                                                {
                                                return (v1 && v2 && v3 && v4) // scenario 1
                                                || (v1 && v2 && v3 && !v4) // scenario 2
                                                || (v1 && !v2 && !v3 && !v4); // scenario 3
                                                }

                                                if (any_of_three_scenarios(bValue1,bValue2,bValue3,bValue4))
                                                {
                                                // ...
                                                }






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Dec 3 at 22:04









                                                Matt

                                                15.2k13447




                                                15.2k13447






















                                                    up vote
                                                    6
                                                    down vote













                                                    Every answer is overly complex and difficult to read. The best solution to this is a switch() statement. It is both readable and makes adding/modifying additional cases simple. Compilers are good at optimising switch() statements too.



                                                    switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
                                                    {
                                                    case 0b1111:
                                                    // scenario 1
                                                    break;

                                                    case 0b0111:
                                                    // scenario 2
                                                    break;

                                                    case 0b0001:
                                                    // scenario 3
                                                    break;

                                                    default:
                                                    // fault condition
                                                    break;
                                                    }


                                                    You can of course use constants and OR them together in the case statements for even greater readability.






                                                    share|improve this answer























                                                    • Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                      – Simon F
                                                      Dec 6 at 14:17















                                                    up vote
                                                    6
                                                    down vote













                                                    Every answer is overly complex and difficult to read. The best solution to this is a switch() statement. It is both readable and makes adding/modifying additional cases simple. Compilers are good at optimising switch() statements too.



                                                    switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
                                                    {
                                                    case 0b1111:
                                                    // scenario 1
                                                    break;

                                                    case 0b0111:
                                                    // scenario 2
                                                    break;

                                                    case 0b0001:
                                                    // scenario 3
                                                    break;

                                                    default:
                                                    // fault condition
                                                    break;
                                                    }


                                                    You can of course use constants and OR them together in the case statements for even greater readability.






                                                    share|improve this answer























                                                    • Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                      – Simon F
                                                      Dec 6 at 14:17













                                                    up vote
                                                    6
                                                    down vote










                                                    up vote
                                                    6
                                                    down vote









                                                    Every answer is overly complex and difficult to read. The best solution to this is a switch() statement. It is both readable and makes adding/modifying additional cases simple. Compilers are good at optimising switch() statements too.



                                                    switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
                                                    {
                                                    case 0b1111:
                                                    // scenario 1
                                                    break;

                                                    case 0b0111:
                                                    // scenario 2
                                                    break;

                                                    case 0b0001:
                                                    // scenario 3
                                                    break;

                                                    default:
                                                    // fault condition
                                                    break;
                                                    }


                                                    You can of course use constants and OR them together in the case statements for even greater readability.






                                                    share|improve this answer














                                                    Every answer is overly complex and difficult to read. The best solution to this is a switch() statement. It is both readable and makes adding/modifying additional cases simple. Compilers are good at optimising switch() statements too.



                                                    switch( (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1) )
                                                    {
                                                    case 0b1111:
                                                    // scenario 1
                                                    break;

                                                    case 0b0111:
                                                    // scenario 2
                                                    break;

                                                    case 0b0001:
                                                    // scenario 3
                                                    break;

                                                    default:
                                                    // fault condition
                                                    break;
                                                    }


                                                    You can of course use constants and OR them together in the case statements for even greater readability.







                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Dec 5 at 14:34

























                                                    answered Dec 4 at 12:02









                                                    shogged

                                                    2167




                                                    2167












                                                    • Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                      – Simon F
                                                      Dec 6 at 14:17


















                                                    • Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                      – Simon F
                                                      Dec 6 at 14:17
















                                                    Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                    – Simon F
                                                    Dec 6 at 14:17




                                                    Being an old C-programmer, I'd define a "PackBools" macro and use that both for the "switch(PackBools(a,b,c,d))" and for the cases, eg either directly "case PackBools(true, true...)" or define them as local constants.e.g. "const unsigned int scenario1 = PackBools(true, true...);"
                                                    – Simon F
                                                    Dec 6 at 14:17










                                                    up vote
                                                    5
                                                    down vote













                                                    I would also use shortcut variables for clarity. As noted earlier scenario 1 equals to scenario 2, because the value of bValue4 doesn't influence the truth of those two scenarios.



                                                    bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
                                                    bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)


                                                    then your expression beomes:



                                                    if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
                                                    {
                                                    // do something
                                                    }
                                                    else
                                                    {
                                                    // There is some error
                                                    }


                                                    Giving meaningful names to MAJORTRUE and MAJORFALSE variables (as well as actually to bValue* vars) would help a lot with readability and maintenance.






                                                    share|improve this answer

























                                                      up vote
                                                      5
                                                      down vote













                                                      I would also use shortcut variables for clarity. As noted earlier scenario 1 equals to scenario 2, because the value of bValue4 doesn't influence the truth of those two scenarios.



                                                      bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
                                                      bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)


                                                      then your expression beomes:



                                                      if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
                                                      {
                                                      // do something
                                                      }
                                                      else
                                                      {
                                                      // There is some error
                                                      }


                                                      Giving meaningful names to MAJORTRUE and MAJORFALSE variables (as well as actually to bValue* vars) would help a lot with readability and maintenance.






                                                      share|improve this answer























                                                        up vote
                                                        5
                                                        down vote










                                                        up vote
                                                        5
                                                        down vote









                                                        I would also use shortcut variables for clarity. As noted earlier scenario 1 equals to scenario 2, because the value of bValue4 doesn't influence the truth of those two scenarios.



                                                        bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
                                                        bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)


                                                        then your expression beomes:



                                                        if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
                                                        {
                                                        // do something
                                                        }
                                                        else
                                                        {
                                                        // There is some error
                                                        }


                                                        Giving meaningful names to MAJORTRUE and MAJORFALSE variables (as well as actually to bValue* vars) would help a lot with readability and maintenance.






                                                        share|improve this answer












                                                        I would also use shortcut variables for clarity. As noted earlier scenario 1 equals to scenario 2, because the value of bValue4 doesn't influence the truth of those two scenarios.



                                                        bool MAJORLY_TRUE=bValue1 && bValue2 && bValue3
                                                        bool MAJORLY_FALSE=!(bValue2 || bValue3 || bValue4)


                                                        then your expression beomes:



                                                        if (MAJORLY_TRUE || (bValue1 && MAJORLY_FALSE))
                                                        {
                                                        // do something
                                                        }
                                                        else
                                                        {
                                                        // There is some error
                                                        }


                                                        Giving meaningful names to MAJORTRUE and MAJORFALSE variables (as well as actually to bValue* vars) would help a lot with readability and maintenance.







                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Dec 3 at 11:59









                                                        Gnudiff

                                                        3,31111721




                                                        3,31111721






















                                                            up vote
                                                            5
                                                            down vote













                                                            As suggested by mch, you could do:



                                                            if(!((bValue1 && bValue2 && bValue3) || 
                                                            (bValue1 && !bValue2 && !bValue3 && !bValue4))
                                                            )


                                                            where the first line covers the two first good cases, and the second line covers the last one.



                                                            Live Demo, where I played around and it passes your cases.






                                                            share|improve this answer



























                                                              up vote
                                                              5
                                                              down vote













                                                              As suggested by mch, you could do:



                                                              if(!((bValue1 && bValue2 && bValue3) || 
                                                              (bValue1 && !bValue2 && !bValue3 && !bValue4))
                                                              )


                                                              where the first line covers the two first good cases, and the second line covers the last one.



                                                              Live Demo, where I played around and it passes your cases.






                                                              share|improve this answer

























                                                                up vote
                                                                5
                                                                down vote










                                                                up vote
                                                                5
                                                                down vote









                                                                As suggested by mch, you could do:



                                                                if(!((bValue1 && bValue2 && bValue3) || 
                                                                (bValue1 && !bValue2 && !bValue3 && !bValue4))
                                                                )


                                                                where the first line covers the two first good cases, and the second line covers the last one.



                                                                Live Demo, where I played around and it passes your cases.






                                                                share|improve this answer














                                                                As suggested by mch, you could do:



                                                                if(!((bValue1 && bValue2 && bValue3) || 
                                                                (bValue1 && !bValue2 && !bValue3 && !bValue4))
                                                                )


                                                                where the first line covers the two first good cases, and the second line covers the last one.



                                                                Live Demo, where I played around and it passes your cases.







                                                                share|improve this answer














                                                                share|improve this answer



                                                                share|improve this answer








                                                                edited Dec 3 at 12:43

























                                                                answered Dec 3 at 10:29









                                                                gsamaras

                                                                49.9k2398181




                                                                49.9k2398181






















                                                                    up vote
                                                                    5
                                                                    down vote













                                                                    Focus on readability of the problem, not the specific "if" statement.



                                                                    While this will produce more lines of code, and some may consider it either overkill or unnecessary. I'd suggest that abstracting your scenarios from the specific booleans is the best way to maintain readability.



                                                                    By splitting things into classes (feel free to just use functions, or whatever other tool you prefer) with understandable names - we can much more easily show the meanings behind each scenario. More importantly, in a system with many moving parts - it is easier to maintain and join into your existing systems (again, despite how much extra code is involed).



                                                                    #include <iostream>
                                                                    #include <vector>
                                                                    using namespace std;

                                                                    // These values would likely not come from a single struct in real life
                                                                    // Instead, they may be references to other booleans in other systems
                                                                    struct Values
                                                                    {
                                                                    bool bValue1; // These would be given better names in reality
                                                                    bool bValue2; // e.g. bDidTheCarCatchFire
                                                                    bool bValue3; // and bDidTheWindshieldFallOff
                                                                    bool bValue4;
                                                                    };

                                                                    class Scenario
                                                                    {
                                                                    public:
                                                                    Scenario(Values& values)
                                                                    : mValues(values) {}

                                                                    virtual operator bool() = 0;

                                                                    protected:
                                                                    Values& mValues;
                                                                    };

                                                                    // Names as examples of things that describe your "scenarios" more effectively
                                                                    class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && !mValues.bValue2
                                                                    && !mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
                                                                    {
                                                                    for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
                                                                    {
                                                                    if (**it)
                                                                    {
                                                                    return *it;
                                                                    }
                                                                    }
                                                                    return NULL;
                                                                    }

                                                                    int main() {
                                                                    Values values = {true, true, true, true};
                                                                    std::vector<Scenario*> scenarios = {
                                                                    new Scenario1_TheCarWasNotDamagedAtAll(values),
                                                                    new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
                                                                    new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
                                                                    };

                                                                    Scenario* matchingScenario = findMatchingScenario(scenarios);

                                                                    if(matchingScenario)
                                                                    {
                                                                    std::cout << matchingScenario << " was a match" << std::endl;
                                                                    }
                                                                    else
                                                                    {
                                                                    std::cout << "No match" << std::endl;
                                                                    }

                                                                    // your code goes here
                                                                    return 0;
                                                                    }





                                                                    share|improve this answer

















                                                                    • 5




                                                                      At some point, verbosity starts to harm readability. I think this goes too far.
                                                                      – JollyJoker
                                                                      Dec 3 at 13:01






                                                                    • 2




                                                                      @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                      – Bilkokuya
                                                                      Dec 3 at 13:30















                                                                    up vote
                                                                    5
                                                                    down vote













                                                                    Focus on readability of the problem, not the specific "if" statement.



                                                                    While this will produce more lines of code, and some may consider it either overkill or unnecessary. I'd suggest that abstracting your scenarios from the specific booleans is the best way to maintain readability.



                                                                    By splitting things into classes (feel free to just use functions, or whatever other tool you prefer) with understandable names - we can much more easily show the meanings behind each scenario. More importantly, in a system with many moving parts - it is easier to maintain and join into your existing systems (again, despite how much extra code is involed).



                                                                    #include <iostream>
                                                                    #include <vector>
                                                                    using namespace std;

                                                                    // These values would likely not come from a single struct in real life
                                                                    // Instead, they may be references to other booleans in other systems
                                                                    struct Values
                                                                    {
                                                                    bool bValue1; // These would be given better names in reality
                                                                    bool bValue2; // e.g. bDidTheCarCatchFire
                                                                    bool bValue3; // and bDidTheWindshieldFallOff
                                                                    bool bValue4;
                                                                    };

                                                                    class Scenario
                                                                    {
                                                                    public:
                                                                    Scenario(Values& values)
                                                                    : mValues(values) {}

                                                                    virtual operator bool() = 0;

                                                                    protected:
                                                                    Values& mValues;
                                                                    };

                                                                    // Names as examples of things that describe your "scenarios" more effectively
                                                                    class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && !mValues.bValue2
                                                                    && !mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
                                                                    {
                                                                    for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
                                                                    {
                                                                    if (**it)
                                                                    {
                                                                    return *it;
                                                                    }
                                                                    }
                                                                    return NULL;
                                                                    }

                                                                    int main() {
                                                                    Values values = {true, true, true, true};
                                                                    std::vector<Scenario*> scenarios = {
                                                                    new Scenario1_TheCarWasNotDamagedAtAll(values),
                                                                    new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
                                                                    new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
                                                                    };

                                                                    Scenario* matchingScenario = findMatchingScenario(scenarios);

                                                                    if(matchingScenario)
                                                                    {
                                                                    std::cout << matchingScenario << " was a match" << std::endl;
                                                                    }
                                                                    else
                                                                    {
                                                                    std::cout << "No match" << std::endl;
                                                                    }

                                                                    // your code goes here
                                                                    return 0;
                                                                    }





                                                                    share|improve this answer

















                                                                    • 5




                                                                      At some point, verbosity starts to harm readability. I think this goes too far.
                                                                      – JollyJoker
                                                                      Dec 3 at 13:01






                                                                    • 2




                                                                      @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                      – Bilkokuya
                                                                      Dec 3 at 13:30













                                                                    up vote
                                                                    5
                                                                    down vote










                                                                    up vote
                                                                    5
                                                                    down vote









                                                                    Focus on readability of the problem, not the specific "if" statement.



                                                                    While this will produce more lines of code, and some may consider it either overkill or unnecessary. I'd suggest that abstracting your scenarios from the specific booleans is the best way to maintain readability.



                                                                    By splitting things into classes (feel free to just use functions, or whatever other tool you prefer) with understandable names - we can much more easily show the meanings behind each scenario. More importantly, in a system with many moving parts - it is easier to maintain and join into your existing systems (again, despite how much extra code is involed).



                                                                    #include <iostream>
                                                                    #include <vector>
                                                                    using namespace std;

                                                                    // These values would likely not come from a single struct in real life
                                                                    // Instead, they may be references to other booleans in other systems
                                                                    struct Values
                                                                    {
                                                                    bool bValue1; // These would be given better names in reality
                                                                    bool bValue2; // e.g. bDidTheCarCatchFire
                                                                    bool bValue3; // and bDidTheWindshieldFallOff
                                                                    bool bValue4;
                                                                    };

                                                                    class Scenario
                                                                    {
                                                                    public:
                                                                    Scenario(Values& values)
                                                                    : mValues(values) {}

                                                                    virtual operator bool() = 0;

                                                                    protected:
                                                                    Values& mValues;
                                                                    };

                                                                    // Names as examples of things that describe your "scenarios" more effectively
                                                                    class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && !mValues.bValue2
                                                                    && !mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
                                                                    {
                                                                    for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
                                                                    {
                                                                    if (**it)
                                                                    {
                                                                    return *it;
                                                                    }
                                                                    }
                                                                    return NULL;
                                                                    }

                                                                    int main() {
                                                                    Values values = {true, true, true, true};
                                                                    std::vector<Scenario*> scenarios = {
                                                                    new Scenario1_TheCarWasNotDamagedAtAll(values),
                                                                    new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
                                                                    new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
                                                                    };

                                                                    Scenario* matchingScenario = findMatchingScenario(scenarios);

                                                                    if(matchingScenario)
                                                                    {
                                                                    std::cout << matchingScenario << " was a match" << std::endl;
                                                                    }
                                                                    else
                                                                    {
                                                                    std::cout << "No match" << std::endl;
                                                                    }

                                                                    // your code goes here
                                                                    return 0;
                                                                    }





                                                                    share|improve this answer












                                                                    Focus on readability of the problem, not the specific "if" statement.



                                                                    While this will produce more lines of code, and some may consider it either overkill or unnecessary. I'd suggest that abstracting your scenarios from the specific booleans is the best way to maintain readability.



                                                                    By splitting things into classes (feel free to just use functions, or whatever other tool you prefer) with understandable names - we can much more easily show the meanings behind each scenario. More importantly, in a system with many moving parts - it is easier to maintain and join into your existing systems (again, despite how much extra code is involed).



                                                                    #include <iostream>
                                                                    #include <vector>
                                                                    using namespace std;

                                                                    // These values would likely not come from a single struct in real life
                                                                    // Instead, they may be references to other booleans in other systems
                                                                    struct Values
                                                                    {
                                                                    bool bValue1; // These would be given better names in reality
                                                                    bool bValue2; // e.g. bDidTheCarCatchFire
                                                                    bool bValue3; // and bDidTheWindshieldFallOff
                                                                    bool bValue4;
                                                                    };

                                                                    class Scenario
                                                                    {
                                                                    public:
                                                                    Scenario(Values& values)
                                                                    : mValues(values) {}

                                                                    virtual operator bool() = 0;

                                                                    protected:
                                                                    Values& mValues;
                                                                    };

                                                                    // Names as examples of things that describe your "scenarios" more effectively
                                                                    class Scenario1_TheCarWasNotDamagedAtAll : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario1_TheCarWasNotDamagedAtAll(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario2_TheCarBreaksDownButDidntGoOnFire : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario2_TheCarBreaksDownButDidntGoOnFire(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && mValues.bValue2
                                                                    && mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    class Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere : public Scenario
                                                                    {
                                                                    public:
                                                                    Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(Values& values) : Scenario(values) {}

                                                                    virtual operator bool()
                                                                    {
                                                                    return mValues.bValue1
                                                                    && !mValues.bValue2
                                                                    && !mValues.bValue3
                                                                    && !mValues.bValue4;
                                                                    }
                                                                    };

                                                                    Scenario* findMatchingScenario(std::vector<Scenario*>& scenarios)
                                                                    {
                                                                    for(std::vector<Scenario*>::iterator it = scenarios.begin(); it != scenarios.end(); it++)
                                                                    {
                                                                    if (**it)
                                                                    {
                                                                    return *it;
                                                                    }
                                                                    }
                                                                    return NULL;
                                                                    }

                                                                    int main() {
                                                                    Values values = {true, true, true, true};
                                                                    std::vector<Scenario*> scenarios = {
                                                                    new Scenario1_TheCarWasNotDamagedAtAll(values),
                                                                    new Scenario2_TheCarBreaksDownButDidntGoOnFire(values),
                                                                    new Scenario3_TheCarWasCompletelyWreckedAndFireEverywhere(values)
                                                                    };

                                                                    Scenario* matchingScenario = findMatchingScenario(scenarios);

                                                                    if(matchingScenario)
                                                                    {
                                                                    std::cout << matchingScenario << " was a match" << std::endl;
                                                                    }
                                                                    else
                                                                    {
                                                                    std::cout << "No match" << std::endl;
                                                                    }

                                                                    // your code goes here
                                                                    return 0;
                                                                    }






                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered Dec 3 at 12:54









                                                                    Bilkokuya

                                                                    770616




                                                                    770616








                                                                    • 5




                                                                      At some point, verbosity starts to harm readability. I think this goes too far.
                                                                      – JollyJoker
                                                                      Dec 3 at 13:01






                                                                    • 2




                                                                      @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                      – Bilkokuya
                                                                      Dec 3 at 13:30














                                                                    • 5




                                                                      At some point, verbosity starts to harm readability. I think this goes too far.
                                                                      – JollyJoker
                                                                      Dec 3 at 13:01






                                                                    • 2




                                                                      @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                      – Bilkokuya
                                                                      Dec 3 at 13:30








                                                                    5




                                                                    5




                                                                    At some point, verbosity starts to harm readability. I think this goes too far.
                                                                    – JollyJoker
                                                                    Dec 3 at 13:01




                                                                    At some point, verbosity starts to harm readability. I think this goes too far.
                                                                    – JollyJoker
                                                                    Dec 3 at 13:01




                                                                    2




                                                                    2




                                                                    @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                    – Bilkokuya
                                                                    Dec 3 at 13:30




                                                                    @JollyJoker I do actually agree in this specific situation - however, my gut feeling from the way OP has named everything extremely generically, is that their "real" code is likely a lot more complex than the example they've given. Really, I just wanted to put this alternative out there, as it's how I'd structure it for something far more complex/involved. But you're right - for OPs specific example, it is overly verbose and makes matters worse.
                                                                    – Bilkokuya
                                                                    Dec 3 at 13:30










                                                                    up vote
                                                                    4
                                                                    down vote













                                                                    I am denoting a, b, c, d for clarity, and A, B, C, D for complements



                                                                    bValue1 = a (!A)
                                                                    bValue2 = b (!B)
                                                                    bValue3 = c (!C)
                                                                    bValue4 = d (!D)


                                                                    Equation



                                                                    1 = abcd + abcD + aBCD
                                                                    = a (bcd + bcD + BCD)
                                                                    = a (bc + BCD)
                                                                    = a (bcd + D (b ^C))


                                                                    Use any equations that suits you.






                                                                    share|improve this answer

























                                                                      up vote
                                                                      4
                                                                      down vote













                                                                      I am denoting a, b, c, d for clarity, and A, B, C, D for complements



                                                                      bValue1 = a (!A)
                                                                      bValue2 = b (!B)
                                                                      bValue3 = c (!C)
                                                                      bValue4 = d (!D)


                                                                      Equation



                                                                      1 = abcd + abcD + aBCD
                                                                      = a (bcd + bcD + BCD)
                                                                      = a (bc + BCD)
                                                                      = a (bcd + D (b ^C))


                                                                      Use any equations that suits you.






                                                                      share|improve this answer























                                                                        up vote
                                                                        4
                                                                        down vote










                                                                        up vote
                                                                        4
                                                                        down vote









                                                                        I am denoting a, b, c, d for clarity, and A, B, C, D for complements



                                                                        bValue1 = a (!A)
                                                                        bValue2 = b (!B)
                                                                        bValue3 = c (!C)
                                                                        bValue4 = d (!D)


                                                                        Equation



                                                                        1 = abcd + abcD + aBCD
                                                                        = a (bcd + bcD + BCD)
                                                                        = a (bc + BCD)
                                                                        = a (bcd + D (b ^C))


                                                                        Use any equations that suits you.






                                                                        share|improve this answer












                                                                        I am denoting a, b, c, d for clarity, and A, B, C, D for complements



                                                                        bValue1 = a (!A)
                                                                        bValue2 = b (!B)
                                                                        bValue3 = c (!C)
                                                                        bValue4 = d (!D)


                                                                        Equation



                                                                        1 = abcd + abcD + aBCD
                                                                        = a (bcd + bcD + BCD)
                                                                        = a (bc + BCD)
                                                                        = a (bcd + D (b ^C))


                                                                        Use any equations that suits you.







                                                                        share|improve this answer












                                                                        share|improve this answer



                                                                        share|improve this answer










                                                                        answered Dec 3 at 10:42









                                                                        yumoji

                                                                        1,52211123




                                                                        1,52211123






















                                                                            up vote
                                                                            4
                                                                            down vote













                                                                            Doing bitwise operation looks very clean and understandable.



                                                                            int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
                                                                            if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
                                                                            {
                                                                            //satisfying condition
                                                                            }





                                                                            share|improve this answer





















                                                                            • The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                              – xtofl
                                                                              Dec 5 at 7:25















                                                                            up vote
                                                                            4
                                                                            down vote













                                                                            Doing bitwise operation looks very clean and understandable.



                                                                            int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
                                                                            if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
                                                                            {
                                                                            //satisfying condition
                                                                            }





                                                                            share|improve this answer





















                                                                            • The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                              – xtofl
                                                                              Dec 5 at 7:25













                                                                            up vote
                                                                            4
                                                                            down vote










                                                                            up vote
                                                                            4
                                                                            down vote









                                                                            Doing bitwise operation looks very clean and understandable.



                                                                            int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
                                                                            if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
                                                                            {
                                                                            //satisfying condition
                                                                            }





                                                                            share|improve this answer












                                                                            Doing bitwise operation looks very clean and understandable.



                                                                            int bitwise = (bValue4 << 3) | (bValue3 << 2) | (bValue2 << 1) | (bValue1);
                                                                            if (bitwise == 0b1111 || bitwise == 0b0111 || bitwise == 0b0001)
                                                                            {
                                                                            //satisfying condition
                                                                            }






                                                                            share|improve this answer












                                                                            share|improve this answer



                                                                            share|improve this answer










                                                                            answered Dec 4 at 22:53









                                                                            Simonare

                                                                            1,770620




                                                                            1,770620












                                                                            • The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                              – xtofl
                                                                              Dec 5 at 7:25


















                                                                            • The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                              – xtofl
                                                                              Dec 5 at 7:25
















                                                                            The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                            – xtofl
                                                                            Dec 5 at 7:25




                                                                            The bitwise comparison looks readable to me. The composition, on the other hand, looks artificial.
                                                                            – xtofl
                                                                            Dec 5 at 7:25










                                                                            up vote
                                                                            4
                                                                            down vote













                                                                            It depends on what they represent.



                                                                            For example if 1 is a key, and 2 and 3 are two people who must agree (except if they agree on NOT they need a third person - 4 - to confirm) the most readable might be:



                                                                            1 &&
                                                                            (
                                                                            (2 && 3)
                                                                            ||
                                                                            ((!2 && !3) && !4)
                                                                            )


                                                                            by popular request:



                                                                            Key &&
                                                                            (
                                                                            (Alice && Bob)
                                                                            ||
                                                                            ((!Alice && !Bob) && !Charlie)
                                                                            )





                                                                            share|improve this answer



















                                                                            • 2




                                                                              You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                              – jxh
                                                                              Dec 3 at 22:45






                                                                            • 1




                                                                              @jxh Those are the numbers OP used. I just removed the bValue.
                                                                              – ispiro
                                                                              Dec 3 at 23:26










                                                                            • @jxh I hope it's better now.
                                                                              – ispiro
                                                                              Dec 5 at 7:49















                                                                            up vote
                                                                            4
                                                                            down vote













                                                                            It depends on what they represent.



                                                                            For example if 1 is a key, and 2 and 3 are two people who must agree (except if they agree on NOT they need a third person - 4 - to confirm) the most readable might be:



                                                                            1 &&
                                                                            (
                                                                            (2 && 3)
                                                                            ||
                                                                            ((!2 && !3) && !4)
                                                                            )


                                                                            by popular request:



                                                                            Key &&
                                                                            (
                                                                            (Alice && Bob)
                                                                            ||
                                                                            ((!Alice && !Bob) && !Charlie)
                                                                            )





                                                                            share|improve this answer



















                                                                            • 2




                                                                              You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                              – jxh
                                                                              Dec 3 at 22:45






                                                                            • 1




                                                                              @jxh Those are the numbers OP used. I just removed the bValue.
                                                                              – ispiro
                                                                              Dec 3 at 23:26










                                                                            • @jxh I hope it's better now.
                                                                              – ispiro
                                                                              Dec 5 at 7:49













                                                                            up vote
                                                                            4
                                                                            down vote










                                                                            up vote
                                                                            4
                                                                            down vote









                                                                            It depends on what they represent.



                                                                            For example if 1 is a key, and 2 and 3 are two people who must agree (except if they agree on NOT they need a third person - 4 - to confirm) the most readable might be:



                                                                            1 &&
                                                                            (
                                                                            (2 && 3)
                                                                            ||
                                                                            ((!2 && !3) && !4)
                                                                            )


                                                                            by popular request:



                                                                            Key &&
                                                                            (
                                                                            (Alice && Bob)
                                                                            ||
                                                                            ((!Alice && !Bob) && !Charlie)
                                                                            )





                                                                            share|improve this answer














                                                                            It depends on what they represent.



                                                                            For example if 1 is a key, and 2 and 3 are two people who must agree (except if they agree on NOT they need a third person - 4 - to confirm) the most readable might be:



                                                                            1 &&
                                                                            (
                                                                            (2 && 3)
                                                                            ||
                                                                            ((!2 && !3) && !4)
                                                                            )


                                                                            by popular request:



                                                                            Key &&
                                                                            (
                                                                            (Alice && Bob)
                                                                            ||
                                                                            ((!Alice && !Bob) && !Charlie)
                                                                            )






                                                                            share|improve this answer














                                                                            share|improve this answer



                                                                            share|improve this answer








                                                                            edited Dec 5 at 7:48

























                                                                            answered Dec 3 at 21:58









                                                                            ispiro

                                                                            12.8k1979178




                                                                            12.8k1979178








                                                                            • 2




                                                                              You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                              – jxh
                                                                              Dec 3 at 22:45






                                                                            • 1




                                                                              @jxh Those are the numbers OP used. I just removed the bValue.
                                                                              – ispiro
                                                                              Dec 3 at 23:26










                                                                            • @jxh I hope it's better now.
                                                                              – ispiro
                                                                              Dec 5 at 7:49














                                                                            • 2




                                                                              You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                              – jxh
                                                                              Dec 3 at 22:45






                                                                            • 1




                                                                              @jxh Those are the numbers OP used. I just removed the bValue.
                                                                              – ispiro
                                                                              Dec 3 at 23:26










                                                                            • @jxh I hope it's better now.
                                                                              – ispiro
                                                                              Dec 5 at 7:49








                                                                            2




                                                                            2




                                                                            You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                            – jxh
                                                                            Dec 3 at 22:45




                                                                            You might be right, but using numbers to illustrate your point detracts from your answer. Try using descriptive names.
                                                                            – jxh
                                                                            Dec 3 at 22:45




                                                                            1




                                                                            1




                                                                            @jxh Those are the numbers OP used. I just removed the bValue.
                                                                            – ispiro
                                                                            Dec 3 at 23:26




                                                                            @jxh Those are the numbers OP used. I just removed the bValue.
                                                                            – ispiro
                                                                            Dec 3 at 23:26












                                                                            @jxh I hope it's better now.
                                                                            – ispiro
                                                                            Dec 5 at 7:49




                                                                            @jxh I hope it's better now.
                                                                            – ispiro
                                                                            Dec 5 at 7:49










                                                                            up vote
                                                                            3
                                                                            down vote













                                                                            If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
                                                                            {
                                                                            // you have a problem
                                                                            }



                                                                            • b1 must always be true

                                                                            • b2 must always equal b3

                                                                            • and b4 cannot be false
                                                                              if b2 (and b3) are true


                                                                            simple






                                                                            share|improve this answer

























                                                                              up vote
                                                                              3
                                                                              down vote













                                                                              If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
                                                                              {
                                                                              // you have a problem
                                                                              }



                                                                              • b1 must always be true

                                                                              • b2 must always equal b3

                                                                              • and b4 cannot be false
                                                                                if b2 (and b3) are true


                                                                              simple






                                                                              share|improve this answer























                                                                                up vote
                                                                                3
                                                                                down vote










                                                                                up vote
                                                                                3
                                                                                down vote









                                                                                If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
                                                                                {
                                                                                // you have a problem
                                                                                }



                                                                                • b1 must always be true

                                                                                • b2 must always equal b3

                                                                                • and b4 cannot be false
                                                                                  if b2 (and b3) are true


                                                                                simple






                                                                                share|improve this answer












                                                                                If (!bValue1 || (bValue2 != bValue3) || (!bValue4 && bValue2))
                                                                                {
                                                                                // you have a problem
                                                                                }



                                                                                • b1 must always be true

                                                                                • b2 must always equal b3

                                                                                • and b4 cannot be false
                                                                                  if b2 (and b3) are true


                                                                                simple







                                                                                share|improve this answer












                                                                                share|improve this answer



                                                                                share|improve this answer










                                                                                answered Dec 4 at 22:36









                                                                                Owen Meyer

                                                                                311




                                                                                311






















                                                                                    up vote
                                                                                    3
                                                                                    down vote













                                                                                    Just a personal preference over the accepted answer, but I would write:



                                                                                    bool valid = false;
                                                                                    // scenario 1
                                                                                    valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
                                                                                    // scenario 2
                                                                                    valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
                                                                                    // scenario 3
                                                                                    valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);





                                                                                    share|improve this answer

























                                                                                      up vote
                                                                                      3
                                                                                      down vote













                                                                                      Just a personal preference over the accepted answer, but I would write:



                                                                                      bool valid = false;
                                                                                      // scenario 1
                                                                                      valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
                                                                                      // scenario 2
                                                                                      valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
                                                                                      // scenario 3
                                                                                      valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);





                                                                                      share|improve this answer























                                                                                        up vote
                                                                                        3
                                                                                        down vote










                                                                                        up vote
                                                                                        3
                                                                                        down vote









                                                                                        Just a personal preference over the accepted answer, but I would write:



                                                                                        bool valid = false;
                                                                                        // scenario 1
                                                                                        valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
                                                                                        // scenario 2
                                                                                        valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
                                                                                        // scenario 3
                                                                                        valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);





                                                                                        share|improve this answer












                                                                                        Just a personal preference over the accepted answer, but I would write:



                                                                                        bool valid = false;
                                                                                        // scenario 1
                                                                                        valid = valid || (bValue1 && bValue2 && bValue3 && bValue4);
                                                                                        // scenario 2
                                                                                        valid = valid || (bValue1 && bValue2 && bValue3 && !bValue4);
                                                                                        // scenario 3
                                                                                        valid = valid || (bValue1 && !bValue2 && !bValue3 && !bValue4);






                                                                                        share|improve this answer












                                                                                        share|improve this answer



                                                                                        share|improve this answer










                                                                                        answered Dec 7 at 2:40









                                                                                        François Gueguen

                                                                                        414




                                                                                        414






















                                                                                            up vote
                                                                                            2
                                                                                            down vote













                                                                                            First, assuming you can only modify the scenario check, I would focus on readability and just wrap the check in a function so that you can just call if(ScenarioA()).





                                                                                            Now, assuming you actually want/need to optimize this, I would recommend converting the tightly linked Booleans into constant integers, and using bit operators on them



                                                                                            public class Options {
                                                                                            public const bool A = 2; // 0001
                                                                                            public const bool B = 4; // 0010
                                                                                            public const bool C = 16;// 0100
                                                                                            public const bool D = 32;// 1000
                                                                                            //public const bool N = 2^n; (up to n=32)
                                                                                            }

                                                                                            ...

                                                                                            public isScenario3(int options) {
                                                                                            int s3 = Options.A | Options.B | Options.C;
                                                                                            // for true if only s3 options are set
                                                                                            return options == s3;
                                                                                            // for true if s3 options are set
                                                                                            // return options & s3 == s3
                                                                                            }


                                                                                            This makes expressing the scenarios as easy as listing what is part of it, allows you to use a switch statement to jump to the right condition, and confuse fellow developers who have not seen this before. (C# RegexOptions uses this pattern for setting flags, I don't know if there is a c++ library example)






                                                                                            share|improve this answer





















                                                                                            • In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 5:30















                                                                                            up vote
                                                                                            2
                                                                                            down vote













                                                                                            First, assuming you can only modify the scenario check, I would focus on readability and just wrap the check in a function so that you can just call if(ScenarioA()).





                                                                                            Now, assuming you actually want/need to optimize this, I would recommend converting the tightly linked Booleans into constant integers, and using bit operators on them



                                                                                            public class Options {
                                                                                            public const bool A = 2; // 0001
                                                                                            public const bool B = 4; // 0010
                                                                                            public const bool C = 16;// 0100
                                                                                            public const bool D = 32;// 1000
                                                                                            //public const bool N = 2^n; (up to n=32)
                                                                                            }

                                                                                            ...

                                                                                            public isScenario3(int options) {
                                                                                            int s3 = Options.A | Options.B | Options.C;
                                                                                            // for true if only s3 options are set
                                                                                            return options == s3;
                                                                                            // for true if s3 options are set
                                                                                            // return options & s3 == s3
                                                                                            }


                                                                                            This makes expressing the scenarios as easy as listing what is part of it, allows you to use a switch statement to jump to the right condition, and confuse fellow developers who have not seen this before. (C# RegexOptions uses this pattern for setting flags, I don't know if there is a c++ library example)






                                                                                            share|improve this answer





















                                                                                            • In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 5:30













                                                                                            up vote
                                                                                            2
                                                                                            down vote










                                                                                            up vote
                                                                                            2
                                                                                            down vote









                                                                                            First, assuming you can only modify the scenario check, I would focus on readability and just wrap the check in a function so that you can just call if(ScenarioA()).





                                                                                            Now, assuming you actually want/need to optimize this, I would recommend converting the tightly linked Booleans into constant integers, and using bit operators on them



                                                                                            public class Options {
                                                                                            public const bool A = 2; // 0001
                                                                                            public const bool B = 4; // 0010
                                                                                            public const bool C = 16;// 0100
                                                                                            public const bool D = 32;// 1000
                                                                                            //public const bool N = 2^n; (up to n=32)
                                                                                            }

                                                                                            ...

                                                                                            public isScenario3(int options) {
                                                                                            int s3 = Options.A | Options.B | Options.C;
                                                                                            // for true if only s3 options are set
                                                                                            return options == s3;
                                                                                            // for true if s3 options are set
                                                                                            // return options & s3 == s3
                                                                                            }


                                                                                            This makes expressing the scenarios as easy as listing what is part of it, allows you to use a switch statement to jump to the right condition, and confuse fellow developers who have not seen this before. (C# RegexOptions uses this pattern for setting flags, I don't know if there is a c++ library example)






                                                                                            share|improve this answer












                                                                                            First, assuming you can only modify the scenario check, I would focus on readability and just wrap the check in a function so that you can just call if(ScenarioA()).





                                                                                            Now, assuming you actually want/need to optimize this, I would recommend converting the tightly linked Booleans into constant integers, and using bit operators on them



                                                                                            public class Options {
                                                                                            public const bool A = 2; // 0001
                                                                                            public const bool B = 4; // 0010
                                                                                            public const bool C = 16;// 0100
                                                                                            public const bool D = 32;// 1000
                                                                                            //public const bool N = 2^n; (up to n=32)
                                                                                            }

                                                                                            ...

                                                                                            public isScenario3(int options) {
                                                                                            int s3 = Options.A | Options.B | Options.C;
                                                                                            // for true if only s3 options are set
                                                                                            return options == s3;
                                                                                            // for true if s3 options are set
                                                                                            // return options & s3 == s3
                                                                                            }


                                                                                            This makes expressing the scenarios as easy as listing what is part of it, allows you to use a switch statement to jump to the right condition, and confuse fellow developers who have not seen this before. (C# RegexOptions uses this pattern for setting flags, I don't know if there is a c++ library example)







                                                                                            share|improve this answer












                                                                                            share|improve this answer



                                                                                            share|improve this answer










                                                                                            answered Dec 4 at 16:03









                                                                                            Tezra

                                                                                            4,95621042




                                                                                            4,95621042












                                                                                            • In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 5:30


















                                                                                            • In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 5:30
















                                                                                            In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                            – Andrew Truckle
                                                                                            Dec 5 at 5:30




                                                                                            In actual fact I am not using four bool values but a DWORD with four embedded BOOLS. Too late to change it now. But thanks for your suggestion.
                                                                                            – Andrew Truckle
                                                                                            Dec 5 at 5:30










                                                                                            up vote
                                                                                            2
                                                                                            down vote













                                                                                            Nested ifs could be easier to read for some people. Here is my version



                                                                                            bool check(int bValue1, int bValue2, int bValue3, int bValue4)
                                                                                            {
                                                                                            if (bValue1)
                                                                                            {
                                                                                            if (bValue2)
                                                                                            {
                                                                                            // scenario 1-2
                                                                                            return bValue3;
                                                                                            }
                                                                                            else
                                                                                            {
                                                                                            // scenario 3
                                                                                            return !bValue3 && !bValue4;
                                                                                            }
                                                                                            }

                                                                                            return false;
                                                                                            }





                                                                                            share|improve this answer





















                                                                                            • Another interesting variation. Thank you.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 17:14










                                                                                            • Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                              – Dnomyar96
                                                                                              Dec 6 at 10:57












                                                                                            • @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                              – sardok
                                                                                              Dec 6 at 11:14















                                                                                            up vote
                                                                                            2
                                                                                            down vote













                                                                                            Nested ifs could be easier to read for some people. Here is my version



                                                                                            bool check(int bValue1, int bValue2, int bValue3, int bValue4)
                                                                                            {
                                                                                            if (bValue1)
                                                                                            {
                                                                                            if (bValue2)
                                                                                            {
                                                                                            // scenario 1-2
                                                                                            return bValue3;
                                                                                            }
                                                                                            else
                                                                                            {
                                                                                            // scenario 3
                                                                                            return !bValue3 && !bValue4;
                                                                                            }
                                                                                            }

                                                                                            return false;
                                                                                            }





                                                                                            share|improve this answer





















                                                                                            • Another interesting variation. Thank you.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 17:14










                                                                                            • Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                              – Dnomyar96
                                                                                              Dec 6 at 10:57












                                                                                            • @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                              – sardok
                                                                                              Dec 6 at 11:14













                                                                                            up vote
                                                                                            2
                                                                                            down vote










                                                                                            up vote
                                                                                            2
                                                                                            down vote









                                                                                            Nested ifs could be easier to read for some people. Here is my version



                                                                                            bool check(int bValue1, int bValue2, int bValue3, int bValue4)
                                                                                            {
                                                                                            if (bValue1)
                                                                                            {
                                                                                            if (bValue2)
                                                                                            {
                                                                                            // scenario 1-2
                                                                                            return bValue3;
                                                                                            }
                                                                                            else
                                                                                            {
                                                                                            // scenario 3
                                                                                            return !bValue3 && !bValue4;
                                                                                            }
                                                                                            }

                                                                                            return false;
                                                                                            }





                                                                                            share|improve this answer












                                                                                            Nested ifs could be easier to read for some people. Here is my version



                                                                                            bool check(int bValue1, int bValue2, int bValue3, int bValue4)
                                                                                            {
                                                                                            if (bValue1)
                                                                                            {
                                                                                            if (bValue2)
                                                                                            {
                                                                                            // scenario 1-2
                                                                                            return bValue3;
                                                                                            }
                                                                                            else
                                                                                            {
                                                                                            // scenario 3
                                                                                            return !bValue3 && !bValue4;
                                                                                            }
                                                                                            }

                                                                                            return false;
                                                                                            }






                                                                                            share|improve this answer












                                                                                            share|improve this answer



                                                                                            share|improve this answer










                                                                                            answered Dec 5 at 16:17









                                                                                            sardok

                                                                                            6921514




                                                                                            6921514












                                                                                            • Another interesting variation. Thank you.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 17:14










                                                                                            • Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                              – Dnomyar96
                                                                                              Dec 6 at 10:57












                                                                                            • @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                              – sardok
                                                                                              Dec 6 at 11:14


















                                                                                            • Another interesting variation. Thank you.
                                                                                              – Andrew Truckle
                                                                                              Dec 5 at 17:14










                                                                                            • Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                              – Dnomyar96
                                                                                              Dec 6 at 10:57












                                                                                            • @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                              – sardok
                                                                                              Dec 6 at 11:14
















                                                                                            Another interesting variation. Thank you.
                                                                                            – Andrew Truckle
                                                                                            Dec 5 at 17:14




                                                                                            Another interesting variation. Thank you.
                                                                                            – Andrew Truckle
                                                                                            Dec 5 at 17:14












                                                                                            Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                            – Dnomyar96
                                                                                            Dec 6 at 10:57






                                                                                            Personally, I'd usually avoid nesting if statements if possible. While this case is nice and readable, once new possibilities are added, the nesting can become very hard to read. But if the scenarios never change, it definitly is a nice and readable solution.
                                                                                            – Dnomyar96
                                                                                            Dec 6 at 10:57














                                                                                            @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                            – sardok
                                                                                            Dec 6 at 11:14




                                                                                            @Dnomyar96 i agree. I personally avoid nested ifs too. Sometimes if the logic is complicated, it is easier for me to understand the logic by breaking it down into the pieces. For example, once you enter bValue1 block, then you may treat everything in it as a new fresh page in your mental process. I bet the way of approaching to the problem may be very personal or even cultural thing.
                                                                                            – sardok
                                                                                            Dec 6 at 11:14










                                                                                            up vote
                                                                                            1
                                                                                            down vote













                                                                                            You won't have to worry about invalid combinations of boolean flags if you get rid of the boolean flags.




                                                                                            The acceptable values are:



                                                                                                     Scenario 1 | Scenario 2 | Scenario 3
                                                                                            bValue1: true | true | true
                                                                                            bValue2: true | true | false
                                                                                            bValue3: true | true | false
                                                                                            bValue4: true | false | false



                                                                                            You clearly have three states (scenarios). It'd be better to model that and to derive the boolean properties from those states, not the other way around.



                                                                                            enum State
                                                                                            {
                                                                                            scenario1,
                                                                                            scenario2,
                                                                                            scenario3,
                                                                                            };

                                                                                            inline bool isValue1(State s)
                                                                                            {
                                                                                            // (Well, this is kind of silly. Do you really need this flag?)
                                                                                            return true;
                                                                                            }

                                                                                            inline bool isValue2(State s)
                                                                                            {
                                                                                            switch (s)
                                                                                            {
                                                                                            case scenario1:
                                                                                            case scenario2:
                                                                                            return true;
                                                                                            case scenario3:
                                                                                            return false;
                                                                                            }
                                                                                            }

                                                                                            inline bool isValue3(State s)
                                                                                            {
                                                                                            // (This is silly too. Do you really need this flag?)
                                                                                            return isValue2(s);
                                                                                            }

                                                                                            inline bool isValue4(State s)
                                                                                            {
                                                                                            switch (s)
                                                                                            {
                                                                                            case scenario1:
                                                                                            return true;
                                                                                            case scenario2:
                                                                                            case scenario3:
                                                                                            return false;
                                                                                            }
                                                                                            }


                                                                                            This is definitely more code than in Gian Paolo's answer, but depending on your situation, this could be much more maintainable:




                                                                                            • There is a central set of functions to modify if additional boolean properties or scenarios are added.


                                                                                              • Adding properties requires adding only a single function.

                                                                                              • If adding a scenario, enabling compiler warnings about unhandled enum cases in switch statements will catch property-getters that don't handle that scenario.



                                                                                            • If you need to modify the boolean properties dynamically, you don't need to re-validate their combinations everywhere. Instead of toggling individual boolean flags (which could result in invalid combinations of flags), you instead would have a state machine that transitions from one scenario to another.


                                                                                            This approach also has the side benefit of being very efficient.






                                                                                            share|improve this answer



























                                                                                              up vote
                                                                                              1
                                                                                              down vote













                                                                                              You won't have to worry about invalid combinations of boolean flags if you get rid of the boolean flags.




                                                                                              The acceptable values are:



                                                                                                       Scenario 1 | Scenario 2 | Scenario 3
                                                                                              bValue1: true | true | true
                                                                                              bValue2: true | true | false
                                                                                              bValue3: true | true | false
                                                                                              bValue4: true | false | false



                                                                                              You clearly have three states (scenarios). It'd be better to model that and to derive the boolean properties from those states, not the other way around.



                                                                                              enum State
                                                                                              {
                                                                                              scenario1,
                                                                                              scenario2,
                                                                                              scenario3,
                                                                                              };

                                                                                              inline bool isValue1(State s)
                                                                                              {
                                                                                              // (Well, this is kind of silly. Do you really need this flag?)
                                                                                              return true;
                                                                                              }

                                                                                              inline bool isValue2(State s)
                                                                                              {
                                                                                              switch (s)
                                                                                              {
                                                                                              case scenario1:
                                                                                              case scenario2:
                                                                                              return true;
                                                                                              case scenario3:
                                                                                              return false;
                                                                                              }
                                                                                              }

                                                                                              inline bool isValue3(State s)
                                                                                              {
                                                                                              // (This is silly too. Do you really need this flag?)
                                                                                              return isValue2(s);
                                                                                              }

                                                                                              inline bool isValue4(State s)
                                                                                              {
                                                                                              switch (s)
                                                                                              {
                                                                                              case scenario1:
                                                                                              return true;
                                                                                              case scenario2:
                                                                                              case scenario3:
                                                                                              return false;
                                                                                              }
                                                                                              }


                                                                                              This is definitely more code than in Gian Paolo's answer, but depending on your situation, this could be much more maintainable:




                                                                                              • There is a central set of functions to modify if additional boolean properties or scenarios are added.


                                                                                                • Adding properties requires adding only a single function.

                                                                                                • If adding a scenario, enabling compiler warnings about unhandled enum cases in switch statements will catch property-getters that don't handle that scenario.



                                                                                              • If you need to modify the boolean properties dynamically, you don't need to re-validate their combinations everywhere. Instead of toggling individual boolean flags (which could result in invalid combinations of flags), you instead would have a state machine that transitions from one scenario to another.


                                                                                              This approach also has the side benefit of being very efficient.






                                                                                              share|improve this answer

























                                                                                                up vote
                                                                                                1
                                                                                                down vote










                                                                                                up vote
                                                                                                1
                                                                                                down vote









                                                                                                You won't have to worry about invalid combinations of boolean flags if you get rid of the boolean flags.




                                                                                                The acceptable values are:



                                                                                                         Scenario 1 | Scenario 2 | Scenario 3
                                                                                                bValue1: true | true | true
                                                                                                bValue2: true | true | false
                                                                                                bValue3: true | true | false
                                                                                                bValue4: true | false | false



                                                                                                You clearly have three states (scenarios). It'd be better to model that and to derive the boolean properties from those states, not the other way around.



                                                                                                enum State
                                                                                                {
                                                                                                scenario1,
                                                                                                scenario2,
                                                                                                scenario3,
                                                                                                };

                                                                                                inline bool isValue1(State s)
                                                                                                {
                                                                                                // (Well, this is kind of silly. Do you really need this flag?)
                                                                                                return true;
                                                                                                }

                                                                                                inline bool isValue2(State s)
                                                                                                {
                                                                                                switch (s)
                                                                                                {
                                                                                                case scenario1:
                                                                                                case scenario2:
                                                                                                return true;
                                                                                                case scenario3:
                                                                                                return false;
                                                                                                }
                                                                                                }

                                                                                                inline bool isValue3(State s)
                                                                                                {
                                                                                                // (This is silly too. Do you really need this flag?)
                                                                                                return isValue2(s);
                                                                                                }

                                                                                                inline bool isValue4(State s)
                                                                                                {
                                                                                                switch (s)
                                                                                                {
                                                                                                case scenario1:
                                                                                                return true;
                                                                                                case scenario2:
                                                                                                case scenario3:
                                                                                                return false;
                                                                                                }
                                                                                                }


                                                                                                This is definitely more code than in Gian Paolo's answer, but depending on your situation, this could be much more maintainable:




                                                                                                • There is a central set of functions to modify if additional boolean properties or scenarios are added.


                                                                                                  • Adding properties requires adding only a single function.

                                                                                                  • If adding a scenario, enabling compiler warnings about unhandled enum cases in switch statements will catch property-getters that don't handle that scenario.



                                                                                                • If you need to modify the boolean properties dynamically, you don't need to re-validate their combinations everywhere. Instead of toggling individual boolean flags (which could result in invalid combinations of flags), you instead would have a state machine that transitions from one scenario to another.


                                                                                                This approach also has the side benefit of being very efficient.






                                                                                                share|improve this answer














                                                                                                You won't have to worry about invalid combinations of boolean flags if you get rid of the boolean flags.




                                                                                                The acceptable values are:



                                                                                                         Scenario 1 | Scenario 2 | Scenario 3
                                                                                                bValue1: true | true | true
                                                                                                bValue2: true | true | false
                                                                                                bValue3: true | true | false
                                                                                                bValue4: true | false | false



                                                                                                You clearly have three states (scenarios). It'd be better to model that and to derive the boolean properties from those states, not the other way around.



                                                                                                enum State
                                                                                                {
                                                                                                scenario1,
                                                                                                scenario2,
                                                                                                scenario3,
                                                                                                };

                                                                                                inline bool isValue1(State s)
                                                                                                {
                                                                                                // (Well, this is kind of silly. Do you really need this flag?)
                                                                                                return true;
                                                                                                }

                                                                                                inline bool isValue2(State s)
                                                                                                {
                                                                                                switch (s)
                                                                                                {
                                                                                                case scenario1:
                                                                                                case scenario2:
                                                                                                return true;
                                                                                                case scenario3:
                                                                                                return false;
                                                                                                }
                                                                                                }

                                                                                                inline bool isValue3(State s)
                                                                                                {
                                                                                                // (This is silly too. Do you really need this flag?)
                                                                                                return isValue2(s);
                                                                                                }

                                                                                                inline bool isValue4(State s)
                                                                                                {
                                                                                                switch (s)
                                                                                                {
                                                                                                case scenario1:
                                                                                                return true;
                                                                                                case scenario2:
                                                                                                case scenario3:
                                                                                                return false;
                                                                                                }
                                                                                                }


                                                                                                This is definitely more code than in Gian Paolo's answer, but depending on your situation, this could be much more maintainable:




                                                                                                • There is a central set of functions to modify if additional boolean properties or scenarios are added.


                                                                                                  • Adding properties requires adding only a single function.

                                                                                                  • If adding a scenario, enabling compiler warnings about unhandled enum cases in switch statements will catch property-getters that don't handle that scenario.



                                                                                                • If you need to modify the boolean properties dynamically, you don't need to re-validate their combinations everywhere. Instead of toggling individual boolean flags (which could result in invalid combinations of flags), you instead would have a state machine that transitions from one scenario to another.


                                                                                                This approach also has the side benefit of being very efficient.







                                                                                                share|improve this answer














                                                                                                share|improve this answer



                                                                                                share|improve this answer








                                                                                                edited Dec 7 at 17:49

























                                                                                                answered Dec 6 at 18:17









                                                                                                jamesdlin

                                                                                                26k65992




                                                                                                26k65992






















                                                                                                    up vote
                                                                                                    0
                                                                                                    down vote













                                                                                                    My 2 cents: declare a variable sum (integer) so that



                                                                                                    if(bValue1)
                                                                                                    {
                                                                                                    sum=sum+1;
                                                                                                    }
                                                                                                    if(bValue2)
                                                                                                    {
                                                                                                    sum=sum+2;
                                                                                                    }
                                                                                                    if(bValue3)
                                                                                                    {
                                                                                                    sum=sum+4;
                                                                                                    }
                                                                                                    if(bValue4)
                                                                                                    {
                                                                                                    sum=sum+8;
                                                                                                    }


                                                                                                    Check sum against the conditions you want and that's it.
                                                                                                    This way you can add easily more conditions in the future keeping it quite straightforward to read.






                                                                                                    share|improve this answer

























                                                                                                      up vote
                                                                                                      0
                                                                                                      down vote













                                                                                                      My 2 cents: declare a variable sum (integer) so that



                                                                                                      if(bValue1)
                                                                                                      {
                                                                                                      sum=sum+1;
                                                                                                      }
                                                                                                      if(bValue2)
                                                                                                      {
                                                                                                      sum=sum+2;
                                                                                                      }
                                                                                                      if(bValue3)
                                                                                                      {
                                                                                                      sum=sum+4;
                                                                                                      }
                                                                                                      if(bValue4)
                                                                                                      {
                                                                                                      sum=sum+8;
                                                                                                      }


                                                                                                      Check sum against the conditions you want and that's it.
                                                                                                      This way you can add easily more conditions in the future keeping it quite straightforward to read.






                                                                                                      share|improve this answer























                                                                                                        up vote
                                                                                                        0
                                                                                                        down vote










                                                                                                        up vote
                                                                                                        0
                                                                                                        down vote









                                                                                                        My 2 cents: declare a variable sum (integer) so that



                                                                                                        if(bValue1)
                                                                                                        {
                                                                                                        sum=sum+1;
                                                                                                        }
                                                                                                        if(bValue2)
                                                                                                        {
                                                                                                        sum=sum+2;
                                                                                                        }
                                                                                                        if(bValue3)
                                                                                                        {
                                                                                                        sum=sum+4;
                                                                                                        }
                                                                                                        if(bValue4)
                                                                                                        {
                                                                                                        sum=sum+8;
                                                                                                        }


                                                                                                        Check sum against the conditions you want and that's it.
                                                                                                        This way you can add easily more conditions in the future keeping it quite straightforward to read.






                                                                                                        share|improve this answer












                                                                                                        My 2 cents: declare a variable sum (integer) so that



                                                                                                        if(bValue1)
                                                                                                        {
                                                                                                        sum=sum+1;
                                                                                                        }
                                                                                                        if(bValue2)
                                                                                                        {
                                                                                                        sum=sum+2;
                                                                                                        }
                                                                                                        if(bValue3)
                                                                                                        {
                                                                                                        sum=sum+4;
                                                                                                        }
                                                                                                        if(bValue4)
                                                                                                        {
                                                                                                        sum=sum+8;
                                                                                                        }


                                                                                                        Check sum against the conditions you want and that's it.
                                                                                                        This way you can add easily more conditions in the future keeping it quite straightforward to read.







                                                                                                        share|improve this answer












                                                                                                        share|improve this answer



                                                                                                        share|improve this answer










                                                                                                        answered Dec 6 at 16:21









                                                                                                        SCdev

                                                                                                        168




                                                                                                        168






















                                                                                                            up vote
                                                                                                            0
                                                                                                            down vote













                                                                                                            Several correct answers have been given to this question, but I would take a different view: if the code looks too complicated, something isn't quite right. The code will be difficult to debug and more likely to be "one-use-only".



                                                                                                            In real life, when we find a situation like this:



                                                                                                                     Scenario 1 | Scenario 2 | Scenario 3
                                                                                                            bValue1: true | true | true
                                                                                                            bValue2: true | true | false
                                                                                                            bValue3: true | true | false
                                                                                                            bValue4: true | false | false


                                                                                                            When four states are connected by such a precise pattern, we are dealing with the configuration of some "entity" in our model.



                                                                                                            An extreme metaphor is how we would describe a "human beings" in a model, if we were not aware of their existence as unitary entities with components connected into specific degrees of freedom: we would have to describe independent states of of "torsoes", "arms", "legs" and "head" which would make it complicated to make sense of the system described. An immediate result would be unnaturally complicated boolean expressions.



                                                                                                            Obviously, the way to reduce complexity is abstraction and a tool of choice in c++ is the object paradigm.



                                                                                                            So the question is: why is there such a pattern? What is this and what does it represent?



                                                                                                            Since we don't know the answer, we can fall back on a mathematical abstraction: the array: we have three scenarios, each of which is now an array.



                                                                                                                            0   1   2   3
                                                                                                            Scenario 1: T T T T
                                                                                                            Scenario 2: T T T F
                                                                                                            Scenario 3: T F F F


                                                                                                            At which point you have your initial configuration. as an array. E.g. std::array has an equality operator:



                                                                                                            At which point your syntax becomes:



                                                                                                            if( myarray == scenario1 ) {
                                                                                                            // arrays contents are the same

                                                                                                            }
                                                                                                            else if ( myarray == scenario2 ) {
                                                                                                            // arrays contents are the same

                                                                                                            }

                                                                                                            else if ( myarray == scenario3 ) {
                                                                                                            // arrays contents are the same

                                                                                                            }
                                                                                                            else {
                                                                                                            // not the same

                                                                                                            }


                                                                                                            Just as the answer by Gian Paolo, it short, clear and easily verifiable/debuggable. In this case, we have delegated the details of the boolean expressions to the compiler.






                                                                                                            share|improve this answer



























                                                                                                              up vote
                                                                                                              0
                                                                                                              down vote













                                                                                                              Several correct answers have been given to this question, but I would take a different view: if the code looks too complicated, something isn't quite right. The code will be difficult to debug and more likely to be "one-use-only".



                                                                                                              In real life, when we find a situation like this:



                                                                                                                       Scenario 1 | Scenario 2 | Scenario 3
                                                                                                              bValue1: true | true | true
                                                                                                              bValue2: true | true | false
                                                                                                              bValue3: true | true | false
                                                                                                              bValue4: true | false | false


                                                                                                              When four states are connected by such a precise pattern, we are dealing with the configuration of some "entity" in our model.



                                                                                                              An extreme metaphor is how we would describe a "human beings" in a model, if we were not aware of their existence as unitary entities with components connected into specific degrees of freedom: we would have to describe independent states of of "torsoes", "arms", "legs" and "head" which would make it complicated to make sense of the system described. An immediate result would be unnaturally complicated boolean expressions.



                                                                                                              Obviously, the way to reduce complexity is abstraction and a tool of choice in c++ is the object paradigm.



                                                                                                              So the question is: why is there such a pattern? What is this and what does it represent?



                                                                                                              Since we don't know the answer, we can fall back on a mathematical abstraction: the array: we have three scenarios, each of which is now an array.



                                                                                                                              0   1   2   3
                                                                                                              Scenario 1: T T T T
                                                                                                              Scenario 2: T T T F
                                                                                                              Scenario 3: T F F F


                                                                                                              At which point you have your initial configuration. as an array. E.g. std::array has an equality operator:



                                                                                                              At which point your syntax becomes:



                                                                                                              if( myarray == scenario1 ) {
                                                                                                              // arrays contents are the same

                                                                                                              }
                                                                                                              else if ( myarray == scenario2 ) {
                                                                                                              // arrays contents are the same

                                                                                                              }

                                                                                                              else if ( myarray == scenario3 ) {
                                                                                                              // arrays contents are the same

                                                                                                              }
                                                                                                              else {
                                                                                                              // not the same

                                                                                                              }


                                                                                                              Just as the answer by Gian Paolo, it short, clear and easily verifiable/debuggable. In this case, we have delegated the details of the boolean expressions to the compiler.






                                                                                                              share|improve this answer

























                                                                                                                up vote
                                                                                                                0
                                                                                                                down vote










                                                                                                                up vote
                                                                                                                0
                                                                                                                down vote









                                                                                                                Several correct answers have been given to this question, but I would take a different view: if the code looks too complicated, something isn't quite right. The code will be difficult to debug and more likely to be "one-use-only".



                                                                                                                In real life, when we find a situation like this:



                                                                                                                         Scenario 1 | Scenario 2 | Scenario 3
                                                                                                                bValue1: true | true | true
                                                                                                                bValue2: true | true | false
                                                                                                                bValue3: true | true | false
                                                                                                                bValue4: true | false | false


                                                                                                                When four states are connected by such a precise pattern, we are dealing with the configuration of some "entity" in our model.



                                                                                                                An extreme metaphor is how we would describe a "human beings" in a model, if we were not aware of their existence as unitary entities with components connected into specific degrees of freedom: we would have to describe independent states of of "torsoes", "arms", "legs" and "head" which would make it complicated to make sense of the system described. An immediate result would be unnaturally complicated boolean expressions.



                                                                                                                Obviously, the way to reduce complexity is abstraction and a tool of choice in c++ is the object paradigm.



                                                                                                                So the question is: why is there such a pattern? What is this and what does it represent?



                                                                                                                Since we don't know the answer, we can fall back on a mathematical abstraction: the array: we have three scenarios, each of which is now an array.



                                                                                                                                0   1   2   3
                                                                                                                Scenario 1: T T T T
                                                                                                                Scenario 2: T T T F
                                                                                                                Scenario 3: T F F F


                                                                                                                At which point you have your initial configuration. as an array. E.g. std::array has an equality operator:



                                                                                                                At which point your syntax becomes:



                                                                                                                if( myarray == scenario1 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }
                                                                                                                else if ( myarray == scenario2 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }

                                                                                                                else if ( myarray == scenario3 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }
                                                                                                                else {
                                                                                                                // not the same

                                                                                                                }


                                                                                                                Just as the answer by Gian Paolo, it short, clear and easily verifiable/debuggable. In this case, we have delegated the details of the boolean expressions to the compiler.






                                                                                                                share|improve this answer














                                                                                                                Several correct answers have been given to this question, but I would take a different view: if the code looks too complicated, something isn't quite right. The code will be difficult to debug and more likely to be "one-use-only".



                                                                                                                In real life, when we find a situation like this:



                                                                                                                         Scenario 1 | Scenario 2 | Scenario 3
                                                                                                                bValue1: true | true | true
                                                                                                                bValue2: true | true | false
                                                                                                                bValue3: true | true | false
                                                                                                                bValue4: true | false | false


                                                                                                                When four states are connected by such a precise pattern, we are dealing with the configuration of some "entity" in our model.



                                                                                                                An extreme metaphor is how we would describe a "human beings" in a model, if we were not aware of their existence as unitary entities with components connected into specific degrees of freedom: we would have to describe independent states of of "torsoes", "arms", "legs" and "head" which would make it complicated to make sense of the system described. An immediate result would be unnaturally complicated boolean expressions.



                                                                                                                Obviously, the way to reduce complexity is abstraction and a tool of choice in c++ is the object paradigm.



                                                                                                                So the question is: why is there such a pattern? What is this and what does it represent?



                                                                                                                Since we don't know the answer, we can fall back on a mathematical abstraction: the array: we have three scenarios, each of which is now an array.



                                                                                                                                0   1   2   3
                                                                                                                Scenario 1: T T T T
                                                                                                                Scenario 2: T T T F
                                                                                                                Scenario 3: T F F F


                                                                                                                At which point you have your initial configuration. as an array. E.g. std::array has an equality operator:



                                                                                                                At which point your syntax becomes:



                                                                                                                if( myarray == scenario1 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }
                                                                                                                else if ( myarray == scenario2 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }

                                                                                                                else if ( myarray == scenario3 ) {
                                                                                                                // arrays contents are the same

                                                                                                                }
                                                                                                                else {
                                                                                                                // not the same

                                                                                                                }


                                                                                                                Just as the answer by Gian Paolo, it short, clear and easily verifiable/debuggable. In this case, we have delegated the details of the boolean expressions to the compiler.







                                                                                                                share|improve this answer














                                                                                                                share|improve this answer



                                                                                                                share|improve this answer








                                                                                                                edited Dec 7 at 6:43

























                                                                                                                answered Dec 7 at 6:32









                                                                                                                fralau

                                                                                                                647617




                                                                                                                647617






















                                                                                                                    up vote
                                                                                                                    0
                                                                                                                    down vote













                                                                                                                    The accepted answer is fine when you've only got 3 cases, and where the logic for each is simple.



                                                                                                                    But if the logic for each case were more complicated, or there are many more cases, a far better option is to use the chain-of-responsibility design pattern.



                                                                                                                    You create a BaseValidator which contains a reference to a BaseValidator and a method to validate and a method to call the validation on the referenced validator.



                                                                                                                    class BaseValidator {
                                                                                                                    BaseValidator* nextValidator;

                                                                                                                    public:
                                                                                                                    BaseValidator() {
                                                                                                                    nextValidator = 0;
                                                                                                                    }

                                                                                                                    void link(BaseValidator validator) {
                                                                                                                    if (nextValidator) {
                                                                                                                    nextValidator->link(validator);
                                                                                                                    } else {
                                                                                                                    nextValidator = validator;
                                                                                                                    }
                                                                                                                    }

                                                                                                                    bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                    if (nextValidator) {
                                                                                                                    return nextValidator->validate(v1, v2, v3, v4);
                                                                                                                    }

                                                                                                                    return false;
                                                                                                                    }

                                                                                                                    virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                    return false;
                                                                                                                    }
                                                                                                                    }


                                                                                                                    Then you create a number of subclasses which inherit from the BaseValidator, overriding the validate method with the logic necessary for each validator.



                                                                                                                    class Validator1: public BaseValidator {
                                                                                                                    public:
                                                                                                                    bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                    if (v1 && v2 && v3 && v4) {
                                                                                                                    return true;
                                                                                                                    }

                                                                                                                    return nextValidator->callLinkedValidator(v1, v2, v3, v4);
                                                                                                                    }
                                                                                                                    }


                                                                                                                    Then using it is simple, instantiate each of your validators, and set each of them to be the root of the others:



                                                                                                                    Validator1 firstValidator = new Validator1();
                                                                                                                    Validator2 secondValidator = new Validator2();
                                                                                                                    Validator3 thirdValidator = new Validator3();
                                                                                                                    firstValidator.link(secondValidator);
                                                                                                                    firstValidator.link(thirdValidator);
                                                                                                                    if (firstValidator.validate(value1, value2, value3, value4)) { ... }


                                                                                                                    In essence, each validation case has its own class which is responsible for (a) determining if the validation matches that case, and (b) sending the validation to someone else in the chain if it is not.



                                                                                                                    Please note that I am not familiar with C++. I've tried to match the syntax from some examples I found online, but if this does not work, treat it more like pseudocode. I also have a complete working Python example below that can be used as a basis if preferred.



                                                                                                                    class BaseValidator:
                                                                                                                    def __init__(self):
                                                                                                                    self.nextValidator = 0

                                                                                                                    def link(self, validator):
                                                                                                                    if (self.nextValidator):
                                                                                                                    self.nextValidator.link(validator)
                                                                                                                    else:
                                                                                                                    self.nextValidator = validator

                                                                                                                    def callLinkedValidator(self, v1, v2, v3, v4):
                                                                                                                    if (self.nextValidator):
                                                                                                                    return self.nextValidator.validate(v1, v2, v3, v4)

                                                                                                                    return False

                                                                                                                    def validate(self, v1, v2, v3, v4):
                                                                                                                    return False

                                                                                                                    class Validator1(BaseValidator):
                                                                                                                    def validate(self, v1, v2, v3, v4):
                                                                                                                    if (v1 and v2 and v3 and v4):
                                                                                                                    return True
                                                                                                                    return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                    class Validator2(BaseValidator):
                                                                                                                    def validate(self, v1, v2, v3, v4):
                                                                                                                    if (v1 and v2 and v3 and not v4):
                                                                                                                    return True
                                                                                                                    return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                    class Validator3(BaseValidator):
                                                                                                                    def validate(self, v1, v2, v3, v4):
                                                                                                                    if (v1 and not v2 and not v3 and not v4):
                                                                                                                    return True
                                                                                                                    return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                    firstValidator = Validator1()
                                                                                                                    secondValidator = Validator2()
                                                                                                                    thirdValidator = Validator3()
                                                                                                                    firstValidator.link(secondValidator)
                                                                                                                    firstValidator.link(thirdValidator)
                                                                                                                    print(firstValidator.validate(False, False, True, False))


                                                                                                                    Again, you may find this overkill for your specific example, but it creates much cleaner code if you end up with a far more complicated set of cases that need to be met.






                                                                                                                    share|improve this answer

























                                                                                                                      up vote
                                                                                                                      0
                                                                                                                      down vote













                                                                                                                      The accepted answer is fine when you've only got 3 cases, and where the logic for each is simple.



                                                                                                                      But if the logic for each case were more complicated, or there are many more cases, a far better option is to use the chain-of-responsibility design pattern.



                                                                                                                      You create a BaseValidator which contains a reference to a BaseValidator and a method to validate and a method to call the validation on the referenced validator.



                                                                                                                      class BaseValidator {
                                                                                                                      BaseValidator* nextValidator;

                                                                                                                      public:
                                                                                                                      BaseValidator() {
                                                                                                                      nextValidator = 0;
                                                                                                                      }

                                                                                                                      void link(BaseValidator validator) {
                                                                                                                      if (nextValidator) {
                                                                                                                      nextValidator->link(validator);
                                                                                                                      } else {
                                                                                                                      nextValidator = validator;
                                                                                                                      }
                                                                                                                      }

                                                                                                                      bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                      if (nextValidator) {
                                                                                                                      return nextValidator->validate(v1, v2, v3, v4);
                                                                                                                      }

                                                                                                                      return false;
                                                                                                                      }

                                                                                                                      virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                      return false;
                                                                                                                      }
                                                                                                                      }


                                                                                                                      Then you create a number of subclasses which inherit from the BaseValidator, overriding the validate method with the logic necessary for each validator.



                                                                                                                      class Validator1: public BaseValidator {
                                                                                                                      public:
                                                                                                                      bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                      if (v1 && v2 && v3 && v4) {
                                                                                                                      return true;
                                                                                                                      }

                                                                                                                      return nextValidator->callLinkedValidator(v1, v2, v3, v4);
                                                                                                                      }
                                                                                                                      }


                                                                                                                      Then using it is simple, instantiate each of your validators, and set each of them to be the root of the others:



                                                                                                                      Validator1 firstValidator = new Validator1();
                                                                                                                      Validator2 secondValidator = new Validator2();
                                                                                                                      Validator3 thirdValidator = new Validator3();
                                                                                                                      firstValidator.link(secondValidator);
                                                                                                                      firstValidator.link(thirdValidator);
                                                                                                                      if (firstValidator.validate(value1, value2, value3, value4)) { ... }


                                                                                                                      In essence, each validation case has its own class which is responsible for (a) determining if the validation matches that case, and (b) sending the validation to someone else in the chain if it is not.



                                                                                                                      Please note that I am not familiar with C++. I've tried to match the syntax from some examples I found online, but if this does not work, treat it more like pseudocode. I also have a complete working Python example below that can be used as a basis if preferred.



                                                                                                                      class BaseValidator:
                                                                                                                      def __init__(self):
                                                                                                                      self.nextValidator = 0

                                                                                                                      def link(self, validator):
                                                                                                                      if (self.nextValidator):
                                                                                                                      self.nextValidator.link(validator)
                                                                                                                      else:
                                                                                                                      self.nextValidator = validator

                                                                                                                      def callLinkedValidator(self, v1, v2, v3, v4):
                                                                                                                      if (self.nextValidator):
                                                                                                                      return self.nextValidator.validate(v1, v2, v3, v4)

                                                                                                                      return False

                                                                                                                      def validate(self, v1, v2, v3, v4):
                                                                                                                      return False

                                                                                                                      class Validator1(BaseValidator):
                                                                                                                      def validate(self, v1, v2, v3, v4):
                                                                                                                      if (v1 and v2 and v3 and v4):
                                                                                                                      return True
                                                                                                                      return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                      class Validator2(BaseValidator):
                                                                                                                      def validate(self, v1, v2, v3, v4):
                                                                                                                      if (v1 and v2 and v3 and not v4):
                                                                                                                      return True
                                                                                                                      return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                      class Validator3(BaseValidator):
                                                                                                                      def validate(self, v1, v2, v3, v4):
                                                                                                                      if (v1 and not v2 and not v3 and not v4):
                                                                                                                      return True
                                                                                                                      return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                      firstValidator = Validator1()
                                                                                                                      secondValidator = Validator2()
                                                                                                                      thirdValidator = Validator3()
                                                                                                                      firstValidator.link(secondValidator)
                                                                                                                      firstValidator.link(thirdValidator)
                                                                                                                      print(firstValidator.validate(False, False, True, False))


                                                                                                                      Again, you may find this overkill for your specific example, but it creates much cleaner code if you end up with a far more complicated set of cases that need to be met.






                                                                                                                      share|improve this answer























                                                                                                                        up vote
                                                                                                                        0
                                                                                                                        down vote










                                                                                                                        up vote
                                                                                                                        0
                                                                                                                        down vote









                                                                                                                        The accepted answer is fine when you've only got 3 cases, and where the logic for each is simple.



                                                                                                                        But if the logic for each case were more complicated, or there are many more cases, a far better option is to use the chain-of-responsibility design pattern.



                                                                                                                        You create a BaseValidator which contains a reference to a BaseValidator and a method to validate and a method to call the validation on the referenced validator.



                                                                                                                        class BaseValidator {
                                                                                                                        BaseValidator* nextValidator;

                                                                                                                        public:
                                                                                                                        BaseValidator() {
                                                                                                                        nextValidator = 0;
                                                                                                                        }

                                                                                                                        void link(BaseValidator validator) {
                                                                                                                        if (nextValidator) {
                                                                                                                        nextValidator->link(validator);
                                                                                                                        } else {
                                                                                                                        nextValidator = validator;
                                                                                                                        }
                                                                                                                        }

                                                                                                                        bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        if (nextValidator) {
                                                                                                                        return nextValidator->validate(v1, v2, v3, v4);
                                                                                                                        }

                                                                                                                        return false;
                                                                                                                        }

                                                                                                                        virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        return false;
                                                                                                                        }
                                                                                                                        }


                                                                                                                        Then you create a number of subclasses which inherit from the BaseValidator, overriding the validate method with the logic necessary for each validator.



                                                                                                                        class Validator1: public BaseValidator {
                                                                                                                        public:
                                                                                                                        bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        if (v1 && v2 && v3 && v4) {
                                                                                                                        return true;
                                                                                                                        }

                                                                                                                        return nextValidator->callLinkedValidator(v1, v2, v3, v4);
                                                                                                                        }
                                                                                                                        }


                                                                                                                        Then using it is simple, instantiate each of your validators, and set each of them to be the root of the others:



                                                                                                                        Validator1 firstValidator = new Validator1();
                                                                                                                        Validator2 secondValidator = new Validator2();
                                                                                                                        Validator3 thirdValidator = new Validator3();
                                                                                                                        firstValidator.link(secondValidator);
                                                                                                                        firstValidator.link(thirdValidator);
                                                                                                                        if (firstValidator.validate(value1, value2, value3, value4)) { ... }


                                                                                                                        In essence, each validation case has its own class which is responsible for (a) determining if the validation matches that case, and (b) sending the validation to someone else in the chain if it is not.



                                                                                                                        Please note that I am not familiar with C++. I've tried to match the syntax from some examples I found online, but if this does not work, treat it more like pseudocode. I also have a complete working Python example below that can be used as a basis if preferred.



                                                                                                                        class BaseValidator:
                                                                                                                        def __init__(self):
                                                                                                                        self.nextValidator = 0

                                                                                                                        def link(self, validator):
                                                                                                                        if (self.nextValidator):
                                                                                                                        self.nextValidator.link(validator)
                                                                                                                        else:
                                                                                                                        self.nextValidator = validator

                                                                                                                        def callLinkedValidator(self, v1, v2, v3, v4):
                                                                                                                        if (self.nextValidator):
                                                                                                                        return self.nextValidator.validate(v1, v2, v3, v4)

                                                                                                                        return False

                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        return False

                                                                                                                        class Validator1(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and v2 and v3 and v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        class Validator2(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and v2 and v3 and not v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        class Validator3(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and not v2 and not v3 and not v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        firstValidator = Validator1()
                                                                                                                        secondValidator = Validator2()
                                                                                                                        thirdValidator = Validator3()
                                                                                                                        firstValidator.link(secondValidator)
                                                                                                                        firstValidator.link(thirdValidator)
                                                                                                                        print(firstValidator.validate(False, False, True, False))


                                                                                                                        Again, you may find this overkill for your specific example, but it creates much cleaner code if you end up with a far more complicated set of cases that need to be met.






                                                                                                                        share|improve this answer












                                                                                                                        The accepted answer is fine when you've only got 3 cases, and where the logic for each is simple.



                                                                                                                        But if the logic for each case were more complicated, or there are many more cases, a far better option is to use the chain-of-responsibility design pattern.



                                                                                                                        You create a BaseValidator which contains a reference to a BaseValidator and a method to validate and a method to call the validation on the referenced validator.



                                                                                                                        class BaseValidator {
                                                                                                                        BaseValidator* nextValidator;

                                                                                                                        public:
                                                                                                                        BaseValidator() {
                                                                                                                        nextValidator = 0;
                                                                                                                        }

                                                                                                                        void link(BaseValidator validator) {
                                                                                                                        if (nextValidator) {
                                                                                                                        nextValidator->link(validator);
                                                                                                                        } else {
                                                                                                                        nextValidator = validator;
                                                                                                                        }
                                                                                                                        }

                                                                                                                        bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        if (nextValidator) {
                                                                                                                        return nextValidator->validate(v1, v2, v3, v4);
                                                                                                                        }

                                                                                                                        return false;
                                                                                                                        }

                                                                                                                        virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        return false;
                                                                                                                        }
                                                                                                                        }


                                                                                                                        Then you create a number of subclasses which inherit from the BaseValidator, overriding the validate method with the logic necessary for each validator.



                                                                                                                        class Validator1: public BaseValidator {
                                                                                                                        public:
                                                                                                                        bool validate(bool v1, bool v2, bool v3, bool v4) {
                                                                                                                        if (v1 && v2 && v3 && v4) {
                                                                                                                        return true;
                                                                                                                        }

                                                                                                                        return nextValidator->callLinkedValidator(v1, v2, v3, v4);
                                                                                                                        }
                                                                                                                        }


                                                                                                                        Then using it is simple, instantiate each of your validators, and set each of them to be the root of the others:



                                                                                                                        Validator1 firstValidator = new Validator1();
                                                                                                                        Validator2 secondValidator = new Validator2();
                                                                                                                        Validator3 thirdValidator = new Validator3();
                                                                                                                        firstValidator.link(secondValidator);
                                                                                                                        firstValidator.link(thirdValidator);
                                                                                                                        if (firstValidator.validate(value1, value2, value3, value4)) { ... }


                                                                                                                        In essence, each validation case has its own class which is responsible for (a) determining if the validation matches that case, and (b) sending the validation to someone else in the chain if it is not.



                                                                                                                        Please note that I am not familiar with C++. I've tried to match the syntax from some examples I found online, but if this does not work, treat it more like pseudocode. I also have a complete working Python example below that can be used as a basis if preferred.



                                                                                                                        class BaseValidator:
                                                                                                                        def __init__(self):
                                                                                                                        self.nextValidator = 0

                                                                                                                        def link(self, validator):
                                                                                                                        if (self.nextValidator):
                                                                                                                        self.nextValidator.link(validator)
                                                                                                                        else:
                                                                                                                        self.nextValidator = validator

                                                                                                                        def callLinkedValidator(self, v1, v2, v3, v4):
                                                                                                                        if (self.nextValidator):
                                                                                                                        return self.nextValidator.validate(v1, v2, v3, v4)

                                                                                                                        return False

                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        return False

                                                                                                                        class Validator1(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and v2 and v3 and v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        class Validator2(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and v2 and v3 and not v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        class Validator3(BaseValidator):
                                                                                                                        def validate(self, v1, v2, v3, v4):
                                                                                                                        if (v1 and not v2 and not v3 and not v4):
                                                                                                                        return True
                                                                                                                        return self.callLinkedValidator(v1, v2, v3, v4)

                                                                                                                        firstValidator = Validator1()
                                                                                                                        secondValidator = Validator2()
                                                                                                                        thirdValidator = Validator3()
                                                                                                                        firstValidator.link(secondValidator)
                                                                                                                        firstValidator.link(thirdValidator)
                                                                                                                        print(firstValidator.validate(False, False, True, False))


                                                                                                                        Again, you may find this overkill for your specific example, but it creates much cleaner code if you end up with a far more complicated set of cases that need to be met.







                                                                                                                        share|improve this answer












                                                                                                                        share|improve this answer



                                                                                                                        share|improve this answer










                                                                                                                        answered Dec 7 at 8:08









                                                                                                                        Jim Cullen

                                                                                                                        85




                                                                                                                        85






















                                                                                                                            up vote
                                                                                                                            -2
                                                                                                                            down vote













                                                                                                                            A simple approach is finding the answer that you think are acceptable.



                                                                                                                            Yes = (boolean1 && boolean2 && boolean3 && boolean4) + + ...



                                                                                                                            Now if possible simplify the equation using boolean algebra.



                                                                                                                            like in this case, acceptable1 and 2 combine to (boolean1 && boolean2 && boolean3).



                                                                                                                            Hence the final answer is:



                                                                                                                            (boolean1 && boolean2 && boolean3) || 
                                                                                                                            ((boolean1 && !boolean2 && !boolean3 && !boolean4)





                                                                                                                            share|improve this answer



























                                                                                                                              up vote
                                                                                                                              -2
                                                                                                                              down vote













                                                                                                                              A simple approach is finding the answer that you think are acceptable.



                                                                                                                              Yes = (boolean1 && boolean2 && boolean3 && boolean4) + + ...



                                                                                                                              Now if possible simplify the equation using boolean algebra.



                                                                                                                              like in this case, acceptable1 and 2 combine to (boolean1 && boolean2 && boolean3).



                                                                                                                              Hence the final answer is:



                                                                                                                              (boolean1 && boolean2 && boolean3) || 
                                                                                                                              ((boolean1 && !boolean2 && !boolean3 && !boolean4)





                                                                                                                              share|improve this answer

























                                                                                                                                up vote
                                                                                                                                -2
                                                                                                                                down vote










                                                                                                                                up vote
                                                                                                                                -2
                                                                                                                                down vote









                                                                                                                                A simple approach is finding the answer that you think are acceptable.



                                                                                                                                Yes = (boolean1 && boolean2 && boolean3 && boolean4) + + ...



                                                                                                                                Now if possible simplify the equation using boolean algebra.



                                                                                                                                like in this case, acceptable1 and 2 combine to (boolean1 && boolean2 && boolean3).



                                                                                                                                Hence the final answer is:



                                                                                                                                (boolean1 && boolean2 && boolean3) || 
                                                                                                                                ((boolean1 && !boolean2 && !boolean3 && !boolean4)





                                                                                                                                share|improve this answer














                                                                                                                                A simple approach is finding the answer that you think are acceptable.



                                                                                                                                Yes = (boolean1 && boolean2 && boolean3 && boolean4) + + ...



                                                                                                                                Now if possible simplify the equation using boolean algebra.



                                                                                                                                like in this case, acceptable1 and 2 combine to (boolean1 && boolean2 && boolean3).



                                                                                                                                Hence the final answer is:



                                                                                                                                (boolean1 && boolean2 && boolean3) || 
                                                                                                                                ((boolean1 && !boolean2 && !boolean3 && !boolean4)






                                                                                                                                share|improve this answer














                                                                                                                                share|improve this answer



                                                                                                                                share|improve this answer








                                                                                                                                edited Dec 5 at 5:33









                                                                                                                                Andrew Truckle

                                                                                                                                5,45142246




                                                                                                                                5,45142246










                                                                                                                                answered Dec 4 at 13:42









                                                                                                                                Rupesh

                                                                                                                                255




                                                                                                                                255






















                                                                                                                                    up vote
                                                                                                                                    -3
                                                                                                                                    down vote













                                                                                                                                    use bit field:



                                                                                                                                    unoin {
                                                                                                                                    struct {
                                                                                                                                    bool b1: 1;
                                                                                                                                    bool b2: 1;
                                                                                                                                    bool b3: 1;
                                                                                                                                    bool b4: 1;
                                                                                                                                    } b;
                                                                                                                                    int i;
                                                                                                                                    } u;

                                                                                                                                    // set:
                                                                                                                                    u.b.b1=true;
                                                                                                                                    ...

                                                                                                                                    // test
                                                                                                                                    if (u.i == 0x0f) {...}
                                                                                                                                    if (u.i == 0x0e) {...}
                                                                                                                                    if (u.i == 0x08) {...}


                                                                                                                                    PS:



                                                                                                                                    That's a big pity to CPPers'. But, UB is not my worry, check it at http://coliru.stacked-crooked.com/a/2b556abfc28574a1.






                                                                                                                                    share|improve this answer



















                                                                                                                                    • 2




                                                                                                                                      This causes UB due to accessing an inactive union field.
                                                                                                                                      – HolyBlackCat
                                                                                                                                      Dec 4 at 13:44










                                                                                                                                    • Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                      – Swift - Friday Pie
                                                                                                                                      Dec 4 at 13:45












                                                                                                                                    • I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                      – supercat
                                                                                                                                      Dec 4 at 19:35















                                                                                                                                    up vote
                                                                                                                                    -3
                                                                                                                                    down vote













                                                                                                                                    use bit field:



                                                                                                                                    unoin {
                                                                                                                                    struct {
                                                                                                                                    bool b1: 1;
                                                                                                                                    bool b2: 1;
                                                                                                                                    bool b3: 1;
                                                                                                                                    bool b4: 1;
                                                                                                                                    } b;
                                                                                                                                    int i;
                                                                                                                                    } u;

                                                                                                                                    // set:
                                                                                                                                    u.b.b1=true;
                                                                                                                                    ...

                                                                                                                                    // test
                                                                                                                                    if (u.i == 0x0f) {...}
                                                                                                                                    if (u.i == 0x0e) {...}
                                                                                                                                    if (u.i == 0x08) {...}


                                                                                                                                    PS:



                                                                                                                                    That's a big pity to CPPers'. But, UB is not my worry, check it at http://coliru.stacked-crooked.com/a/2b556abfc28574a1.






                                                                                                                                    share|improve this answer



















                                                                                                                                    • 2




                                                                                                                                      This causes UB due to accessing an inactive union field.
                                                                                                                                      – HolyBlackCat
                                                                                                                                      Dec 4 at 13:44










                                                                                                                                    • Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                      – Swift - Friday Pie
                                                                                                                                      Dec 4 at 13:45












                                                                                                                                    • I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                      – supercat
                                                                                                                                      Dec 4 at 19:35













                                                                                                                                    up vote
                                                                                                                                    -3
                                                                                                                                    down vote










                                                                                                                                    up vote
                                                                                                                                    -3
                                                                                                                                    down vote









                                                                                                                                    use bit field:



                                                                                                                                    unoin {
                                                                                                                                    struct {
                                                                                                                                    bool b1: 1;
                                                                                                                                    bool b2: 1;
                                                                                                                                    bool b3: 1;
                                                                                                                                    bool b4: 1;
                                                                                                                                    } b;
                                                                                                                                    int i;
                                                                                                                                    } u;

                                                                                                                                    // set:
                                                                                                                                    u.b.b1=true;
                                                                                                                                    ...

                                                                                                                                    // test
                                                                                                                                    if (u.i == 0x0f) {...}
                                                                                                                                    if (u.i == 0x0e) {...}
                                                                                                                                    if (u.i == 0x08) {...}


                                                                                                                                    PS:



                                                                                                                                    That's a big pity to CPPers'. But, UB is not my worry, check it at http://coliru.stacked-crooked.com/a/2b556abfc28574a1.






                                                                                                                                    share|improve this answer














                                                                                                                                    use bit field:



                                                                                                                                    unoin {
                                                                                                                                    struct {
                                                                                                                                    bool b1: 1;
                                                                                                                                    bool b2: 1;
                                                                                                                                    bool b3: 1;
                                                                                                                                    bool b4: 1;
                                                                                                                                    } b;
                                                                                                                                    int i;
                                                                                                                                    } u;

                                                                                                                                    // set:
                                                                                                                                    u.b.b1=true;
                                                                                                                                    ...

                                                                                                                                    // test
                                                                                                                                    if (u.i == 0x0f) {...}
                                                                                                                                    if (u.i == 0x0e) {...}
                                                                                                                                    if (u.i == 0x08) {...}


                                                                                                                                    PS:



                                                                                                                                    That's a big pity to CPPers'. But, UB is not my worry, check it at http://coliru.stacked-crooked.com/a/2b556abfc28574a1.







                                                                                                                                    share|improve this answer














                                                                                                                                    share|improve this answer



                                                                                                                                    share|improve this answer








                                                                                                                                    edited Dec 5 at 4:54

























                                                                                                                                    answered Dec 4 at 13:32









                                                                                                                                    hedzr

                                                                                                                                    9524




                                                                                                                                    9524








                                                                                                                                    • 2




                                                                                                                                      This causes UB due to accessing an inactive union field.
                                                                                                                                      – HolyBlackCat
                                                                                                                                      Dec 4 at 13:44










                                                                                                                                    • Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                      – Swift - Friday Pie
                                                                                                                                      Dec 4 at 13:45












                                                                                                                                    • I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                      – supercat
                                                                                                                                      Dec 4 at 19:35














                                                                                                                                    • 2




                                                                                                                                      This causes UB due to accessing an inactive union field.
                                                                                                                                      – HolyBlackCat
                                                                                                                                      Dec 4 at 13:44










                                                                                                                                    • Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                      – Swift - Friday Pie
                                                                                                                                      Dec 4 at 13:45












                                                                                                                                    • I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                      – supercat
                                                                                                                                      Dec 4 at 19:35








                                                                                                                                    2




                                                                                                                                    2




                                                                                                                                    This causes UB due to accessing an inactive union field.
                                                                                                                                    – HolyBlackCat
                                                                                                                                    Dec 4 at 13:44




                                                                                                                                    This causes UB due to accessing an inactive union field.
                                                                                                                                    – HolyBlackCat
                                                                                                                                    Dec 4 at 13:44












                                                                                                                                    Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                    – Swift - Friday Pie
                                                                                                                                    Dec 4 at 13:45






                                                                                                                                    Formally it's UB in C++, you can't set one member of union and read from another. Technically it might be better to implement templated getterssetters for bits of integral value.
                                                                                                                                    – Swift - Friday Pie
                                                                                                                                    Dec 4 at 13:45














                                                                                                                                    I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                    – supercat
                                                                                                                                    Dec 4 at 19:35




                                                                                                                                    I think the behavior would shift to Implementation-Defined if one were to convert the union's address to an unsigned char*, though I think simply using something like ((((flag4 <<1) | flag3) << 1) | flag2) << 1) | flag1 would probably be more efficient.
                                                                                                                                    – supercat
                                                                                                                                    Dec 4 at 19:35


















                                                                                                                                    draft saved

                                                                                                                                    draft discarded




















































                                                                                                                                    Thanks for contributing an answer to Stack Overflow!


                                                                                                                                    • Please be sure to answer the question. Provide details and share your research!

                                                                                                                                    But avoid



                                                                                                                                    • Asking for help, clarification, or responding to other answers.

                                                                                                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                                                                                                    To learn more, see our tips on writing great answers.





                                                                                                                                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                                                                                                    Please pay close attention to the following guidance:


                                                                                                                                    • Please be sure to answer the question. Provide details and share your research!

                                                                                                                                    But avoid



                                                                                                                                    • Asking for help, clarification, or responding to other answers.

                                                                                                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                                                                                                    To learn more, see our tips on writing great answers.




                                                                                                                                    draft saved


                                                                                                                                    draft discarded














                                                                                                                                    StackExchange.ready(
                                                                                                                                    function () {
                                                                                                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53591559%2fhow-to-improve-logic-to-check-whether-4-boolean-values-match-some-cases%23new-answer', 'question_page');
                                                                                                                                    }
                                                                                                                                    );

                                                                                                                                    Post as a guest















                                                                                                                                    Required, but never shown





















































                                                                                                                                    Required, but never shown














                                                                                                                                    Required, but never shown












                                                                                                                                    Required, but never shown







                                                                                                                                    Required, but never shown

































                                                                                                                                    Required, but never shown














                                                                                                                                    Required, but never shown












                                                                                                                                    Required, but never shown







                                                                                                                                    Required, but never shown







                                                                                                                                    Popular posts from this blog

                                                                                                                                    If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                                                                                                                                    Alcedinidae

                                                                                                                                    Can an atomic nucleus contain both particles and antiparticles? [duplicate]