We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Const Correctness and Class Design step 2 of 3
The conversion nobody asked for
class Fahrenheit {
public:
Fahrenheit(double degrees);
};
That is not only a constructor. It is a standing instruction to the compiler:
any double may become a Fahrenheit, silently, wherever one is wanted.
Returning one, passing one, comparing one — the conversion is applied without
a cast, a warning, or a word in the source.
Which means a class written to make units unmixable does not:
Fahrenheit convert(Celsius c) {
return c.degrees(); // compiles. It is not a conversion, it is a relabel.
}
The whole point of having two types was to make that line impossible, and one missing keyword handed the compiler permission to write it for you.
explicit
explicit Fahrenheit(double degrees);
Now the type must be named at every construction: Fahrenheit(x) or
Fahrenheit{x}. The line above stops compiling, and the error appears at the
place where the mistake actually is.
Single-argument constructors are
explicitby default, as a habit. Drop it only when the conversion is genuinely something callers should be able to write without thinking — which in practice means when the two types are the same idea in two representations, likestd::stringfrom a string literal.
Note that “single-argument” includes constructors where the rest have
defaults, and that since C++11 explicit matters for multi-argument
constructors too, because a braced list can be implicitly converted.
The other half: conversion operators
operator bool() const; // every Handle is now also an int, a
// char, a comparison operand...
explicit operator bool() const; // usable in `if (h)`, and nowhere else
An implicit operator bool is the classic version of this bug, because
bool promotes to int and from there everything is arithmetic. explicit operator bool is special-cased by the language to still work in conditions,
so you lose nothing.
The gate checks this
google-explicit-constructor is enabled, so an implicit single-argument
constructor is a gate failure here, not just advice.
Your task
Fahrenheit to_fahrenheit(Celsius c);
Convert. F = C × 9/5 + 32.
Celsius is given and already correct — look at how it is declared. Fix
Fahrenheit to match, and then fix to_fahrenheit, which currently returns
a Celsius number wearing a Fahrenheit label and is only able to because of
the missing keyword.
report is given: it converts each reading and flags the ones above a
threshold. Do not change it.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.