DiscussionIf you're in the office and run out of paper, what do you do? Of course, you walk to your trusty photocopier and make several copies of a white sheet of paper. As silly as it sounds, this is often what implicit conversions do: unnecessarily go through the trouble of creating temporaries, just to perform some trivial operation on them and toss them away (see Item 40). A common example is string comparison: class String {// … String( const char* text ); // enables implicit conversion }; bool operator==( const String&, const String& ); // … somewhere in the code … if( someString == "Hello" ) {... } Having seen the definitions above, the compiler will compile the comparison as if you had written s == String("Hello"). This can be quite wasteful, considering that you don't need to copy the characters just to read them. The solution to this problem is simple: define overloads that avoid the conversion. For example: bool operator==( const String& lhs, const String& rhs ); // #1 bool operator==( const String& lhs, const char* rhs ); // #2 bool operator==( const char* lhs, const String& rhs ); // #3 That looks like a lot of code duplication, but in reality it is only "signature duplication" because all three typically use the same back-end function. You're unlikely to commit a premature optimization heresy (see Item 8) with such simple overloads, and it's de bon goût to provide them especially when designing a library when it's difficult to predict in advance what common types will be in performance-sensitive code. ![]() |