I'm trying to wrap ROS(robot operating system) which has iterators that yield 
non constructible objects, i.e. dereferencing the iterator returns an object 
which only has a private constructor.

I've tried to use this format for wrapping c++ iterators in a nim iterator:
    
    
    type
        CxxIterator*[T,U]{.importcpp: "'0::iterator",nodecl.} = object
    proc inc*[T,U](it: var CxxIterator[T,U]): void {.importcpp: "(++#)".}
    proc `==`*[T,U](a,b:CxxIterator[T,U]): bool {.importcpp: "(# == #)".}
    proc `[]`*[T,U](it: CxxIterator[T,U]):U {.importcpp: "(*#)".}
    
    proc cxBegin(self:View):CxxIterator[View,Message] 
{.header:"rosbag/view.h",importcpp:"(#.begin())".}
    proc cxEnd(self:View):CxxIterator[View,Message] 
{.header:"rosbag/view.h",importcpp:"(#.end())".}
    
    iterator cxxitems*[T](obj:T):Message{.inline.} =
        #mixin cxBegin,cxEnd
        var start = obj.cxBegin()
        var fin = obj.cxEnd()
        while start != fin:
            yield start[]
            inc start
    
    
    Run

but Nim emits:
    
    
    {
       rosbag::MessageInstance const msg;
      while(1){
        /*...*/
      }
    }
    
    Run

which results in `error: no matching function for call to 
‘rosbag::MessageInstance::MessageInstance()’`

For comparison, here's how they should be used in c++:
    
    
    rosbag::View view(bag);
        
        BOOST_FOREACH(rosbag::MessageInstance const m, view)
        {...}
    
    
    Run

or with c++11
    
    
    for(rosbag::MessageInstance const m: rosbag::View(bag))
    {...}
    
    
    Run

And here is the ROS source for the real-world iterators: 
[view.h](http://docs.ros.org/en/diamondback/api/rosbag/html/c++/view_8h_source.html)
 
[message_instance.h](http://docs.ros.org/en/diamondback/api/rosbag/html/c++/message__instance_8h_source.html)

I've put together a minimal example here: [playground 
version:](https://play.nim-lang.org/#ix=3Sen)

please forgive my shitty c++, I know there are bugs in the equality operators:
    
    
    #include <iterator>
    #include <cstddef>
    struct Data
    {
      int m_data[20];
    };
    
    class DataReference
    {
      friend class View;
    public:
      int inspect() {return m_data->m_data[index];}
      int index;
    private:
      Data const* m_data;
      DataReference(Data const& data,int idx) : m_data(&data), index(idx) {}
    };
    
    class View
    {
    public:
        struct Iterator
        {
            using iterator_category = std::forward_iterator_tag;
            using pointer           = DataReference*;
            using reference         = DataReference&;
            
            Iterator(pointer ptr) : m_ptr(ptr) {}
            reference operator*() const { return *m_ptr; }
            
            Iterator& operator++() { (m_ptr->index)++; return *this; }
            Iterator operator++(int) { Iterator tmp = *this; ++(*this); return 
tmp; }
            
            friend bool operator!= (const Iterator& a, const Iterator& b) { 
return (a.m_ptr->index != b.m_ptr->index); };
        
        private:
            pointer m_ptr;
        };
        
        Iterator begin() {
          DataReference* tmp = new DataReference(*m_data,0);
          return Iterator(tmp);
        }
        Iterator end()   {
          DataReference* tmp = new DataReference(*m_data,20);
          return Iterator(tmp);
        }
      View(Data const& d) : m_data(&d){}
    private:
        Data const* m_data;
    };
    
    
    Run
    
    
    type
      Data{.importc.} = object
        m_data: array[20,cint]
      DataReference{.importc.} = object
      View{.importc,nodecl.} = object
    proc initView(d: Data):View{.importcpp:"View(#)".}
    proc inspect(d: DataReference):int{.importcpp.}
    type
        CxxIterator*[T,U]{.importcpp: "'0::Iterator",nodecl.} = object
    proc inc*[T,U](it: var CxxIterator[T,U]): void {.importcpp: "(++#)".}
    proc `!=`*[T,U](a,b:CxxIterator[T,U]): bool {.importcpp: "(# != #)".}
    proc `[]`*[T,U](it: CxxIterator[T,U]):U {.importcpp: "(*#)".}
    
    proc cxbegin(self:View):CxxIterator[View,DataReference] {.importcpp: 
"#.begin()".}
    proc cxend(self:View):CxxIterator[View,DataReference] {.importcpp: 
"#.end()".}
    
    
    proc main() =
      var
        d:Data
        ii:cint
      for i in d.m_data.mitems:
        i = ii
        inc ii
      
      var v{.nodecl.} = initView(d)
      var it = v.cxbegin()
      while it != v.cxend():
        echo it[].inspect()
        inc it
    
    main()
    
    
    Run

The above code works, but what I want is:
    
    
    for x in initView(d):
      echo x.inspect()
    
    
    Run

is there anyway to do that?

Reply via email to