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?

dhasenan
  • 1,177
  • 7
  • 15

2 Answers2

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.

zah
  • 5,314
  • 1
  • 34
  • 31
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.

endragor
  • 368
  • 2
  • 9
  • That would work if I wanted to wrap `Foo::Bar`. I don't know how to make it work with `Foo::Bar`. – dhasenan Apr 09 '15 at 18:27
  • A more concrete example would help to understand your use case. I'm not sure why difference between `Foo::Bar` and `Foo::Bar` matters to you. – endragor Apr 10 '15 at 03:12
  • Updated example. Vector::Iterator 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::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::iterator. – dhasenan Apr 10 '15 at 13:59
  • 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++. – endragor Apr 10 '15 at 14:48
  • You're still not understanding. I want to add a `type VectorIterator[T]` which maps to `Vector::Iterator`. I could add a `Vector::Iterator`, 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::Iterator`. – dhasenan Apr 11 '15 at 18:41