Classes and class hierarchies
C.164
Avoid implicit conversion operators
Reason
Implicit conversions can be essential (e.g., double to int) but often cause surprises (e.g., String to C-style string).
Note
Prefer explicitly named conversions until a serious need is demonstrated. By "serious need" we mean a reason that is fundamental in the application domain (such as an integer to complex number conversion) and frequently needed. Do not introduce implicit conversions (through conversion operators or non-explicit constructors) just to gain a minor convenience.
Example
struct S1 {
string s;
// ...
operator char*() { return s.data(); } // BAD, likely to cause surprises
};
struct S2 {
string s;
// ...
explicit operator char*() { return s.data(); }
};
void f(S1 s1, S2 s2)
{
char* x1 = s1; // OK, but can cause surprises in many contexts
char* x2 = s2; // error (and that's usually a good thing)
char* x3 = static_cast<char*>(s2); // we can be explicit (on your head be it)
}
The surprising and potentially damaging implicit conversion can occur in arbitrarily hard-to spot contexts, e.g.,
S1 ff();
char* g()
{
return ff();
}
The string returned by ff() is destroyed before the returned pointer into it can be used.
Enforcement
Flag all non-explicit conversion operators.