Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions _posts/2018-02-15-totw-142.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,26 @@ object, no confusion arises from this affordance.

## Constructors That Do More

Implicitly calling a constructor isn’t such a good idea if its output is a
different value than its input, or if it might have preconditions.

Consider a `Request` class with a constructor `Request(Server*, Connection*)`.
There’s no sense in which the value of the request object “is” the server and
connection — it’s just that we can create a request that uses them. There could
be many semantically different types that can be constructed from `{server,
connection}`, such as a `Response`. Such a constructor should be `explicit`, so
that we can’t pass `{server, connection}` to a function that accepts a `Request`
(or `Response`) parameter. In such cases marking the constructor as `explicit`
makes the code clearer for readers by requiring the target type to be named when
it’s instantiated and helps to avoids bugs caused by unintended conversions.
The constructor should be `explicit` when it may have preconditions or when
the new object is a different kind of thing than its inputs (that is,
when the inputs do not uniquely define the object but are used to build
a new thing that has additional semantic meaning or state beyond these
inputs).

Consider a `Request` class with a constructor `Request(Server*,
Connection*)`. The server and connection are not converted into a
request object. Rather, we use this constructor to create a new object
that uses the inputs and has an implied direction of information flow.
There could be many semantically different types that can be constructed
from `{server, connection}`, such as a `Response` going in the opposite
direction from a `Request`.

Such a constructor should be `explicit` so that we can’t pass
`{server, connection}` to a function that accepts a `Request` or
`Response` parameter. Marking the constructor as `explicit` makes the
code clearer for readers by requiring the target type (and thus the
intended direction) to be named when it’s instantiated. This
explicitness helps to avoids bugs caused by unintended conversions.

```c++
// A line is defined by two distinct points.
Expand Down Expand Up @@ -167,4 +175,4 @@ If the recommendations in this tip were applied, that constructor would be
`explicit`, because the value of a `std::vector<char>` is not two iterators
(rather, it’s a sequence of characters). As it is, `explicit` was omitted, and
this example code gives undefined behavior as the second iterator is not
reachable from the first.
reachable from the first.