Incompatibilities between safe bool idiom and expl

2019-06-18 04:53发布

问题:

I'm thinking of replacing all the instances of safe bool idiom by explicit operator bool in code which already uses C++11 features (so the fact that older compilers don't recognized explicit conversion operators will not matter), so I'd like to know if it can cause some subtle problems.

Thus, what are all the possible incompatibilities (even the most minute ones) that can be caused by switching from old and dull safe bool idiom to new and shiny explicit operator bool?

EDIT: I know that switching is a good idea anyway, for the latter is a language feature, well-understood by the compiler, so it'll work no worse than what's in fact just a hack. I simply want to know the possible differences.

回答1:

Probably the biggest difference, assuming your code is free of bugs (I know, not a safe assumption), will be that in some cases, you may want an implicit conversion to exactly bool. An explicit conversion function will not match.

struct S1
{
    operator S1*() { return 0; } /* I know, not the best possible type */
} s1;

struct S2
{
    explicit operator bool() { return false; }
} s2;

void f()
{
    bool b1 = s1; /* okay */
    bool b2 = s2; /* not okay */
}


回答2:

If you've used safe-bool conversion incorrectly in your code, only then explicit operator bool be incompatible, as it wouldn't allow you to do things incorrectly that easily. Otherwise, it should be just fine without any problem. In fact, even if there is problem, you should still switch to explicit operator bool, because if you do so, then you could identify the problem in the usage of the safe-bool conversion.

According to this article, some compilers emit inefficient instructions for safe-bool implementation using member function pointer,

When people started using this idiom, it was discovered that there was an efficiency penalty on some compilers — the member function pointer caused a compiler headache resulting in slower execution when the address was fetched. Although the difference is marginal, the current practice is typically to use a member data pointer instead of a member function pointer.