Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to clarify wording #156

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
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
25 changes: 15 additions & 10 deletions _posts/2018-02-15-totw-142.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,23 @@ 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.
Implicitly calling a constructor isn’t such a good idea if the new object is a
different value than its inputs (that is, the input and output are not in an
“is” relationship, either by inheritance or conversion) or if the constructor
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.
connection that simply get converted into a request object. Rather, we use this
constructor to create a request that uses the inputs -- a “has” relationship.

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.

```c++
// A line is defined by two distinct points.
Expand Down Expand Up @@ -167,4 +172,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.