Hi,

I have a little question. I order to wrap some C++ code (and add a feature to c2nim), I have to write something like this:

proc constructFoo*[T1, T2](): Foo[T1, T2] =
  result = implConstructFoo(T1, T2)

proc implConstructFoo*(T1: typedesc, T2: typedesc): Foo[T1, T2] {.constructor, importcpp: "Foo<\'1, \'2>(@)",
                               header: "typename.hpp".}
This allows me to wrap C++ constructors/destrucotrs/methods that depends on templates.

The template parameters have to be passed as arguments to the functions, as 'i refers to the ith parameter type and not the ith generic type.

What I'd like to do now is to make constructFoo a template, so I'm sure that it is inlined and do not cost the user any overhead.

Something like this:

template constructFoo*[T1, T2](): untyped =
  implConstructFoo(T1, T2)

proc implConstructFoo*(T1: typedesc, T2: typedesc): Foo[T1, T2] {.constructor, importcpp: "Foo<\'1, \'2>(@)",
                               header: "typename.hpp".}
But I get an error:
Error: type mismatch: got (float, float)
but expected one of:
proc implConstructFoo(T1, T2: typedesc): Foo[T1, T2]

thanks for your help

2017-10-09 14:30:43
.
template constructFoo*(T1, T2): untyped =
  implConstructFoo(T1, T2)
2017-10-09 17:43:51

well my point from using the syntax construct[T1, T2]() is to separate generic parameters from normal ones.

For example, if I wrap the C++ vector, I want to be able to write:

var v = construcVector[float](10)
which is more clear than constructVector(float, 10) and more similar to the C++ version vector<float>(10).

2017-10-10 07:06:24

Yes, that makes sense.

This seems to work:

template constructFoo*[T1, T2](): Foo[T1, T2] =
  implConstructFoo(typedesc[T1], typedesc[T2])

2017-10-10 09:49:26

Oh great that's works !

template constructFooOtherNestedClass*[T; T1; T2](): FooOtherNestedClass[T, T1, T2] =
  implConstructFooOtherNestedClass(typedesc[T], typedesc[T1], typedesc[T2])

proc implConstructFooOtherNestedClass*(T, T1, T2: typedesc): FooOtherNestedClass[T, T1, T2] {.
    constructor, importcpp: "Foo<\'*1>::OtherNestedClass<\'*2,\'*3>()",
    header: "typename.hpp".}


template constructFooOtherNestedClass*[T; T1; T2](i: cint): FooOtherNestedClass[T, T1, T2] =
  implConstructFooOtherNestedClass(typedesc[T], typedesc[T1], typedesc[T2], i)

proc implConstructFooOtherNestedClass*(T, T1, T2: typedesc, i: cint): FooOtherNestedClass[T, T1, T2] {.
    constructor, importcpp: "###Foo<\'*1>::OtherNestedClass<\'*2,\'*3>(@)", #The ### is to avoid the three first argumenta being passed to the constructor
    header: "typename.hpp".}

but too bad there is a bug preventing me from using it :/ It seems that we cannot overload templates with generic parameters:

var nc = constructFooOtherNestedClass[float, float64, int8]()
gives me:

 Error: type mismatch: got ()
but expected one of:
template constructFooOtherNestedClass[T; T1; T2](i: cint): FooOtherNestedClass[T, T1,
    T2]
test case:
#this works
template test() =
    echo "no param"

template test(i: int)=
    echo "in param"

test()
test(1)

#but this not
template test[T]() =
    echo "no param"

template test[T](i: int)=
    echo "in param"

test[int]()
test[int](1)
https://play.nim-lang.org/?gist=f92e0ddcce67df8ca604a253ead94e21

2017-10-10 12:40:14

You can circumvent it.
Choose some type, which won't be used in your overloadings. Say, let it be float.

template test[T](i: int|float = 0.0)=
  when i is int:
    echo "in param"
  else:
    echo "no param"

test[int]()
test[int](1)

Or, for it to look less hacky, you may define some special type and value for it:

type Nothing = object
const nothing = Nothing()
template test[T](i: int|Nothing = nothing)=
  when i is int:
    echo "in param"
  else:
    echo "no param"

test[int]()
test[int](1)

2017-10-10 13:17:47

Wow thank !

And I'll look into fixing the bug when I'll really need it.

2017-10-10 14:00:05