You need to avoid the `ref` if you need to avoid the indirection, but apart from that it's IMO an idiomatic API. type BarObj = object data: Foo refcount: ptr int proc `=destroy`(bar: var BarObj) = if bar.refcount[] == 0: freeFoo(bar.data) dealloc bar.refcount else: dec bar.refcount[] proc `=copy`(dest: var BarObj; src: BarObj) = inc src.refcount[] `=destroy`(dest) dest.data = src.data dest.refcount = src.refcount proc newBar(): BarObj = result = BarObj(data: newFoo(), refcount: cast[ptr int](alloc0(sizeof(int))) Run
unless Foo already offers a refcount, you need to add one yourself and it needs a pointer indirection.