{.experimental.}
type
List*[T] = object
len: Natural
elms: ptr T
proc allocList*[T](len: Natural): List[T] =
result = List[T](len: len, elms: cast[ptr T](alloc(len*sizeof(T))))
proc `=destroy`(list: var List) =
if list.elms != nil: dealloc list.elms
echo "List destroyed"
proc `[]`*[T](list: var List[T]; i: Natural): var T =
cast[array[T]](list.elms)[i]
block:
var l1 = allocList[char](3)
l1[0] = 'a'
l1[1] = 'b'
l1[2] = 'c'
The allocation and destruction operate as expected but I am struggling to find a way to access the elements of the allocated array elms. Clearly ptr T cannot be treated as an array as it can in C so I have tried various alternatives including openarray but not allowed to cast to ptr openarray[T] following the alloc call. I looked through the tests and examples provided with the Nim compiler but cannot find something similar. Any ideas?
{.experimental.}
type
List*[T] = object
len: Natural
elms: ptr array[0, T]
proc allocList*[T](len: Natural): List[T] =
result = List[T](len: len, elms: cast[ptr array[0, T]](alloc(len*sizeof(T))))
proc `=destroy`(list: var List) =
if list.elms != nil: dealloc list.elms
echo "List destroyed"
proc `[]`*[T](list: var List[T]; i: Natural): var T =
list.elms[][i]
block:
var l1 = allocList[char](3)
l1[0] = 'a'
l1[1] = 'b'
l1[2] = 'c'
generates the message: list.nim(20, 5) Error: type mismatch: got (List[system.char], int literal(0), char)
The following code should do what you want:
{.experimental.}
type
Elems{.unchecked.}[T] = array[0..0, T]
List*[T] = object
len: Natural
elms: ptr Elems[T]
proc allocList*[T](len: Natural): List[T] =
result = List[T](len: len, elms: cast[ptr Elems[T]](alloc(len*sizeof(T))))
proc `=destroy`(list: var List) =
if list.elms != nil: dealloc list.elms
echo "List destroyed"
proc `[]`*[T](list: var List[T]; i: Natural): var T =
list.elms[][i.int]
proc `[]=`*[T](list: List[T]; i: Natural, x: T) =
list.elms[][i] = x
block:
var l1 = allocList[char](3)
l1[0] = 'a'
l1[1] = 'b'
l1[2] = 'c'
proc initList: List[char] =
result = allocList[char](3)
result[0] = 'a'
result[1] = 'b'
result[2] = 'c'
proc print[T](list: List[T]) =
echo "print " & list[0]
block:
print(initList())
the destructor for the list created by initList() is never called. Do I need to add more pragmas or is this a limitation of the current RAII support?
block:
var l2 = allocList[List[char]](2)
l2[0] = initList()
l2[1] = initList()
echo l2[0][0]
only the list l2 is destroyed, the element lists are not. What do I need to do in the list destructor to ensure that the elements are also destroyed if a destructor is defined for them?