Hello,
I have a little question. I'm creating some procs with a template like this:
template iteratorsArithmetics*(name, constName: untyped): untyped =
proc `+`*[T](it: constName[T], offset: int) : constName[T]
{.importcpp: "# + #"}
proc `-`*[T](it: constName[T], offset: int) : constName[T]
{.importcpp: "# - #"}
proc `+`*[T](it: name[T], offset: int) : name[T]
{.importcpp: "# + #"}
proc `-`*[T](it: name[T], offset: int) : name[T]
{.importcpp: "# - #"}
Now the problem is that I also what to be able to pass the generic parameters ([T], [T1, T2], nothing...etc) as argument to the template. I tried addi a gen: untyped parameter but the syntax:
proc `+`* gen (it: constName gen, offset: int) : constName gen
is not accepted.
Is there a simple way to do it or do I have to use more elaborated marcos ?
Thank you
This should work:
template iteratorsArithmetics*(name, constName, T: untyped): untyped =
proc `+`*[T](it: constName[T], offset: int) : constName[T]
{.importcpp: "# + #"}
proc `-`*[T](it: constName[T], offset: int) : constName[T]
{.importcpp: "# - #"}
proc `+`*[T](it: name[T], offset: int) : name[T]
{.importcpp: "# + #"}
proc `-`*[T](it: name[T], offset: int) : name[T]
{.importcpp: "# - #"}
Your T should still be a generic symbol like T, T1, T2, U, ... not instantiated like int
Thanks you @mratsim.
The problem with this approach is that I cannot use it if my type don't have generic parameters or if it has multiples generic parameters.
For multiple params, I tried something like this:
template iteratorsArithmetics*(name, constName: untyped, gparams: varargs[untyped]):untyped =
proc `+`*[gparams](it: constName[gparams], offset: int) : constName[gparams]
{.importcpp: "# + #"}
proc `-`*[gparams](it: constName[gparams], offset: int) : constName[gparams]
{.importcpp: "# - #"}
proc `+`*[gparams](it: name[gparams], offset: int) : name[gparams]
{.importcpp: "# + #"}
proc `-`*[gparams](it: name[gparams], offset: int) : name[gparams]
{.importcpp: "# - #"}
iteratorsArithmetics(VecIterator, VecConstIterator, T)
but I get an error:
vector.nim(207, 21) template/generic instantiation of `iteratorsArithmetics` from here
./private/utils.nim(33, 72) Error: cannot instantiate VecConstIterator
got: <T>
but expected: <T>
For the case where I don't have any generic parameters, I could make one template for non generic types and use overloading, but for the sake of learning can we manage to do it all with only one template ?
PS: I my code base I have only too uses of that template, one where there is one generic parameter and the other with no generic parameters (so I could not use this template approach), but I'm trying to learn more about Nim templates.
You can simply leave off the generic parameters and use it as a typeclass.
template iteratorsArithmetics*(name: untyped): untyped =
proc `+`*[T:name](it: T, offset: int): T
{.importcpp: "# + #"}
proc `-`*[T:name](it: T, offset: int): T
{.importcpp: "# - #"}
type
Foo0 = distinct int
Foo1[T] = distinct T
iteratorsArithmetics(Foo0)
iteratorsArithmetics(Foo1)
var
x0: Foo0
x1: Foo1[int]
echo int(x0 + 1)
echo int(x1 + 1)
Clean and beautiful, thanks !
I didn't know about type classes and that we could use a type without its generic parameters like this.
For any one like me: https://nim-lang.org/docs/manual.html#generics-type-classes