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.
((*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++.
that's why google code style allows only explicit constructors
OdpowiedzUsuńTrue, they banned a lot of crazy constructions allowed by the language.
OdpowiedzUsuńit's helpful that they stated why it's banned, usually in detail.
OdpowiedzUsuń