I'm fond of C++ weirdness, really. This language is full of traps, and it shocks me once in a while.
Let's look at this piece of code, a part of a larger module:
void validate_date() {
// ...
boost::optional<unsigned> clock_hour;
boost::optional<unsigned> am_pm_clock;
// ... fill these fields
if (some sanity check failed) {
report_error("user has entered wrong time: %d %s",
*clock_hour
*am_pm_clock ? "AM" : "PM");
}
}
We would expect that in case of an error following line will be reported: "user has entered wrong time: 123 PM". Obvious. But please look closer at the code, do you see any mistake? There is one... dirty... hard to notice. I'll give you a minute.
So, the mistake is lack of comma between expressions
*clock_hour and
*am_pm_clock. However, the code is valid! It compiles! And it took me a little longer than a minute to understand what happened. Explanation is:
- *clock_hour evaluates to expression of type unsigned;
- then compiler sees * - a multiplication operator;
- so checks if multiplication of unsigned (on the left side) with boost::optional<unsigned> (on the right side) is possible;
- it is, because boost::optional<T> has conversion operator to type T.
We can rewrite the whole expression, now it should be clear:
((*clock_hour) * unsigned(am_pm_clock)) ? "AM" : "PM"
In result method is called with
a single parameter of type
cont char*.
It's bizarre, it's terrible. A language should help a programmer. In my opinion implicit conversions is the worst feature of C++.