title: Creating C++ stl forward iterator given numpy array using Boost::Python
body: <p>I'm having trouble creating a boost python forward iterator to get a numpy array as input of a C++ function that takes an stl begin and end iterator as a template and modifies it, here's the code for the C++ function:</p>
  <pre><code>template&lt;typename _InputIt&gt;
  void vec_fill_increasing(_InputIt begin, _InputIt end, typename std::iterator_traits&lt;_InputIt&gt;::value_type start, typename std::iterator_traits&lt;_InputIt&gt;::value_type increment)
  {
      typedef typename std::iterator_traits&lt;_InputIt&gt;::value_type _Type;
      if (std::is_floating_point&lt;_Type&gt;::value)
      {
          std::size_t count = 0;
          while (begin != end)
          {
          *begin = start + ((_Type)count*increment);
          ++begin;
          ++count;
          }
      }
      else {
  
          while (begin != end)
          {
              *begin = start;
              start += increment;
              ++begin;
          }
  }
  </code></pre>
  <p>There is already an implementation of an stl input iterator in Boost Python (i.e. <strong>stl_iterator.hpp</strong>) but it's not mutable, so that won't help me here, so I tried to create my own stl_forward_iterator based on the input iterator.</p>
  <pre><code>namespace boost {
      namespace python
      {
          // An STL forward iterator over a python sequence
          template&lt;typename ValueT&gt;
          struct stl_forward_iterator
          : boost::iterator_facade&lt;
              stl_forward_iterator&lt;ValueT&gt;
              , ValueT
              , std::forward_iterator_tag
          &gt;
          {
              stl_forward_iterator()
              : impl_()
              {
              }
  
              // ob is the python sequence
              stl_forward_iterator(boost::python::object const &amp;ob)
              : impl_(ob)
              {
              }
  
          private:
              friend class boost::iterator_core_access;
  
              void increment()
              {
                  this-&gt;impl_.increment();
              }
  
              ValueT&amp; dereference() const
              {
                  return extract&lt;ValueT&amp;&gt;(this-&gt;impl_.current().get())();
              }
  
              bool equal(stl_forward_iterator&lt;ValueT&gt; const &amp;that) const
              {
                  return this-&gt;impl_.equal(that.impl_);
              }
  
              objects::stl_input_iterator_impl impl_;
          };
      }
  }
  </code></pre>
  <p>The only change I really made was changing the return of the deference function to a reference instead of just a value.</p>
  <p>And I use this in my main application as follows:</p>
  <pre><code>template&lt;typename T&gt;
  void wrap_fill_increasing(boost::python::numeric::array&amp; array, T start, T increment) {
     boost::python::stl_forward_iterator&lt;T&gt; begin(array);
     boost::python::stl_forward_iterator&lt;T&gt; end;
     vec_fill_increasing(begin, end, start, increment);
  }
  
  BOOST_PYTHON_MODULE(example) {
      import_array();
      p::numeric::array::set_module_and_type(&quot;numpy&quot;, &quot;ndarray&quot;);
      p::def(&quot;fill_increasing&quot;, &amp;wrap_fill_increasing&lt;int&gt;);
  }
  
  int main(int argc, char **argv)
  {
      PyImport_AppendInittab(&quot;example&quot;, &amp;PyInit_example);
      
      Py_Initialize();
  
      PyRun_SimpleString(
      &quot;import example\n&quot;
      &quot;import numpy\n&quot;
      &quot;z3 = numpy.zeros((1024,), dtype=numpy.int)\n&quot;
      &quot;example.fill_increasing(z3, 0, 1)\n&quot;
      &quot;print(z3)\n&quot;
      );
  
      Py_Finalize();
  }
  </code></pre>
  <p>But I get the error:</p>
  <blockquote>
  <p><strong>TypeError: No registered converter was able to extract a C++ reference to type int from this Python object of type numpy.int32</strong></p>
  </blockquote>
  <p>And it occurs on the dereference function in my stl_forward_iterator and I don't know how to resolve this.</p>
  <p>If something that can help in this scenario doesn't exist, I really think there should be one as a suggestion, unless there is a different solution.</p>