Skip to content

Commit 152536a

Browse files
committed
Fix code snippets
1 parent f6e44fb commit 152536a

File tree

1 file changed

+49
-33
lines changed

1 file changed

+49
-33
lines changed

lectures/variant.md

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,43 +65,58 @@ Aha, I hear you say, we can create an interface class and store pointers to obje
6565

6666
Indeed, we can create a class, say `Saveable`, that has a single pure `virtual` function `Save`. We can then inherit from this class in our `PngImage` and `JpegImage` that override `Save` with their respective implementations:
6767

68+
<!--
69+
`CPP_SETUP_START`
70+
71+
struct Noncopyable {
72+
Noncopyable() = default;
73+
Noncopyable(const Noncopyable&) = delete;
74+
Noncopyable(Noncopyable&&) = delete;
75+
Noncopyable& operator=(const Noncopyable&) = delete;
76+
Noncopyable& operator=(Noncopyable&&) = delete;
77+
};
78+
79+
$PLACEHOLDER
80+
`CPP_SETUP_END`
81+
`CPP_COPY_SNIPPET` variant_images/main.cpp
82+
`CPP_RUN_CMD` CWD:variant_images c++ -std=c++17 main.cpp
83+
-->
6884
```cpp
6985
#include <iostream>
7086
#include <memory>
7187
#include <string>
7288
#include <vector>
7389

7490
// 💡 See lecture on inheritance for Noncopyable implementation.
75-
struct Saveable : public Noncopyable {
76-
virtual void Save(const std::string& file_name) const = 0;
77-
virtual ~Saveable() = default;
91+
struct Saveable {
92+
virtual void Save(const std::string& file_name) const = 0;
93+
virtual ~Saveable() = default;
7894
};
7995

8096
struct PngImage : public Saveable {
81-
void Save(const std::string& file_name) const override {
82-
std::cout << "Saving " << file_name << ".png\n";
83-
}
84-
// Some private image data would go here.
97+
void Save(const std::string& file_name) const override {
98+
std::cout << "Saving " << file_name << ".png\n";
99+
}
100+
// Some private image data would go here.
85101
};
86102

87103
struct JpegImage : public Saveable {
88-
void Save(const std::string& file_name) const override {
89-
std::cout << "Saving " << file_name << ".jpg\n";
90-
}
91-
// Some private image data would go here.
104+
void Save(const std::string& file_name) const override {
105+
std::cout << "Saving " << file_name << ".jpg\n";
106+
}
107+
// Some private image data would go here.
92108
};
93109

94110
void SaveImage(const Saveable& image, const std::string& file_name) {
95-
image.Save(file_name);
111+
image.Save(file_name);
96112
}
97113

98114
int main() {
99-
// A bunch of images that could be put here at runtime.
100-
const std::vector<std::unique_ptr<Saveable>> images {
101-
std::make_unique<PngImage>(),
102-
std::make_unique<JpegImage>()
103-
};
104-
for (const auto& image : images) SaveImage(*image, "output");
115+
// A bunch of images that could be put here at runtime.
116+
std::vector<std::unique_ptr<Saveable>> images;
117+
images.push_back(std::make_unique<PngImage>());
118+
images.push_back(std::make_unique<JpegImage>());
119+
for (const auto& image : images) SaveImage(*image, "output");
105120
}
106121
```
107122
@@ -119,28 +134,28 @@ This is where `std::variant` comes to the rescue. It allows us to keep using tem
119134
#include <vector>
120135
121136
struct PngImage {
122-
void Save(const std::string& file_name) const {
123-
std::cout << "Saving " << file_name << ".png\n";
124-
}
125-
// Some private image data would go here.
137+
void Save(const std::string& file_name) const {
138+
std::cout << "Saving " << file_name << ".png\n";
139+
}
140+
// Some private image data would go here.
126141
};
127142
128143
struct JpegImage {
129-
void Save(const std::string& file_name) const {
130-
std::cout << "Saving " << file_name << ".jpg\n";
131-
}
132-
// Some private image data would go here.
144+
void Save(const std::string& file_name) const {
145+
std::cout << "Saving " << file_name << ".jpg\n";
146+
}
147+
// Some private image data would go here.
133148
};
134149
135150
using Image = std::variant<PngImage, JpegImage>;
136151
137152
void SaveImage(const Image& image, const std::string& file_name) {
138-
std::visit([&](const auto& img) { img.Save(file_name); }, image);
153+
std::visit([&](const auto& img) { img.Save(file_name); }, image);
139154
}
140155
141156
int main() {
142-
const std::vector<Image> images = {PngImage{}, JpegImage{}};
143-
for (const auto& image : images) SaveImage(image, "output");
157+
const std::vector<Image> images = {PngImage{}, JpegImage{}};
158+
for (const auto& image : images) SaveImage(image, "output");
144159
}
145160
```
146161

@@ -163,7 +178,7 @@ int main() {
163178
std::variant<int, std::string> value{};
164179
// By default, variant stores a value of the first type.
165180
std::cout << "Integer: " << std::get<int>(value) << '\n';
166-
value = "Hello, variant!" // Value now holds a std::string.
181+
value = "Hello, variant!"; // Value now holds a string.
167182
std::cout << "String: " << std::get<std::string>(value) << '\n';
168183
value = 42; // Value holds an int.
169184
std::cout << "Integer: " << std::get<int>(value) << '\n';
@@ -191,10 +206,10 @@ But we already saw that there is this function `std::visit` that we can use to m
191206
#include <variant>
192207

193208
struct Printer {
194-
void operator(int value) const {
209+
void operator()(int value) const {
195210
std::cout << "Integer: " << value << '\n';
196211
}
197-
void operator(std::string value) const {
212+
void operator()(const std::string& value) const {
198213
std::cout << "String: " << value << '\n';
199214
}
200215
};
@@ -448,8 +463,9 @@ For this purpose there is a type `std::monostate` in the standard library. This
448463

449464
<!--
450465
`CPP_SETUP_START`
466+
#include <variant>
451467
using SomeType = int;
452-
using someOtherType = double;
468+
using SomeOtherType = double;
453469
$PLACEHOLDER
454470
`CPP_SETUP_END`
455471
`CPP_COPY_SNIPPET` variant_monostate/main.cpp

0 commit comments

Comments
 (0)