What Is the Performance Implication of Converting to Bool in C++

What is the performance implication of converting to bool in C++?

I was puzzled by this behaviour, until I found this link:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633

Apparently, coming from the Microsoft Developer who "owns" this warning:

This warning is surprisingly
helpful, and found a bug in my code
just yesterday. I think Martin is
taking "performance warning" out of
context.

It's not about the generated code,
it's about whether or not the
programmer has signalled an intent to
change a value from int to bool
.
There is a penalty for that, and the
user has the choice to use "int"
instead of "bool" consistently (or
more likely vice versa) to avoid the
"boolifying" codegen. [...]

It is an old warning, and may have
outlived its purpose, but it's
behaving as designed here.

So it seems to me the warning is more about style and avoiding some mistakes than anything else.

Hope this will answer your question...

:-p

Why is there a performance warning on casting pointer to bool?

There's a discussion on Microsoft Connect about this (What is the performance implication of converting to bool in C++?). The example given to Microsoft is:

$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp
1 bool f1 (int i)
2 {
3 return i & 2;
4 }
5
6 bool f2 (int i)
7 {
8 const bool b = i & 2;
9 return b;
10 }
11
12 bool f3 (int i)
13 {
14 const bool b = 0 != (i & 2);
15 return b;
16 }
t.cpp
t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

And Microsoft's response (from the developer responsible for the warning) is:

This warning is surprisingly helpful, and found a bug in my code just yesterday. I think Martin is taking "performance warning" out of context.

It's not about the generated code, it's about whether or not the programmer has signalled an intent to change a value from int to bool. There is a penalty for that, and the user has the choice to use "int" instead of "bool" consistently (or more likely vice versa) to avoid the "boolifying" codegen. The warning is suppressed in the third case below because he's clearly signalled his intent to accept the int->bool transition.

It is an old warning, and may have outlived its purpose, but it's behaving as designed here

So basically the MS developer seems to be saying that if you want to 'cast' an int to bool you should more properly do it by using "return this->parentNode != 0" instead of an implicit or explicit cast.

Personally, I'd be interested to know more about what kind of bugs the warning uncovers. I'd think that this warning wouldn't have a whole lot of value.

Is !! a safe way to convert to bool in C++?

The argument of the ! operator and the first argument of the ternary operator are both implicitly converted to bool, so !! and ?: are IMO silly redundant decorations of the cast. I vote for

b = (t != 0);

No implicit conversions.

warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) in MFC(VC++)

The reason is that MFC's GetCheck doesn't return a bool:

The return value from a button control created with the BS_AUTOCHECKBOX, BS_AUTORADIOBUTTON, BS_AUTO3STATE, BS_CHECKBOX, BS_RADIOBUTTON, or BS_3STATE style is one of the following values:

- BST_UNCHECKED - Button state is unchecked.

- BST_CHECKED - Button state is checked.

- BST_INDETERMINATE - Button state is indeterminate (applies only if the button has the BS_3STATE or BS_AUTO3STATE style).

So you probably want

if (g_objConfigurationDetails.bAutoScan
!= (m_objScanNASBtn.GetCheck() == BST_CHECKED))

or

bool bNASBtnChecked = (m_objScanNASBtn.GetCheck() == BST_CHECKED);
if (g_objConfigurationDetails.bAutoScan != bNASBtnChecked)
{
g_objConfigurationDetails.bAutoScan = bNASBtnChecked;
}

Why doesn't comparison with bool convert to bool in C11?

Why doesn't comparison with bool convert to bool in C11?

_Bool is the lowest rank and equality operator == specifies that its _Bool operands are promoted to int. @StoryTeller


The rank of _Bool shall be less than the rank of all other standard integer types. C11 §6.3.1.1 1

(Equality operators) If both of the operands have arithmetic type, the usual arithmetic conversions are performed. §6.5.9 4

(usual arithmetic conversions) ... the integer promotions are performed on both operands §6.3.1.8 1

(integer promotions) If an int can represent all values of the original type ... the value is converted to an int ... §6.3.1.1 2


OP's code samples did not have a "comparison with bool".

// int compared to int: false since a == 1234 and that is not equal 1
if (a == true)

Instead could have had

// int compared to _Bool: false since a == 1234 and that is not equal to 0 or 1
if (a == b)

With int == _Bool, int == short, int == signed char, the same thing occurs. The lower rank operand is promoted to int.


1) Why wasn't true defined as (bool)1? This would allow the compiler to at least output a warning.

Why? a standard committee decision of years ago. Considering true as (int)1 rather than (_Bool)1 certainly would have impacted the existing code less when _Bool was introduced. (C99). This is consistent with other sub-int constants like SHRT_MAX which is usually an int, not short. In any case, in most contexts, a promotion to int/unsigned would occur anyway before further processing - like in this compare case.

Further (_Bool)1 is not needed to allow a compiler to provide a warning. A compiler can be made that supplies a warning using various analytic tools. As (_Bool)1, it would simplify things for a compiler to provide such a warning though.

2) Why is the integer in my example not converted into a bool such that a == true would evaluate to (bool)a == true which actually would be true?

As true is an (int)1, with a == true, both operands are int. _Bool does not apply here.

2) [OP Updated] Why is the integer in my example not converted into a bool such that a == true would evaluate to (bool)a == true which actually would be true?

The top of the answer addresses this: true in an int, so (bool)a is promoted to an int before the comparison as int is higher rank than _Bool.

What's the fastest way to interpret a bool string into a number in C?

Perhaps a simple hash and test?

#define Ttrue  (((uint_least64_t)'t') << 32 | ((uint_least64_t)'r') << 24 | ((uint_least64_t)'u') << 16 | ((uint_least64_t)'e') << 8 | 0)
#define T1 (((uint_least64_t)'1') << 8 | 0)
#define Tfalse (((uint_least64_t)'f') << 40 | ((uint_least64_t)'a') << 32 | ((uint_least64_t)'l') << 24 | ((uint_least64_t)'s') << 16 | ((uint_least64_t)'e') << 8 | 0)
#define T0 (((uint_least64_t)'0') << 8 | 0)

int Bool_str_decode(const char *Str) {
uint_least64_t sum = 0;
do {
sum <<= 8;
sum |= *(unsigned char*) Str;
} while (*Str++ && (sum & 0xFF0000000000) == 0); // loop to \0 or 6 characters

if (sum == T1 || sum == Ttrue) return 1;
if (sum == T0 || sum == Tfalse) return 0;
return -1;
}

explicit specifier doesn't seem to work when converting an object to bool

Contextual conversion is special; since C++11, explicit conversion functions will be considered in contextual conversions.

(emphasis mine)

(since C++11)

In the following contexts, the type bool is expected and the implicit conversion is performed if the declaration bool t(e); is well-formed (that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be contextually converted to bool.

  • the controlling expression of if, while, for;
  • the operands of the built-in logical operators !, && and ||;
  • the first operand of the conditional operator ?:;
  • the predicate in a static_assert declaration;
  • the expression in a noexcept specifier;
  • the expression in an explicit specifier; (since C++20)
  • the predicate of a contract attribute. (since C++20)

That means for if (b2), b2 will be converted to bool implicitly by B::operator bool() even it's declared as explicit.

When returning a boolean, why use !!

In your example, there's no difference between returning fBar and returning !!fBar.

In other cases, e.g. when a user-defined type such as BOOL (typedef-ed to be int) is used, the !! construct has the effect of coercing any non-zero value to true; i.e. !!fBar is equivalent to fBar ? true : false. This can make a difference if fBar can be 5 and you want to compare it against TRUE, which is defined to be (BOOL)1.



Related Topics



Leave a reply



Submit