Hi,
I was looking at approaches to something resembling variadic templates in C++. Procs accepting tuples seem very powerful but maybe not super friendly for a third party to use in some cases where seemingly insignificant syntax differences can cause errors: https://play.nim-lang.org/#ix=2SnY
But this is otherwise awesome so I figured why not try and put an abstraction in front of them?
In my case this is useful because it lets me easily populate what is essentially a multi-typed generic data store of components for an entity component system (of course what the world really needs is yet another ECS, right? :D). I have a generic builder which works fine (if slightly java-y) but wanted something a bit more terse.
I found you can simplify the interface by putting a special template in front of it that looks like this:
echoTypes(values: varargs[untyped]) =
echoTypesImpl((values))
The magic happens because adding that extra pair of parens causes the compiler to interpret the varargs as a tuple assuming it contains two or more elements. If it only contains one it interprets it as that single value (not a tuple). It seems the compiler sees the varargs as a kind of comma separated list in the template context. I discovered this almost totally by accident: https://play.nim-lang.org/#ix=2SnK
Example generates an error containing: but expression 'MyType()' is of type: MyType "expression: myProc(MyType(), MyType())"
Here's a full, working example:
import typetraits
type
A = object
B = object
proc echoTypesImpl[T](value: T) =
echo "the type is: ", value.type # maybe this is more like myContainer[T].put(key, value) or something to that effect.
proc echoTypesImpl(values: tuple) =
for x in values.fields: echoTypesImpl(x)
template echoTypes(values: varargs[untyped]) =
echoTypesImpl((values))
echoTypes(A(), B(), B(), A())
https://play.nim-lang.org/#ix=2Snw
My question is: is this a good idea? Is the way template varargs are handled stable such that this won't break in the future? Is there some edge case where this won't work properly? Or is using macros simply a better approach for this?
I ask partly because the nim manual suggests that untyped varargs in templates aren't that useful, but this seems useful and I've not seen this approach documented anywhere. Thanks!