Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b6a357c
Fix C++ this. to this-> (compilation error)
jwiegley Feb 11, 2026
25f9d65
Fix uninitialized loop variable in C++ example (UB)
jwiegley Feb 11, 2026
698ea57
Fix twice() computing square instead of double
jwiegley Feb 11, 2026
bee11ae
Fix normalization math error in setters_and_getters example
jwiegley Feb 11, 2026
0c370cd
Fix Optional<Box<T>> to Option<Box<T>> in sentinel_values
jwiegley Feb 11, 2026
6557dac
Fix ErrorB copy-paste error showing ErrorA message
jwiegley Feb 11, 2026
40ae09d
Fix Rust snake_case violations in expected_errors examples
jwiegley Feb 11, 2026
fa7dac3
Fix Rust camelCase variable names to snake_case
jwiegley Feb 11, 2026
94492d1
Fix subject-verb agreement in abstract_classes.md
jwiegley Feb 11, 2026
ef1a3c6
Fix typos in templates.md
jwiegley Feb 11, 2026
9a63090
Fix typos and grammar in overloading.md
jwiegley Feb 11, 2026
c82466e
Fix typos in iterators.md
jwiegley Feb 11, 2026
76086e2
Fix 'beacause' typo in visitor.md
jwiegley Feb 11, 2026
35b1224
Fix grammar errors and TODO in rtti.md
jwiegley Feb 11, 2026
9276ce3
Fix typos in placement_new.md and rvo.md
jwiegley Feb 11, 2026
cc22444
Fix typos and missing article in private_constructors.md
jwiegley Feb 11, 2026
94aec27
Fix grammar and missing space in user-defined_conversions.md
jwiegley Feb 11, 2026
30384d5
Fix subject-verb agreement in sentinel_values.md
jwiegley Feb 11, 2026
49fe939
Fix grammar and clarify wording in promotions_and_conversions.md
jwiegley Feb 11, 2026
80ca769
Fix 'build in' to 'built-in' in build_systems.md
jwiegley Feb 11, 2026
4a9e1b4
Fix article 'a' to 'an' before 'encapsulated' in private_and_friends.md
jwiegley Feb 11, 2026
3b94a5a
Fix missing article and plural in inheritance_and_reuse.md
jwiegley Feb 11, 2026
4583786
Fix 'a methods' to 'a method' in setters_and_getters.md
jwiegley Feb 11, 2026
e53aee3
Fix grammar in object_identity.md
jwiegley Feb 11, 2026
1f67bca
Fix missing word in expected_errors.md
jwiegley Feb 11, 2026
34d8664
Remove empty link from Concurrency entry in SUMMARY.md
jwiegley Feb 11, 2026
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
2 changes: 1 addition & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
- [Rust and C++ interoperability (FFI)](./idioms/ffi.md)
- [NRVO and RVO](./idioms/rvo.md)
- [Placement new](./idioms/placement_new.md)
- [Concurrency (threads and async)]()
- Concurrency (threads and async)

# Patterns

Expand Down
2 changes: 1 addition & 1 deletion src/etc/build_systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repository for a project, while Rust has a central language-specific package
registry called [crates.io](https://crates.io/).

This difference is amplified by the fact that the Rust build tool, Cargo, has a
build in package manager that works with crates.io, private registries, local
built-in package manager that works with crates.io, private registries, local
packages, and vendored sources.

Cargo is documented in detail in the [Cargo
Expand Down
2 changes: 1 addition & 1 deletion src/idioms/data_modeling/abstract_classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ given by a user defined `Drop` implementation or not) required for the value.

## Vtables and Rust trait object types

C++ and Rust both requires some kind of indirection to perform dynamic dispatch
C++ and Rust both require some kind of indirection to perform dynamic dispatch
against an interface. In C++ this indirection takes the form of a pointer to the
abstract class (instead of the derived concrete class), making use of a vtable
to resolve the virtual method.
Expand Down
8 changes: 4 additions & 4 deletions src/idioms/data_modeling/inheritance_and_reuse.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ class Printer : public Device {
bool powered = false;
public:
void powerOn() override {
this.powered = true;
this->powered = true;
std::cout << "Printer is powered on." << std::endl;
}

void powerOff() override {
this.powered = false;
this->powered = false;
std::cout << "Printer is powered off." << std::endl;
}
};
Expand Down Expand Up @@ -100,7 +100,7 @@ dispatch](./concepts.md) (with [no vtable overhead in the
static dispatch
case](./abstract_classes.md#vtables-and-rust-trait-object-types)).

Rust traits differ from abstract classes in few more ways. For example,
Rust traits differ from abstract classes in a few more ways. For example,
Rust traits cannot define data members and cannot define private or protected
methods. This limits the effectiveness of using traits to implement the template
method pattern.
Expand All @@ -112,7 +112,7 @@ visible as methods on the type.
Traits can, however, inherit from each other, including multiple inheritance. As
in modern C++, inheritance hierarchies in Rust tend to be shallow. In situations
with complex multiple inheritance, however, the diamond problem cannot arise in
Rust because traits cannot override other traits implementations. Therefore, all
Rust because traits cannot override other trait implementations. Therefore, all
paths to a common parent trait resolve to the same implementation.

{{#quiz inheritance_and_reuse.toml}}
6 changes: 3 additions & 3 deletions src/idioms/data_modeling/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl<Label> DirectedGraph<Label> {
</div>

In the use case demonstrated in the above example, there are few practical
differences between using C++ template to define a class and using and Rust's
differences between using a C++ template to define a class and using Rust's
generics to define a struct. Whenever one would use a template that takes a
`typename` or `class` parameter in C++, one can instead take a type parameter in
Rust.
Expand Down Expand Up @@ -197,7 +197,7 @@ impl<Label> DirectedGraph<Label> {
where
Label: Ord,
{
// Matches the C++, but is not the idomatic
// Matches the C++, but is not the idiomatic
// implementation!
if self.node_labels.is_empty() {
None
Expand Down Expand Up @@ -390,7 +390,7 @@ because both are part of the type of the produced array.

## Rust's `Self` type

Within a Rust struct defintion, `impl` block, or `impl` trait block, there is a
Within a Rust struct definition, `impl` block, or `impl` trait block, there is a
`Self` type that is in scope. The `Self` type is the type of the class being
defined with all of the generic type parameters filled in. It can be useful to
refer to this type especially in cases where there are many parameters that
Expand Down
2 changes: 1 addition & 1 deletion src/idioms/encapsulation/private_and_friends.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class of `BinaryTree`.

In Rust, however, both types can be defined in the same module, and so have
access to each other's private fields and methods. The module as a whole
provides a collection of types, methods, and functions that together define a
provides a collection of types, methods, and functions that together define an
encapsulated concept.

<div class="comparison">
Expand Down
8 changes: 4 additions & 4 deletions src/idioms/encapsulation/private_constructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn main() {
let carol =
Person::new("Carol".to_string(), 20);
// Can match on the public fields, and then
// use .. to ignore the remaning ones.
// use .. to ignore the remaining ones.
let Person { name, age, .. } = carol;
}
```
Expand Down Expand Up @@ -146,15 +146,15 @@ mod shape {
use shape::*;

fn main() {
// Variant constructor is accesssible despite not being marked pub.
// Variant constructor is accessible despite not being marked pub.
let triangle = Shape::Triangle {
base: 1.0,
height: 2.0,
};

let circle = Shape::Circle { radius: 1.0 };

// Fields accessbile despite not being marked pub.
// Fields accessible despite not being marked pub.
match circle {
Shape::Triangle { base, height } => {
println!("Triangle: {}, {}", base, height);
Expand Down Expand Up @@ -363,7 +363,7 @@ pub enum Shape {

The attribute is more typically used to force clients of a library to include
the wildcard when matching on the struct fields, making it so that adding
additional fields to a struct is not breaking change (i.e., that it does not
additional fields to a struct is not a breaking change (i.e., that it does not
[require the increase of the major version component when using semantic
versioning](https://doc.rust-lang.org/cargo/reference/semver.html)).

Expand Down
4 changes: 2 additions & 2 deletions src/idioms/encapsulation/setters_and_getters.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ fn sqrt_approx_zero(x: f64) -> bool {

impl Normalized {
pub fn from_vec2(v: Vec2) -> Option<Self> {
if sqrt_approx_zero(v.x * v.x + v.y * v.x - 1.0) {
if sqrt_approx_zero(v.x * v.x + v.y * v.y - 1.0) {
Some(Self(v))
} else {
None
Expand All @@ -139,7 +139,7 @@ impl Normalized {

A significant limitation that arises from the way that getter methods interact
with the borrow checker is that it isn't possible to mutably borrow multiple
elements from an indexed structure like a vector using a methods like
elements from an indexed structure like a vector using a method like
`Vec::get_mut`.

The built-in indexed types have several methods for creating split views onto a
Expand Down
32 changes: 16 additions & 16 deletions src/idioms/exceptions/expected_errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ fn main() {
In C++, the only way to handle exceptions is `catch`. In Rust, all of the
features for dealing with [tagged
unions](../data_modeling/tagged_unions.md) can be used with `Result` and
`Option`. The most approach depends on the intention of the program.
`Option`. The best approach depends on the intention of the program.

The basic way of handling an error indicated by a `Result` in Rust is by using
`match`.
Expand Down Expand Up @@ -447,7 +447,7 @@ struct ErrorA : public std::exception {
void mightThrowA() {}

struct ErrorB : public std::exception {
const char *msg = "ErrorA was produced";
const char *msg = "ErrorB was produced";
const char *what() const noexcept override {
return msg;
}
Expand Down Expand Up @@ -480,7 +480,7 @@ impl Display for ErrorA {

impl Error for ErrorA {}

fn might_throw_A() -> Result<(), ErrorA> {
fn might_throw_a() -> Result<(), ErrorA> {
Ok(())
}

Expand All @@ -498,7 +498,7 @@ impl Display for ErrorB {

impl Error for ErrorB {}

fn might_throw_B() -> Result<(), ErrorB> {
fn might_throw_b() -> Result<(), ErrorB> {
Ok(())
}

Expand Down Expand Up @@ -537,8 +537,8 @@ impl From<ErrorB> for ErrorAOrB {

fn process() -> Result<(), ErrorAOrB> {
// the ? operator uses the From instance
might_throw_A()?;
might_throw_B()?;
might_throw_a()?;
might_throw_b()?;
Ok(())
}
```
Expand All @@ -565,7 +565,7 @@ struct ErrorA : public std::exception {
void mightThrowA() {}

struct ErrorB : public std::exception {
const char *msg = "ErrorA was produced";
const char *msg = "ErrorB was produced";
const char *what() const noexcept override {
return msg;
}
Expand All @@ -586,15 +586,15 @@ use thiserror::Error;
#[error("ErrorA was produced")]
struct ErrorA;

fn might_throw_A() -> Result<(), ErrorA> {
fn might_throw_a() -> Result<(), ErrorA> {
Ok(())
}

#[derive(Debug, Error)]
#[error("ErrorB was produced")]
struct ErrorB;

fn might_throw_B() -> Result<(), ErrorB> {
fn might_throw_b() -> Result<(), ErrorB> {
Ok(())
}

Expand All @@ -607,8 +607,8 @@ enum ErrorAOrB {
}

fn process() -> Result<(), ErrorAOrB> {
might_throw_A()?;
might_throw_B()?;
might_throw_a()?;
might_throw_b()?;
Ok(())
}
```
Expand Down Expand Up @@ -645,7 +645,7 @@ struct ErrorA : public std::exception {
void mightThrowA() {}

struct ErrorB : public std::exception {
const char *msg = "ErrorA was produced";
const char *msg = "ErrorB was produced";
const char *what() const noexcept override {
return msg;
}
Expand Down Expand Up @@ -676,21 +676,21 @@ use thiserror::Error;
#[error("ErrorA was produced")]
struct ErrorA;

fn might_throw_A() -> Result<(), ErrorA> {
fn might_throw_a() -> Result<(), ErrorA> {
Ok(())
}

#[derive(Debug, Error)]
#[error("ErrorB was produced")]
struct ErrorB;

fn might_throw_B() -> Result<(), ErrorB> {
fn might_throw_b() -> Result<(), ErrorB> {
Ok(())
}

fn process() -> anyhow::Result<()> {
might_throw_A()?;
might_throw_B()?;
might_throw_a()?;
might_throw_b()?;
Ok(())
}

Expand Down
8 changes: 4 additions & 4 deletions src/idioms/iterators.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Rust iterators resemble C++
[ranges](https://en.cppreference.com/w/cpp/ranges.html) in that they represent
iterable sequence and can be manipulated similarly to using
an iterable sequence and can be manipulated similarly to using
range views. Since C++ ranges are defined using iterators and ranges were only
introduced in C++20, this chapter compares Rust iterators with both C++
iterators and with C++ ranges.
Expand Down Expand Up @@ -222,15 +222,15 @@ fn main() {
println!("{}", x);
}

// since v was borrowed, not moved, it is still accessiable here.
// since v was borrowed, not moved, it is still accessible here.
println!("{:?}", v);

for x in &mut v {
// x: &mut String
x.push('!');
}

// since v was borrowed, not moved, it is still accessiable here.
// since v was borrowed, not moved, it is still accessible here.
// however, the content of v has been modified
println!("{:?}", v);

Expand Down Expand Up @@ -351,7 +351,7 @@ fn main() {
## Iterator invalidation

In C++, operations sometimes only invalidate some iterators on a value, such as
the `erase` method on `std::vector` only invaliding iterators to the erased
the `erase` method on `std::vector` only invalidating iterators to the erased
element and those after it, but not the ones before it.

In Rust, the fact that iterators borrow the whole iterated value means that no
Expand Down
4 changes: 2 additions & 2 deletions src/idioms/null/sentinel_values.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sentinel values

Sentinel values are in-band value that indicates a special situation, such as
Sentinel values are in-band values that indicate a special situation, such as
having reached the end of valid data in an iterator.

## `nullptr`
Expand Down Expand Up @@ -53,7 +53,7 @@ The `Box<T>` type has the same meaning as `std::unique_ptr<T>` in terms of being
a uniquely owned pointer to some `T` on the heap, but unlike `std::unique_ptr`,
it cannot be null. Rust's `Option<T>` (which is similar to `std::optional<T>` in
C++) can represent optional pointers when used in conjunction with `Box<T>`, as
in `Optional<Box<T>>`. In [those cases (and in some other
in `Option<Box<T>>`. In [those cases (and in some other
cases)](../data_modeling/template_specialization.md#niche-optimization) the
compiler optimizes the representation to be the same size as `Box<T>` by
leveraging the fact that `Box` cannot be null.
Expand Down
6 changes: 3 additions & 3 deletions src/idioms/object_identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ between specific instances of an object that otherwise have the same properties.
For example, representing a labeled graph where there may be distinct nodes that
have the same label.

In Rust, some of these cases are not applicable, and others cases are typically
handled by instead by implementing a synthetic notion of identity for the
In Rust, some of these cases are not applicable, and other cases are typically
handled instead by implementing a synthetic notion of identity for the
values.

## Overloading copy assignment and equality comparison operators
Expand Down Expand Up @@ -40,7 +40,7 @@ struct Person
Person& operator=(const Person& other) {
// compare object identity first
if (this != &other) {
this.name = other.name;
this->name = other.name;
// copy the other expensive-to-copy fields
}

Expand Down
8 changes: 4 additions & 4 deletions src/idioms/overloading.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ fn main() {
```

One exception to this is when the methods are all from the same generic trait
with with different type parameters for the implementations. In that case, if
with different type parameters for the implementations. In that case, if
the signature is sufficient to determine which implementation to use, the trait
does not need to be specified to resolve the method. This is common when using
the [`From` trait](https://doc.rust-lang.org/std/convert/trait.From.html).
Expand Down Expand Up @@ -149,10 +149,10 @@ fn main() {

## Overloaded operators

In C++ most operators can either be overloaded either with a free-standing
In C++ most operators can be overloaded either with a free-standing
function or by providing a method defining the operator on a class.

Rust provides operator via implementation of specific traits. Implementing a
Rust provides operators via implementation of specific traits. Implementing a
method of the same name as required by the trait will not make a type usable
with the operator if the trait is not implemented.

Expand Down Expand Up @@ -227,7 +227,7 @@ impl std::ops::Add<&Vec2> for &Vec2 {
}
}

// If Vec2 weren't so small, it might be desireable to re-use space in the below
// If Vec2 weren't so small, it might be desirable to re-use space in the below
// implementations, since they take ownership.

impl std::ops::Add<Vec2> for &Vec2 {
Expand Down
Loading