How do I idiomatically convert a BOOL to a bool?

10,240

There's no need for any explicit conversion:

BOOL x = some_value;
bool b = x;

The implicit conversion of a numeric type to bool yields false for a value of 0, and true for any non-zero value.

Incidentally, you've told us how <windows.h> defines FALSE and TRUE. How does it define BOOL? (From your comment, it's typedef int BOOL;)

But some compilers may warn about this implicit conversion, even though it's perfectly valid code. Compilers are free to warn about anything they like, including the ugly font you used to write your code. g++, for example, doesn't complain about the conversion, even with:

g++ -std=c++11 -pedantic -Wall -Wextra ...

But according to this online Visual C++ compiler, VC++ does produce a warning:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)

Even with a static_cast, it still produces the warning.

You can avoid the warning by using !!x or x ? true : false. But I'm not sure the cure is any better than the disease.

The simple and correct way to do this is simply to assign the value and rely on the implicit conversion to do the right thing (it will).

If you have an additional requirement to avoid compiler warnings, then this becomes more a question about Visual C++ rather than the C++ language. There may also be some way to inhibit certain warnings without changing the source -- though that risks losing those same warnings when they actually make sense. In a comment, Dieter Lücking suggests:

#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)

but that looks like it still requires modifying the source. Perhaps there's something equivalent that doesn't.

One more thing: since BOOL is really type int, this proposed solution:

bool c = (x == TRUE);

is not equivalent to the others. Any non-zero int is treated as true, but only the value 1 is equal to TRUE. The above will set c to false if x == 2, for example -- whereas if (x) would still treat it as a true condition. Never compare boolean values for equality to true or TRUE. (Comparing them to false or FALSE is safer, but still unnecessary; that's what the ! operator is for.)

This all assumes that if you have a value of type BOOL, you only care whether it's falsish or truthy (zero or non-zero). Unfortunately, this may not always be the case. As Ben Voight's answer points out, Microsoft's API includes at least one function, GetMessage, that returns a BOOL result that is not a simple Boolean value. In such a horrible case, conversion from BOOL to bool is not appropriate if you need to distinguish among the multiple non-zero values.

Ultimately, I blame Microsoft for defining a type BOOL for a language that already has a perfectly well behaved built-in bool type. Actually that's not quite fair; it's used in APIs that need to be accessible from both C and C++. Microsoft's definition of BOOL probably goes back to their C implementation, where it makes some sense -- at least prior to C99, which Microsoft still doesn't support. (I don't know whether Microsoft's C compiler support _Bool. Even if it does, _Bool has some semantic differences from int, and changing the definition of BOOL might break some code -- particularly code that uses GetMessage.)

Share:
10,240
fredoverflow
Author by

fredoverflow

Updated on July 26, 2022

Comments

  • fredoverflow
    fredoverflow almost 2 years

    The <windows.h> header comes with its own BOOL type. Peeking at the implementation, it seems FALSE is just a macro for 0, and TRUE is just a macro for 1, but I'm not sure this is specified.

    What is the idiomatic way to convert a BOOL to a bool? I can imagine lots of possible ways:

    bool a = static_cast<bool>(x);
    
    bool b = x ? true : false;
    
    bool c = (x == TRUE);
    
    bool d = (x != FALSE);
    
    bool e = !!x;
    
    // ...
    
  • fredoverflow
    fredoverflow over 10 years
    This gives me a compiler warning. Otherwise I wouldn't have asked :)
  • Keith Thompson
    Keith Thompson over 10 years
    @FredOverflow: What's the warning? (And why didn't you mention that, and quote the warning, in your original question?) Compilers can warn about anything they like; gcc, for example, doesn't warn about an implicit conversion fromint to bool. And please update your question to show that typedef.
  • fredoverflow
    fredoverflow over 10 years
    Sorry, I cannot reproduce the warning at home, because I don't have Visual Studio installed here. I'll get back to you tomorrow!
  • chris
    chris over 10 years
    @FredOverflow, There's an online MSVC11 and CTP compiler if it helps: rise4fun.com/vcpp
  • Admin
    Admin over 10 years
    @KeithThompson I guess: #pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)
  • Keith Thompson
    Keith Thompson over 10 years
    That's assuming you need to retain those values. If it's being used sanely, you should only care whether it's truthy or falsish.
  • Ben Voigt
    Ben Voigt over 10 years
    @Keith: That's true for many of the APIs, but the one I linked to returns values from three equivalence classes.
  • Ben Voigt
    Ben Voigt over 10 years
    Re: "goes back to their C implementation"... the interface is still C89-compatible, which is a necessary result of backward compatibility requirements. The implementation doesn't matter, return types are part of the interface.
  • Keith Thompson
    Keith Thompson over 10 years
    That's a stupid, stupid, stupid API. (Changing the return type from BOOL to int would solve that problem and make no difference to the API.)
  • Keith Thompson
    Keith Thompson over 10 years
    @BenVoigt: I'm still going to blame Microsoft, whether it's really their fault or not. 8-)}
  • chris
    chris over 10 years
    The static cast producing a warning is just...bad.
  • chris
    chris over 10 years
    It really is, but as Raymond Chen explained once upon a time, there can only be an error if you do something stupid while passing in the arguments. It won't return a value less than 0 unless it's your fault. Still, there might be others that use something similar to a tribool.
  • Ben Voigt
    Ben Voigt over 10 years
    @chris: I guess this is the explanation you're referring to?
  • chris
    chris over 10 years
    @BenVoigt, That's the one, thanks. I actually stopped putting in the > 0 after that.
  • IInspectable
    IInspectable over 10 years
    That day is now, sort of: VARIANT_BOOL can be assigned VARIANT_FALSE and VARIANT_TRUE with the latter being defined as (short)-1, in other words 0xFFFF. On Windows I would suggest always using bool d = (x != FALSE);. You cannot expect everyone on your team to know how to convert from VARIANT_BOOL to BOOL properly.
  • IInspectable
    IInspectable over 10 years
    Names that begin with an underscore in the global namespace are reserved.
  • avo
    avo over 10 years
    Not a problem for me. This macro is used only by my own code and get expanded by pre-processor, so compiler and namespaces know nothing about it. Anyway, one can use __bool.
  • IInspectable
    IInspectable over 10 years
    A name that contains a double underscore is reserved everywhere. This has nothing to do with your code either. The rules are there to prevent name clashes with the C++ implementation. You certainly don't want a standard library header include guard to conflict with code using it. A safe alternative would be: bool bool_(const BOOL b){return !!b;}
  • avo
    avo over 10 years
    I live and learn, but I still like the old name _bool :) Do you think I'm safe with the new version - edited?