Skip to content

← Const Correctness and Class Design step 2 of 3

Medium Primitives

Make temperature construction explicit

A constructor without explicit can allow a value to be converted to the class type implicitly:

class Fahrenheit {
public:
    Fahrenheit(double degrees);
};

Fahrenheit freezing = 32.0;  // implicitly constructs a Fahrenheit

That can hide a missing units calculation. In the starter, this return converts a Celsius number directly into a Fahrenheit object:

Fahrenheit to_fahrenheit(Celsius c) {
    return c.degrees();
}

The classes are distinct types, but extracting a plain double loses the unit information. The compiler can construct Fahrenheit from that number without knowing whether it has been converted correctly.

Restrict implicit construction

Mark the constructor explicit:

explicit Fahrenheit(double degrees);

Direct construction still works:

Fahrenheit a(32.0);
Fahrenheit b{32.0};
auto c = Fahrenheit{32.0};

But Fahrenheit a = 32.0; and return c.degrees(); no longer use that constructor implicitly. This exposes the starter's return as something to fix. It does not check the formula: Fahrenheit{c.degrees()} would still compile and still give the wrong conversion in general.

Use explicit when an implicit conversion would obscure meaning. Constructors with default arguments can also be callable with one argument, and explicit can affect multi-argument constructors used with braced lists. The choice concerns the intended interface, not just the number of parameters.

Explicit conversion to bool

Conversion operators can also be explicit:

explicit operator bool() const;

This still supports boolean contexts such as if (handle), while (handle), !handle and built-in handle && ready, as well as an explicit cast such as static_cast<bool>(handle). It does not implicitly convert for bool ok = handle; or ordinary arithmetic through bool. That restriction lets a handle support presence checks without acting like a number.

Your task

Fahrenheit to_fahrenheit(Celsius c);

Add explicit to Fahrenheit's constructor, then implement the conversion:

F = C * 9.0 / 5.0 + 32.0

Construct and return a Fahrenheit containing the computed value. Leave Celsius, the accessors and report unchanged. With a standalone ratio, 9 / 5 is integer division and produces 1; use floating-point arithmetic.

Celsius Fahrenheit
0 32
100 212
-40 -40

The provided report function returns 1 when a converted temperature is strictly greater than alert_above, measured in Fahrenheit, and 0 otherwise. Equality does not trigger an alert. The harness also reports converted values multiplied by 100 and rounded to the nearest integer, with halfway cases rounded away from zero. This output encoding does not change the conversion's double return value inside the Fahrenheit object.

For inputs [0, 100] and threshold 100, the harness reports flags [0, 1] and encoded temperatures [3200, 21200]. Empty input produces two empty lists. Test inputs keep conversion and output rounding within representable ranges.