blITeratorAPI — Custom iterators in c++11 made easy

What is this?

This header-only-library provides a set of classes that allow a programmer to easily create custom iterators and/or custom buffers like the boost circular buffer here:

Ring buffer from boost c++

Where do I get it and how do I install it?

You can get the library on github here, download and unzip.

Just copy the blIteratorAPI folder with its content to your ‘include’ directory, and include it into your code:

#include "blIteratorAPI/blIteratorAPI.hpp"

Dependencies

  • c++11
  • <memory>
  • <iterator>

Quick Example

#include <iterator>
#include <memory>
#include <iostream>

// Include the blIteratorAPI

#include "blIteratorAPI.hpp"

int main()
{
    // Create a raw array

    int myArray[] = {2,23,5,56,2354,-23,23,-432,231};

    // The library provides a class
    // to wrap a raw array

    auto myArrayWrapper = blIteratorAPI::getRawArrayWrapper(myArray);

    // The library provides a
    // flexible iterator class
    // to create custom iterators

    // Here we create an iterator
    // to linearly move through
    // the array.
    // This iterator never goes
    // past the array's end even
    // if the user tries to.

    blLinearIterator<decltype(myArrayWrapper)> myIter(myArrayWrapper);

    for(auto iter = myIter.begin();
        iter != myIter.end();
        ++iter)
    {
        std::cout << "iter pos = " << iter.getDistanceFromBeginToIter();
        std::cout << ", dist from end = " << iter.getDistanceFromIterToEnd();
        std::cout << ", value = " << *iter << "\n";
    }

    std::cout << "\n\n";

    // Get input from user
    // before quitting

    int inputFromUser;
    std::cin >> inputFromUser;

    return 0;
}

What does this library actually provide?

The aim of the blIteratorAPI library is to allow a user to easily create custom iterators for their own needs.

In order to do that, it introduces tools broken down in the following header files:

  • blSmartPointerFunctions.hpp — A collection of simple template functions to get std::shared_ptr pointers of resources.
    • For example:
    // Some object of whatever type
    myType object;
    
    // Get a shared_ptr to object
    auto objectPtr = get_shared_ptr(object);
    
  • blRawIterators.hpp — Defines a random access iterator and reverse_iterator that can be used in custom classes to allow their use in stl algorithms.
    • For example in a custom container class, define the following typedefs:
    template<typename blDataType>
    class customArray
    {
    public:
    
        // Define the iterator typedefs
        typdef blRawIterator<blDataType> iterator;
        typdef blRawReverseIterator<blDataType> reverse_iterator;
    
        iterator begin(){return iterator(&m_container[0]);}
        iterator end(){return iterator(&m_container[size()];}
        reverse_iterator rbegin(){return reverse_iterator(&m_container[size()-1];}
        reverse_iterator rend(){return reverse_iterator(&m_container[-1];}
    
        blDataType m_container;
    };
    
  • blArray.hpp — A static templated array with helper functions such as “begin”, “end” and “size” that make it easy to use with stl algorithms.
[^]: Similar to std::array, but can be used where there is no stl like for Arduino.

[^]: blArray is null terminatedand like std::string, its nul terminated data can be accessed with functions “c_std()” and “data()”

[^]: blArray size is known at compile time, it can be declared and used like in the following examples:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Ex. 1
blIteratorAPI::blArray&lt;int,3&gt; myArray1;

// Ex. 2 (From a null terminated string)
auto myArray2 = blIteratorAPI::getArrayFromNullTerminated("hello world");

// Ex. 3 (From begin/end iterators)
std::vector&lt;float&gt; myVector(13,4);
auto myArray3 = blIteratorAPI::blArray&lt;float,13&gt;(myVector.begin(),myVector.end());

// Ex. 4 (From a static array)
int a[] = {4,23,24,43,1};
auto myArray4 = blIteratorAPI::blArray(a);

// Ex. 5 (From an initializer list)
blIteratorAPI::blArray&lt;int,6&gt; myArray5 = {1,2,3,4,5,6};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • blRawArrayWrapper.hpp — A class that wraps existing raw static or dynamic arrays with iterator functionality to make it easy to use with stl algorithms. This only wraps raw arrays, but does not delete them on destruction.
    // Create a static
    // array and wrap it
    
    int myArray[] = {2,3,4,5,2,12,3,43,234,121,90};
    auto myArrayWrapper = getRawArrayWrapper(myArray);
    
    // Iterate over it
    
    for(auto iter = myArrayWrapper.begin();
        iter != myArrayWrapper.end();
        ++iter)
    {
        std::cout &lt;&lt; "iter = " &lt;&lt; *iter &lt;&lt; "\n";
    }
    
    // Create a dynamic
    // array and wrap it
    // NOTE: With a dynamic
    //       array, we have to
    //       specify the size
    
    char* myWord = "hello world";
    auto myWordWrapper = getRawArrayWrapper(myWord,12);
    
  • blIteratorFunctors.hpp — Functors defined in this header file are used by the custom iterator class to make it behave as desired.
    • There are two types of functors defined in this file:
    1. blBeginEndFunctor — Used to know how to call the container’s begin() and end() functions. A user can define his/her own blBeginEndFunctorType to customize the behaviour.
    2. blAdvanceDistanceFunctor — Used to know how to advance the iterator and how to calculate the distance between two custom iterators. A user can define his/her own blAdvanceDistanceFunctor to customize the behaviour.
    [^]: The “begin” and “end” functions inside a blBeginEndFunctor are defined as static functions.

    [^]: The “advance” and “distance” functions inside a blAdvanceDistanceFunctor are defined as static functions.
  • blIterator.hpp — Finally, the custom iterator class. This class can be used to create iterators with custom behaviour.
    • The library already provides some common use iterators, for example:
      • blLinearIterator, blLinearConstIterator, blLinearReverseIterator, blLinearConstReverseIterator — These iterators advance linearly, but never go past their “end” or never past their “begin” when moving backwards.
      • blCircularIterator, blCircularConstIterator, blCircularReverseIterator, blCircularConstReverseIterator — These iterators advance through the container in a circular fashion, never reaching their “end”.
      [^]: NOTE: Be careful with circular iterators, because they never reach their “end”

      • The following are the steps necessary to define your own custom iterator:
      1. Create a blBeginEndFunctor that defines two static functions:
        • begin(T& container) — Calls iterator to first element of container
        • end(T& container) — Call iterator to one place after last element of container
      2. Create a blAdvanceDistanceFunctor that defines two static functions:
        template <typename blIteratorType>
        static void advance(blIteratorType& iter,
                            const ptrdiff_t& howManyStepsToAdvanceIter,
                            const blIteratorType& beginIter,
                            const blIteratorType& endIter,
                            const ptrdiff_t& distanceFromBeginToIter,
                            const ptrdiff_t& distanceFromIterToEnd)
        {
        }
        
        template <typename blIteratorType>
        static ptrdiff_t distance(const blIteratorType& iter1,
                                  const blIteratorType& iter2,
                                  const ptrdiff_t& distanceFromBeginToIter1,
                                  const ptrdiff_t& distanceFromBeginToIter2,
                                  const ptrdiff_t& distanceFromIterToEnd1,
                                  const ptrdiff_t& distanceFromIterToEnd2)
        {
            return whateverDistance;
        }
        

    What is the license?

    The MIT License (MIT)

    To do:

    Add more examples showing how to create and use custom iterators

About Vincenzo Barbato

Known to his friends as Enzo, he's an outside-the-box engineer/researcher whose interests and expertise span many fields, including controls systems, multi-physics simulations, mechatronics, oil technologies, data analysis and machine vision just to name a few.

Refusing to grow up, he's on a continuous journey to develop simple and creative solutions that have the power of disrupting industries by optimizing systems and processes.

Married to a beautiful wife, with two beautiful daughters and two identical twin boys, his home is a never ending chaotic fountain of inspiration.

His outlook on life:

"Never blindly accept what you're told, listen, but then question, with curiosity, creativity and collaboration we can change the world"

About Enzo

Known to his friends as Enzo, he's an outside-the-box engineer/researcher whose interests and expertise span many fields, including controls systems, multi-physics simulations, mechatronics, oil technologies, data analysis and machine vision just to name a few. Refusing to grow up, he's on a continuous journey to develop simple and creative solutions that have the power of disrupting industries by optimizing systems and processes. Married to a beautiful wife, with two beautiful daughters and two identical twin boys, his home is a never ending chaotic fountain of inspiration. His outlook on life: "Never blindly accept what you're told, listen, but then question, with curiosity, creativity and collaboration we can change the world"

One Comment

  1. Pingback: Using OpenCV within QTCreator in Windows | BarbatoLabs

Leave a Reply

Your email address will not be published. Required fields are marked *