Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e54141256 |
23
src/ch08.md
23
src/ch08.md
@@ -217,11 +217,10 @@ const Writer = struct {
|
||||
const gen = struct {
|
||||
pub fn writeAll(pointer: *anyopaque, data: []const u8) anyerror!void {
|
||||
const self: T = @ptrCast(@alignCast(pointer));
|
||||
return ptr_info.Pointer.child.writeAll(self, data);
|
||||
return ptr_info.pointer.child.writeAll(self, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return .{
|
||||
.ptr = ptr,
|
||||
.writeAllFn = gen.writeAll,
|
||||
@@ -289,18 +288,18 @@ union), которая полностью описывает тип. Далее
|
||||
возможности Zig по генерации исходного кода во время компиляции.
|
||||
|
||||
Последняя часть этого кода это вызов функции посредством
|
||||
`ptr_info.Pointer.child.writeAll(self, data)`. Встроенная функция
|
||||
`ptr_info.pointer.child.writeAll(self, data)`. Встроенная функция
|
||||
`@@typeInfo(T)` возвращает `std.builtin.Type`, а это, как уже было
|
||||
отмечено, маркированная объединение, которое описывает тот или иной тип.
|
||||
Оно может описывать 24 разновидности типов, как то целые числа,
|
||||
необязательные значения, структуры, указатели и т.д. Каждый тип имеет
|
||||
необязательные значения, структуры, указатели и т.д. Каждый тип имеет
|
||||
свои особенные свойства. Так, целые числа обладают "знаковостью"
|
||||
(`signedness`), в то время как другие типы такого свойства не имеют. Вот
|
||||
так выглядит `@typeInfo(*File)`:
|
||||
|
||||
```zig
|
||||
builtin.Type{
|
||||
.Pointer = builtin.Type.Pointer{
|
||||
.pointer = builtin.Type.Pointer{
|
||||
.address_space = builtin.AddressSpace.generic,
|
||||
.alignment = 4,
|
||||
.child = demo.File,
|
||||
@@ -308,14 +307,14 @@ builtin.Type{
|
||||
.is_const = false,
|
||||
.is_volatile = false,
|
||||
.sentinel = null,
|
||||
.size = builtin.Type.Pointer.Size.One
|
||||
.size = builtin.Type.Pointer.Size.one
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Поле `child` это фактический тип сущности, на которую показывает
|
||||
указатель. Когда мы вызываем `init`, передавая ей `*File`,
|
||||
`ptr_info.Pointer.child.writeAll(...)` транслируется в
|
||||
`ptr_info.pointer.child.writeAll(...)` транслируется в
|
||||
`File.writeAll(...)`, то есть получается именно то, что мы и хотели.
|
||||
|
||||
Если вы посмотрите на другие применения такой витиеватой схемы,
|
||||
@@ -323,8 +322,8 @@ builtin.Type{
|
||||
получения информации о типе:
|
||||
|
||||
```zig
|
||||
if (ptr_info != .Pointer) @compileError("ptr must be a pointer");
|
||||
if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single item pointer");
|
||||
if (ptr_info != .pointer) @compileError("ptr must be a pointer");
|
||||
if (ptr_info.pointer.size != .one) @compileError("ptr must be a single item pointer");
|
||||
```
|
||||
|
||||
Таким образом делаются дополнительные проверки во время компиляции,
|
||||
@@ -334,13 +333,13 @@ if (ptr_info.Pointer.size != .One) @compileError("ptr must be a single item poin
|
||||
Также вместо вызова функции посредством
|
||||
|
||||
```zig
|
||||
ptr_info.Pointer.child.writeAll(self, data);
|
||||
ptr_info.pointer.child.writeAll(self, data);
|
||||
```
|
||||
|
||||
можно встретить такое
|
||||
|
||||
```zig
|
||||
@call(.always_inline, ptr_info.Pointer.child.writeAll, .{self, data});
|
||||
@call(.always_inline, ptr_info.pointer.child.writeAll, .{self, data});
|
||||
```
|
||||
|
||||
Вызов функции напрямую (как мы это и делали) по сути ничем не отличается
|
||||
@@ -358,7 +357,7 @@ ptr_info.Pointer.child.writeAll(self, data);
|
||||
|
||||
## Использование маркированных объединений
|
||||
|
||||
В качестве более простой альтернативы описанным схемам для эмуляции
|
||||
В качестве более простой альтернативы описанным схемам для эмуляции
|
||||
интерфейсов можно применять маркированные объединения, вот полноценный
|
||||
рабочий пример:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user