# Pointer to optional self in struct method

**URL:** <https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592>\
**Category:** Help\
**Tags:** language\
**Created:** [August 11, 2024, 4:31pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592 "2024-08-11T16:31:47Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 11, 2024, 4:31pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/1 "2024-08-11T16:31:47Z")

</div>

I was experimenting with some things and run into a problem.

```zig
const log = @import("std").debug.print;

const Thing: type = struct {

    data: u32,

    fn init(d: u32) Thing {
        return .{.data = d};
    }

    fn func(thing: *?Thing) void {
        //log("d = {}\n", .{thing.?.data});
        log("d = {}\n", .{thing.data});
    }
};

pub fn main() void {
    const t = Thing.init(11);
    t.func();
}

```

Compiler says:

```plaintext
$ zig build-exe test.zig 
test.zig:20:6: error: no field or member function named 'func' in 'test.Thing'
    t.func();
    ~^ ~~~~
test.zig:4:21: note: struct declared here
const Thing: type = struct {
                    ^ ~~~~~
test.zig:12:5: note: 'func' is not a member function
    fn func(thing: *?Thing) void {
    ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

```

I can not understand what is going on here. ☹

---

<div class="post-metadata">

**Author:** ![IntegratedQuantum](https://ziggit.dev/user_avatar/ziggit.dev/integratedquantum/32/782_2.png) [@IntegratedQuantum](https://ziggit.dev/u/IntegratedQuantum)\
**Post date:** [August 11, 2024, 4:36pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/2 "2024-08-11T16:36:45Z")

</div>

Shouldn’t it be `?*Thing`

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 11, 2024, 4:38pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/3 "2024-08-11T16:38:08Z")

</div>

No, I wanted pointer to optional, not an optional pointer.

---

<div class="post-metadata">

**Author:** ![LucasSantos91](https://ziggit.dev/user_avatar/ziggit.dev/lucassantos91/32/440_2.png) [@LucasSantos91](https://ziggit.dev/u/LucasSantos91)\
**Post date:** [August 11, 2024, 4:39pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/4 "2024-08-11T16:39:23Z")

</div>

The method syntactic sugar only works for `This`, `* This` and `*const This`. Anything other than that, you have to do normal function call.

---

<div class="post-metadata">

**Author:** ![dude\_the\_builder](https://ziggit.dev/user_avatar/ziggit.dev/dude_the_builder/32/557_2.png) [@dude\_the\_builder](https://ziggit.dev/u/dude_the_builder)\
**Post date:** [August 11, 2024, 4:59pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/5 "2024-08-11T16:59:42Z")

</div>

If this worked, what would the method call do if the `thing` argument points to `null`?

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 11, 2024, 5:11pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/6 "2024-08-11T17:11:24Z")

</div>

something like this I suppose:

```zig
const log = @import("std").debug.print;

const Thing: type = struct {

    data: u32,

    fn init(d: u32) Thing {
        return .{.data = d};
    }

    fn func(thing: *?Thing) void {
        const t: Thing = thing.* orelse { 
            log("oops\n", .{});
            return;
        };
        log("d = {}\n", .{t.data});
    }
};

pub fn main() void {
    var t: ?Thing = Thing.init(11);
    Thing.func(&t);
    t = null;
    Thing.func(&t);
}

```

now it’s working but it’s not exactly what I wanted.  
ok, nevermind.

---

<div class="post-metadata">

**Author:** ![IntegratedQuantum](https://ziggit.dev/user_avatar/ziggit.dev/integratedquantum/32/782_2.png) [@IntegratedQuantum](https://ziggit.dev/u/IntegratedQuantum)\
**Post date:** [August 11, 2024, 5:12pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/7 "2024-08-11T17:12:15Z")

</div>

Why do you need a pointer to optional anyways?

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 11, 2024, 5:20pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/8 "2024-08-11T17:20:06Z")

</div>

> [@IntegratedQuantum](#):
>
> Why do you need a pointer to optional anyways?

Good question.  
I studied [various ways of constructing interfaces](https://zig.news/yglcode/code-study-interface-idiomspatterns-in-zig-standard-libraries-4lkj) with particular interest in method number 4 (old way, embed an interface struct into implementer struct and use `@fieldParentPtr()`). Obviously this method does not allow a struct to implement several interfaces since methods are passed a pointer to a particular one. Then I thought that we can construct a _set of interfaces_.

> **Failed attempt to do this**
>
> ```zig
> const log = @import("std").debug.print;
> 
> const TraitA: type = struct {
> 
> impl: ?*const fn(*TraitSet) void = null,
> 
> fn doit(t: *?TraitA) void {
> // if (*t and t.impl) |t, impl| {
> if (t.impl) |impl| {
> const ts: *TraitSet = @fieldParentPtr("a", t);
> impl(ts);
> } else {
> log("A default implementation\n", .{});
> }
> }
> };
> 
> const TraitB: type = struct {
> 
> impl: ?*const fn(*TraitSet) void = null,
> 
> fn doit(t: *?TraitB) void {
> if (t.impl) |impl| {
> const ts: *TraitSet = @fieldParentPtr("b", t);
> impl(ts);
> } else {
> log("B default implementation\n", .{});
> }
> }
> };
> 
> const TraitSet: type = struct {
> a: ?TraitA = null,
> b: ?TraitB = null,
> };
> 
> /// implementations
> 
> const ThingOne: type = struct {
> data: u32,
> ts: TraitSet,
> 
> fn init(d: u32) ThingOne {
> return .{
> .data = d,
> .ts = .{
> .a = .{.impl = myAImpl},
> },
> };
> }
> 
> fn myAImpl(ts: *TraitSet) void {
> const me: *ThingOne = @fieldParentPtr("ts", ts);
> log("I can do A with {}\n", .{me.data});
> }
> };
> 
> const ThingTwo: type = struct {
> data: u32,
> ts: TraitSet,
> 
> fn init(d: u32) ThingTwo {
> return .{
> .data = d,
> .ts = .{
> .b = .{.impl = myBImpl},
> },
> };
> }
> 
> fn myBImpl(ts: *TraitSet) void {
> const me: *ThingTwo = @fieldParentPtr("ts", ts);
> log("I can do B with {}\n", .{me.data});
> }
> };
> 
> pub fn main() void {
> const t1 = ThingOne.init(11);
> var a = t1.ts.a; a.doit();
> 
> // const t2 = ThingTwo.init(22);
> // t1.ts.a.doit();
> // t1.ts.b.doit();
> // t2.ts.a.doit();
> // var m = t2.ts.b.?; m.doit();
> }
> 
> ```

```zig
const TraitSet: type = struct {
    a: ?TraitA = null,
    b: ?TraitB = null,
};

```

These have to be optional otherwise adding more interfaces to the set would break existing implementers.

---

<div class="post-metadata">

**Author:** ![IntegratedQuantum](https://ziggit.dev/user_avatar/ziggit.dev/integratedquantum/32/782_2.png) [@IntegratedQuantum](https://ziggit.dev/u/IntegratedQuantum)\
**Post date:** [August 11, 2024, 5:43pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/9 "2024-08-11T17:43:56Z")

</div>

> [@dee0xeed](#):
>
> Obviously this method does not allow a struct to implement several interfaces since methods are passed a pointer to a particular one.

I don’t really see the problem. Sure you can’t have two interfaces that point at the same function, but apart from that you can you just do it like this:

```zig
const SeveralInterfaceImpl: type = struct {
    data: u32,
    a: TraitA,
    b: TraitB,

    fn init(d: u32) SeveralInterfaceImpl {
        return .{
            .data = d,
            .a = .{.impl = &myAImpl},
            .b = .{.impl = &myBImpl},
        };
    }

    fn myAImpl(a: *TraitA) void {
        const me: *SeveralInterfaceImpl = @fieldParentPtr("a", a);
        ...
    }
    fn myBImpl(b: *TraitB) void {
        const me: *SeveralInterfaceImpl = @fieldParentPtr("b", b);
        ...
    }
};

```

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 11, 2024, 5:56pm UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/10 "2024-08-11T17:56:23Z")

</div>

> [@IntegratedQuantum](#):
>
> I don’t really see the problem

I wanted all interfaces to be collected in a struct and pass it to implementing functions instead of a pointer to concrete interface.  
Ok, it’s another topic already.  
I will mark @LucasSantos91 answer as solution.  
As to my affair with interfaces - if I will be able to do what I wanted I will create new topic.

---

<div class="post-metadata">

**Author:** ![dee0xeed](https://ziggit.dev/letter_avatar_proxy/v4/letter/d/3ab097/32.png) [@dee0xeed](https://ziggit.dev/u/dee0xeed)\
**Post date:** [August 12, 2024, 10:39am UTC](https://ziggit.dev/t/pointer-to-optional-self-in-struct-method/5592/11 "2024-08-12T10:39:29Z")

</div>

> [@IntegratedQuantum](#):
>
> > [@dee0xeed](#):
> >
> > Obviously this method does not allow a struct to implement several interfaces since methods are passed a pointer to a particular one.
> 
> I don’t really see the problem. Sure you can’t have two interfaces that point at the same function, but apart from that you can you just do it like this:

Yep, that was some kind of glitch in my head, sorry.  
Have no idea now what made me think in a so weird way.
