Stop using bool in C++ for function parameters !

Introduction

This article deals with the use of bool in C++. Should we use it or not? That is the question we will try to answer here. However, this is more of an open discussion than a coding rule.

First of all, what is the bool type? A boolean variable is a variable that can be set to false or true.

Imagine you have a simple function to decide whether or not to buy an house, you may design it like this

bool shouldBuyHouse(bool hasSwimmingPool, bool hasEconomicLight);

Problems arrived!

Then, when you want to use it, you can do it like this:

if(shouldBuyHouse(false, true)){}

There is no problem here, however the reader may not understand at first glance if the false means no pools, or if it means no energy saving lights.

So, you will try to change the function call like this:

bool economicLight = true;
bool hasSwimmingPool = false;

if(shouldBuyHouse(economicLight, hasSwimmingPool)) {

}

Now you are happy, the reader knows exactly what bool means. Are you sure? A very thorough reader may notice that there is a reversal of the parameters.

How to solve the problem?

There is different ways to solve this type of problem. The first is to use a strong_type. There are many libraries that offer this kind of thing, however, a simple enum class can do the trick.

Not only will the reader know which argument corresponds to which parameter, but also, in the case of a parameter inversion, the compiler will not let the error pass

Let’s rewrite the function declaration:

enum class HouseWithSwimmingPool {No, Yes};
enum class HouseWithLights {Economical, Incandescent};

bool shouldBuyHouse(HouseWithSwimmingPool, HouseWithLights);

if(shouldBuyHouse(HouseWithSwimmingPool::Yes, HouseWithLights::Economical)) {

}

Conclusion

I would encourage people not to use the bool type for function parameters. What do you think? Do you use bool everywhere?

Thanks for reading !

Comments

16 responses to “Stop using bool in C++ for function parameters !”

  1. Zen Avatar
    Zen

    Awesome article!

  2. artcats Avatar

    Agreed! You should use bit fields for this kind of thing!

    1. Antoine MORRIER Avatar
      Antoine MORRIER

      Would you like to provide an example using bitfields ☺️?

  3. ctarsoaga Avatar
    ctarsoaga

    awful advice. This has nothing to do with enums or bools. Your problem is that you are using const literals instead of symbolic names.

    1. Antoine MORRIER Avatar
      Antoine MORRIER

      Hello !
      Thanks for comment ☺️
      Maybe I should have been less “rude” on the “don’t use bool…” Because as a developer you should not be dogmatic.

      That being said, your advice is the same as mine, without typing. So it is less safe

      1. kcris Avatar
        kcris

        Hi,
        the fact that the title makes it look as if the article deals with a bool specific problem is one thing.5

        The worse is that you are dealing with two problems, both real, both having nothing to do with bools.

        problem #1: a literal value does not convey semantics. If I use 3.14 are you sure it’s PI that I want or maybe some other value that might be 3.14? I case of booleans/true/false this is way more obvious.

        So if you just say
        const bool somethingWithAMeaning = true; //solves problem #1

        the name describes the intention. This is an issue even if you have a single variable. It has nothing to do with strong typing nor with problem #2.

        Problem #2: what happens if you have multiple variables of the same type being passed as params. There, yes, you can a different strong type for each one to solve it. If you ask me, that is NOT why I would choose a strong type (I would choose a strong type to make sure that everywhere in my program, not only inside a params list, I cannot pass the wrong type). And by the way, unless you want to go paranoid, you will not create a strong type for each param. That does not make sense. A type too has a meaning. It is not associated with a symbolic name, which is what I think is the main issue here.

        So no, I am not advising strong types for this use case. Nor enums.

        1. Antoine MORRIER Avatar
          Antoine MORRIER

          Hello,
          For the problem 1, I’d say that I agree with you. There is a codingrule we defined with my team mates that is : “No magic number!”
          So yes, in general, this is more than enough to do so.

          For the problem 2, I’d say I agree with you again, you, indeed, I would not create strong type(or enum class) only for parameters. As you said, I would use them in my whole code to be sure that there is no type mismatch during the use of my library or other. Maybe the idea I wanted to share was not what I intended to do.

          I agree too about the fact that it is not a problem related with bool, however, in the code base I have worked on, it is on the type bool that such issue appeared the most.
          But well, in the globality, I agree with you :).

    2. IF Avatar
      IF

      agree. It actually has nothing to do with bools.

  4. Al Avatar
    Al

    You have exactly the same problem with any repeated types, not just bool. E.g. a rendering function taking a clipping window (x,y) as int; or was that (rows, cols)? Or (y,x)?

    1. Antoine MORRIER Avatar
      Antoine MORRIER

      Hello, sorry for the late answer.
      Yes I totally agree, in this case, you may use also strong type, but for just “coordinates”, I would go with a structure and designated initializers instead of strong type ;).

  5. Al Avatar
    Al

    My last post doesn’t seem to have been published. Anyway, you have the same problem with any set of parameters of the same type. Was that clipping function (x,y), (y,x) or maybe (row, column)?

    Anyway, the bitfield solution is an acceptable idiom; shouldbuyhouse(SWIMMINGPOOL & ~LIGHTS), or a more complete idiom is described here: https://isocpp.org/wiki/faq/ctors#named-parameter-idiom

    1. Antoine MORRIER Avatar
      Antoine MORRIER

      Hello,
      I must accept each comment one by one, because I got too much comment “spam” recommanding porn web site or other things like that…

      Considering the bitfield, I think it is clearly a good way to use it, however, I’d go with a or instead of a and 😉

  6. Some One Avatar
    Some One

    Or use a language not retarded to the point of lacking named parameters.

    1. Antoine MORRIER Avatar
      Antoine MORRIER

      There is designated initializer that are close to what you are suggesting

      1. Some One Avatar
        Some One

        The thing is that when you’re forced to use such a cumbersome, verbose and unsightly (that also pollutes the type namespace) method to get named parameters, you simply don’t unless it’s absolutely needed.

        While in Common Lisp, Ada and more recently Nim, these are provided and quite used/useful. And CL has &allow-other-keys which should be hard to emulate in a statically typed language.

        People who never had them are simply too used to the jank to feel their lack. Actually, most people used them: program option flags ARE named parameters; try to imagine sh without them =(.

  7. Someone Avatar
    Someone

    The same reasoning can be made for int, float, or even MyStruct or so on. When you have a function expecting several parameters of the same type, or even of implicitly castable types, you end up with this issue.
    C++ parameters are based on their position, not their name.
    Using a different type for each parameters isn’t something easy and will for sure add overhead.

    See that:
    void f(float a, double b);

    float x,y;
    f(y,x);

    Same issue.

Leave a Reply