Wrapping nested templated types in nim
Asked Answered
B

2

7

I have a C++ type like:

template <typename T>
class Vector {
  struct Iterator {
  };
};

And in C++ I can use Iterator as Vector<int>::Iterator.

How do I wrap this to use it from Nim? c2nim emits

type Vector[T] {.importcpp...} = object
  type Iterator[T] {.importcpp...}

which doesn't compile because nim doesn't have nested types, and would produce Vector<T>::Iterator<T> rather than Vector<T>::Iterator.

I can use non-nested types in Nim:

type VectorIterator[T] {.importcpp: "Vector::Iterator".}
var v : VectorIterator[cint]

And this naturally produces Vector::Iterator<int>, which is wrong (it should be Vector<int>::Iterator).

Is there a way to change the import specification to produce the correct output?

Bosket answered 8/4, 2015 at 23:15 Comment(0)
B
6

I've recently added the support for wrapping such nested types in the compiler. You'll need to use the latest code from the devel branch. Here is how it can be done:

{.emit: """

template <class T>
struct Vector {
  struct Iterator {};
};

""".}

type
  Vector {.importcpp: "Vector".} [T] = object
  VectorIterator {.importcpp: "Vector<'0>::Iterator".} [T] = object

var it: VectorIterator[int]

The relevant details in the manual can be found here and here.

Brookebrooker answered 13/4, 2015 at 23:17 Comment(0)
T
0

I think there is no much sense in creating nested types in Nim, because minimal unit of encapsulation is module. So you should just create a separate FooBar[T] type in the same module.

Trilley answered 9/4, 2015 at 12:27 Comment(5)
That would work if I wanted to wrap Foo::Bar<T>. I don't know how to make it work with Foo<T>::Bar.Bosket
A more concrete example would help to understand your use case. I'm not sure why difference between Foo::Bar<T> and Foo<T>::Bar matters to you.Trilley
Updated example. Vector::Iterator<int> uses Vector as a namespace, and Vector is an uninstantiated template, not a type or a namespace. It's illegal to use uninstantiated templates in C++. Then it uses Iterator as a template, and Iterator is not a template, just a type inside a templated type. Vector<int>::Iterator is a struct inside an instantiated template and works as expected. This isn't some strange edge case of the language; everyone who's worked with the STL has seen a std::vector<int>::iterator.Bosket
In Nim, you should just add iterator items[T](v: Vector[T]): T in your module. There is no need in a separate class. Even if there would be a need, I don't see a problem in having a separate VectorIterator[T] class. Bottom line is - there is no way to have nested types in Nim, because there is no point in that. So you should do some refactoring for the cases where you have nested types in C++.Trilley
You're still not understanding. I want to add a type VectorIterator[T] which maps to Vector<T>::Iterator. I could add a Vector::Iterator<T>, but that doesn't match the C++ type. I don't have control over the C++ type. I need to know if I can set any options, use a particular format of import specification, with {.importcpp.} to map a type to Vector<T>::Iterator.Bosket

© 2022 - 2024 — McMap. All rights reserved.