Iterators
ruby-bindgen automatically generates Rice define_iterator calls for C++ classes that expose iterator methods. This provides Ruby's Enumerable module support for C++ containers. For details on how Rice bridges C++ iterators to Ruby, see the Rice Iterators documentation.
Automatic Iterator Detection
When ruby-bindgen encounters a C++ class with begin() and end() methods that return iterators, it automatically generates the appropriate define_iterator calls. For example, a C++ class like:
class Bitmap {
public:
PixelIterator begin();
PixelIterator end();
};
Will generate:
define_class_under<Bitmap>(rb_mModule, "Bitmap").
define_iterator<PixelIterator(Bitmap::*)()>(&Bitmap::begin, &Bitmap::end, "each");
Note: If a class only defines begin() const and end() const (without non-const versions), the generated method will be each_const. Since Ruby conventions expect each, ruby-bindgen automatically aliases each to each_const in this case.
Multiple Iterator Types
ruby-bindgen handles classes with multiple iterator types, such as const iterators, reverse iterators, and const reverse iterators:
| Method Pair | Ruby Method Name |
|---|---|
begin()/end() |
each |
begin() const/end() const |
each_const |
rbegin()/rend() |
each_reverse |
rbegin() const/rend() const |
each_reverse_const |
Incomplete Iterator Traits
Some C++ libraries define iterators that lack the required std::iterator_traits typedefs. These iterators are missing one or more of:
value_typereferencepointerdifference_typeiterator_category
Rice's define_iterator requires these traits to function properly. Without them, you'll see compile errors like:
error C2039: 'value_type': is not a member of 'std::iterator_traits<MyIterator>'
Automatic Traits Generation
ruby-bindgen automatically detects incomplete iterators and generates std::iterator_traits specializations for them. For example, given an iterator like:
// Iterator WITHOUT proper std::iterator_traits
class IncompleteIterator
{
public:
IncompleteIterator() : ptr_(nullptr) {}
explicit IncompleteIterator(Pixel* p) : ptr_(p) {}
Pixel& operator*() const { return *ptr_; }
IncompleteIterator& operator++() { ++ptr_; return *this; }
bool operator!=(const IncompleteIterator& other) const { return ptr_ != other.ptr_; }
private:
Pixel* ptr_;
// NOTE: Missing value_type, reference, pointer, difference_type, iterator_category
};
ruby-bindgen will generate:
// Iterator traits specializations for iterators missing std::iterator_traits
namespace std
{
template<>
struct iterator_traits<iter::IncompleteIterator>
{
using iterator_category = forward_iterator_tag;
using value_type = iter::Pixel;
using difference_type = ptrdiff_t;
using pointer = iter::Pixel*;
using reference = iter::Pixel&;
};
}
Examples
See test/headers/cpp/iterators.hpp for example iterator classes, including both complete and incomplete iterators. The generated bindings are in test/bindings/cpp/iterators-rb.cpp.