Take the following example. Obviously the doSomething function is wrong but
should hint what I want to do.
type
TestObj = object
text: string
value1: int
value2: int
type
TestGeneric[T, MEMBER] = object
internalVal: T
proc doSomething[T, MEMBER](obj: TestGeneric[T, MEMBER], newVal: int) =
...
let offset = offsetOf(T, MEMBER)
...
var x = T(text: "test", value1: 1, value2: 5)
x.MEMBER = newVal
internalVal = x
...
Run
I want to do operations with a compile time selected member variable in a
generic type. Generics don't seem to accept untyped parameters so I have so far
understood that you have two ways to point out the member variable either using
a string or type.member like in the example below.
let x = TestGeneric[TestObj , TestObj.value1]()
... alternatively ...
let x = TestGeneric[TestObj , "value1"]()
Run
offsetOf takes a type or a value and then an identifier. Neither TestObj.value1
or a "value1" will satisfy offsetOf second argument as it only wants an untyped
identifier. Ironically offsetOf seems to trickle down to an intrinsic
offsetOfDotExpr(value.member) which almost seems to use type.member syntax
(<https://github.com/nim-lang/Nim/blob/version-1-6/lib/system.nim#L635>) .
Maybe a type.member version of it could be useful. Regardless, offsetOf needs
an identifier which neither TestObj.value1 or "value1" are so the question is
how I can convert it to one.
For using x.MEMBER in the example, it seems like there are dereference
operators for the any object
(<https://nim-lang.org/docs/typeinfo.html#%5B%5D%3D%2CAny%2CAny>). However,
these require some kind of conversion to an any object and using the string to
identify the member variable must be used. I have not been able to get these to
work. The question is also if there is a performance penalty when using these.
Also another question is if there are more direct ways to achieve this.