Symbian
Symbian OS Library

FAQ-0824 Why can't I find TBool operator!=(TTrue,volatile const TBool)? What is __BOOL_NO_TRUE_TRAP__?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Development
Created: 09/20/2002 Modified: 12/16/2002
Number: FAQ-0824
Platform: Not Applicable

Question:
My code fails to link because there is no implementation of an overloaded operator== function. This function is defined in e32std.h inside #if !defined(__BOOL_NO_TRUE_TRAP__), but I can't find the implementation anywhere. What's going on?

Answer:
The section of e32std.h is as follows:

    #if !defined(__BOOL_NO_TRUE_TRAP__)
    TBool operator==(TTrue,volatile const TBool);
    TBool operator==(volatile const TBool,TTrue);
    TBool operator!=(TTrue,volatile const TBool);
    TBool operator!=(volatile const TBool,TTrue);
    #endif

      This exists as a deliberate mechanism for getting the compiler to tell you if you make a classic coding mistake such as

      if (myTBool != theirTBool)
      {
      doSomething();
      }

      The TBool type is actually an integer rather than a true C++ boolean, and so any non-zero value means "true" and equality comparisons between the values don't give the same result as logical comparisons. The above code is correctly written as

      if ((myTBool && !theirTBool) || (theirTBool && !myTBool))
      {
      doSomething();
      }

      Here is the original reasoning behind the definitions of ETrue and EFalse, and the creation of the decoy operators.
      ------------------------
      In addition, we would like to trap the existing conditionals converting truth values into TBool. They would only serve to waste space as well as cycles.

      The proposed new definition is:

      typedef int TBool;

      enum TFalse {EFalse=FALSE};

      enum TTrue {ETrue=TRUE};

      Making EFalse and ETrue values of different types is the key to trapping illegal use, and does not make any difference otherwise.

      These definitions in themselves will cause the offending conditionals to fail to compile, but not comparisons involving ETrue. To trap those, we propose to exploit the overload resolution and ambiguity rules.

      Introducing an alternative comparison operator involving "similar conversions" results in an ambiguous call when a TBool and a TTrue are compared, as follows:

      #if !defined(__BOOL_NO_TRUE_TRAP__)

      TBool operator==(TTrue,volatile const TBool);

      TBool operator==(volatile const TBool,TTrue);

      TBool operator!=(TTrue,volatile const TBool);

      TBool operator!=(volatile const TBool,TTrue);

      #endif

      Note that there is no point in defining these operators, declaring them is sufficient. I find it useful not to use argument names in a case like this.

      The choice of volatile const TBool is motivated by the speculation that instances of this exact type would be thin on the ground, and that any TBool value would therefore require at least one--trivial--conversion to match the argument. The C++ ARM is a bit on the vague side as to the overload resolution rules. Introducing these operators causes the desired ambiguity using MSVC, but it might not do so using a different compiler. The __BOOL_NO_TRUE_TRAP__ macro serves to be able to turn the operators off selectively, in case a compiler chokes on them. Or even as a migration tool: defining it for selected compilation units would allow ETrue comparisons to be phased out over a period of time.

      ------------------------