Common Structures
Iterators
Iterators provide a container-independent way to access elements in an aggregate structure without exposing or requiring any underlying structure. This vital implementation intends to provide an easy way to create an input iterator via a value reference generation function, similar to how iterators in the python language function.
Each iterator class descends from a common base-class due to a wealth of shared functionality. This base class has protected constructors in order to prevent direct use.
It is currently undefined behavior when dereferencing an iterator after source
data has been released (e.g. if the next_value_func
is iterating
over a vector of values and the source vector is released in the middle of
iteration).
Generation Function
The value reference generation function’s purpose is to return the reference to the next value of type T in a sequence every time it is called. When the end of a specific is reached, an exception is raised to signal the end of iteration.`
Upon incrementing this iterator, this next
function is called and the
reference it returns is retained in order to yield the value or reference
when the *
or ->
operator is invoked on this iterator.
Generator function caveat: Since the next-value generator function is to return references, the function should ideally return unique references every time it is called. If this is not the case, the prefix-increment operator does not function correctly since the returned iterator copy and old, incremented iterator share the same reference and thus share the same value yielded.
Providing a function
Next value functions can be provided in various ways from existing functions to functions created on the fly. Usually, inline structure definitions or lambda functions are used to provide the next-value functionality.
For example, the following shows how to use a lambda function to satisfy
the next_value_func
parameter for a vital::iterator of type int:
int a[] = { 0, 1, 2, 3 };
using iterator_t = vital::iterator< int >;
iterator_t it( []() ->iterator_t::reference {
static size_t i = 0;
if( i == 4 ) { VITAL_THROW( vital::stop_iteration_exception, "container-name" ); }
return a[i++];
} );
Similarly an inline structure that overloads operator() can be provided if more state needs to be tracked:
using iterator_t = vital::iterator< int >;
struct next_int_generator
{
int *a;
size_t len;
size_t idx;
next_int_generator(int *a, size_t len )
: a( a )
, len( len )
, idx( 0 )
{}
iterator_t::reference operator()()
{
if( idx == len ) { VITAL_THROW( vital::stop_iteration_exception, "container-name" ); }
return a[idx++];
}
};
int a[] = {0, 1, 2, 3};
iterator_t it( next_int_generator(a, 4) );
-
template<typename T, typename Tb>
class base_iterator Internal base class for vital iterator types, fulfilling the input-iterator concept.
- Template Parameters:
T – Value type being iterated over. This should not be const.
Tb – Base type for references and pointers. This will will be the same as T for a non-const iterator and the const version of T for a const iterator.
Public Functions
-
virtual ~base_iterator() = default
Default destructor.
-
inline virtual base_iterator<T, Tb> &operator=(base_iterator<T, Tb> const &rhs)
Assignment operator overload
Assigning another iterator to this iterator copies the other iterator’s next value function, current value pointer and past-end state flag. Remember that copying the other iterator’s next-value function does not copy that function’s state and iterations by the other iterator now affect iteration returns of this iterator.
- Parameters:
rhs – Other iterator instance to assign to this iterator instance.
- Returns:
Reference to this iterator instance.
-
inline virtual base_iterator<T, Tb> &operator++()
Prefix increment operator overload (e.g. ++i)
This requests and stores the reference to the next value provided by the generation function.
- Returns:
Reference to this iterator instance.
-
inline virtual base_iterator<T, Tb> operator++(int)
Postfix increment operator overload (e.g. i++).
- Returns:
A copy of this iterator before requesting the next value reference. If the next value function does not return sequentially unique references, then the returned iterator’s reference will point to the same value as this iterator.
-
inline virtual value_type operator*() const
Dereference operator overload
- Returns:
A copy of the current iteration reference.
-
inline virtual pointer operator->() const
Arrow operator overload
- Returns:
Pointer to the current iteration reference.
Friends
-
inline friend bool operator==(base_iterator<T, Tb> const &lhs, base_iterator<T, Tb> const &rhs)
Equality operator overload
Two iterators are considered equal if their current iteration references are equal in value or both iterators in a past-end state. If one iterator is in a past-end state and the other is not, they two iterators will never be equal.
- Returns:
If the two iterators are equal to each other.
-
inline friend bool operator!=(base_iterator<T, Tb> const &lhs, base_iterator<T, Tb> const &rhs)
Inequality operator overload
- Returns:
If the two iterators is NOT equal to each other.
-
inline friend void swap(base_iterator<T, Tb> const &lhs, base_iterator<T, Tb> const &rhs)
Override of swap function between two same-type iterators.
Swaps function reference, current value pointer and past-end state boolean.
-
template<typename T>
class iterator : public kwiver::vital::base_iterator<T, T> Vital templated non-const iterator class.
- Template Parameters:
T – Value type being iterated over.
Public Functions
-
iterator() = default
Construct default iterator.
A default constructed iterator is set to be a past-end iterator and is equal to any iterator past its end.
-
inline iterator(next_value_func_t const &next_value_func)
Construct iterator with a function to yield the next iteration value reference or raise a stop_iteration_exception.
- Parameters:
next_value_func – Function that returns the reference to the next value in a sequence until the end of that sequence, then raising the
stop_iteration_exception
.
-
inline iterator(iterator<T> const &other)
Copy Constructor (shallow)
Shallow copy iteration state from another iterator. This is shallow because the next-value function’s state is not fully copied, but now shared between the original and copied iterator. Thus, as one iterator is moved, the generation function state is changed, affecting subsequent generator function returns in the other iterator.
- Parameters:
other – Other iterator to copy from.
Friends
- friend class const_iterator< T >
-
template<typename T>
class const_iterator : public kwiver::vital::base_iterator<T, T const> Vital templated const iterator class.
This class is similar to the vital::iterator except that returned references and pointers from dereferencing and arrow operators are const.
This subclass provides additional overloaded implementations of `
friend bool operator==
andfriend bool operator!=
for the different combinations of const and non-const iterator equality checks.- Template Parameters:
T – Value type being iterated over.
Public Functions
-
const_iterator() = default
Construct default iterator.
A default constructed iterator is set to be a past-end iterator and is equal to any iterator past its end.
-
inline const_iterator(next_value_func_t const &next_value_func)
Construct iterator with a function to yield the next iteration value reference or raise a stop_iteration_exception.
- Parameters:
next_value_func – Function that returns the reference to the next value in a sequence until the end of that sequence, then raising the
stop_iteration_exception
.
-
inline const_iterator(const_iterator<T> const &other)
Copy Constructor (shallow)
Shallow copy iteration state from another iterator. This is shallow because the next-value function’s state is not fully copied, but now shared between the original and copied iterator. Thus, as one iterator is moved, the generation function state is changed, affecting subsequent generator function returns in the other iterator.
- Parameters:
other – Other iterator to copy from.
-
inline const_iterator(iterator<T> const &other)
Copy Constructor (shallow) from non-const iterator
Shallow copy iteration state from another iterator. This is shallow because the next-value function’s state is not fully copied, but now shared between the original and copied iterator. Thus, as one iterator is moved, the generation function state is changed, affecting subsequent generator function returns in the other iterator.
- Parameters:
other – Other iterator to copy from.
Friends
-
inline friend bool operator==(iterator<T> const &it, const_iterator<T> const &cit)
Friend operator== overload for testing [non-const, const] equality.
-
inline friend bool operator==(const_iterator<T> const &cit, iterator<T> const &it)
Friend operator== overload for testing [const, non-const] equality.
-
inline friend bool operator!=(iterator<T> const &it, const_iterator<T> const &cit)
Friend operator!= overload for testing [non-const, const] non-equality.
-
inline friend bool operator!=(const_iterator<T> const &cit, iterator<T> const &it)
Friend operator!= overload for testing [const, non-const] non-equality.
References
In creating this structure, the following were referenced for what composes input iterators as well as how this fits into C++ class and function definitions:
Iterable Mixin
This mixin is intended to allow containers implemented in Vital to expose an
iteration interface via the C++ standard begin
and end
methods.
-
template<typename T>
class iterable Pure-virtual mixin class to add iteration support to a class.
- Template Parameters:
Type – to iterate over.
Subclassed by kwiver::vital::set< descriptor_sptr >, kwiver::vital::set< image_container_sptr >, kwiver::vital::set< detected_object_sptr >, kwiver::vital::set< T >
Iterator Accessors
Accessors for const and non-const iterators
Get the non-const iterator to the beginning of the collection.
- return:
An iterator over the objects in this collection.
-
inline virtual iterator end()
Get the non-const iterator past the end of the collection
- Returns:
An iterator base the end of this collection.
-
inline virtual const_iterator cbegin() const
Get the const iterator to the beginning of the collection.
- Returns:
An iterator over the objects in this collection.
-
inline virtual const_iterator cend() const
Get the const iterator past the end of the collection
- Returns:
An iterator base the end of this collection.