bnmf-algs
Public Member Functions | List of all members
bnmf_algs::util::ComputationIterator< T, Computer > Class Template Reference

A template iterator that generates values via computation using the previous value. More...

#include <generator.hpp>

Inheritance diagram for bnmf_algs::util::ComputationIterator< T, Computer >:
std::iterator< std::forward_iterator_tag, T >

Public Member Functions

 ComputationIterator (T *init_val_ptr, size_t *step_count_ptr, Computer *computer_ptr)
 ComputationIterator constructor that takes pointers for initial value, current step count and the computer. More...
 
 ComputationIterator (size_t *step_count_ptr)
 ComputationIterator constructor that takes a pointer for the current step only. More...
 
ComputationIteratoroperator++ ()
 Pre-increment operator that computes the next value of the computation and updates step_count and curr_val. More...
 
const T & operator* () const
 Dereference operator to the get a const reference to the most recently computed value. More...
 
const T * operator-> () const
 Member access operator to access the members of the most recently computed value. More...
 
bool operator== (const ComputationIterator &other) const
 Equality operator. More...
 
bool operator!= (const ComputationIterator &other) const
 Inquality operator. More...
 

Detailed Description

template<typename T, typename Computer>
class bnmf_algs::util::ComputationIterator< T, Computer >

A template iterator that generates values via computation using the previous value.

ComputationIterator is a template class that can compute new values on-the-go by storing only the most recently computed value. The computation to perform at each step is taken as a constructor parameter and must be invokable (functions or functors).

After being constructed with an initial value, each call to pre-increment operator (++it) would compute the next value in-place (modify the previous value). Hence, prefix increment is an operation that mutates the actual computation results.

A call to dereference operator (*it) would return a const reference to the computed value.

Two ComputationIterator types can be compared using the inequality operator. Two ComputationIterator types are equal if they have been advanced the same number of times (number of operator++ invocations are the same).

ComputationIterator doesn't store any of the results by value itself. Instead, pointers to all the required variables are taken at construction time. Then, the values pointed by these pointers are updated. This is in line with pointer/iterator semantics in the sense that incrementing a copy of an iterator performs a step of the computation and updates the values pointed by the pointer variables. For example,

// Usual C++ iterators
std::vector<int> vec{1, 2, 3};
auto beg = vec.begin();
auto it = beg;
++(*beg);
// *it == 2
// ComputationIterator
int init = 0, beg_index = 0, end_index = 5;
Computer computer;
ComputationIterator<int, Computer> begin(&init, &beg_index, &computer);
ComputationIterator<int>, Computer end(&end_index);
auto it = beg;
++beg;
// *it has changed as well

Since ComputationIterator provides a similar API to STL ForwardIterator, it can be used with STL algorithms that only use the current value at a time and doesn't depend on any of the past values. For example, to transform a sequence of integers:

int init = 0, beg_index = 0, end_index = 5;
ComputationIterator<int, Computer> begin(&init, &beg_index, &computer);
ComputationIterator<int, Computer> end(&end_index);
std::vector<int> out(end_index);
std::transform(begin, end, out.begin(), multiply_by_2);
// out == {0, 2, 4, 6, 8}

However, it is not possible to use std::max_element since when an iterator it is incremented, the value pointed by the iterator is updated and all copies of it point to the updated value, as well. Fixing this issue would require actually storing the past values which is not the functionality provided by ComputationIterator whose main purpose is to store only the most recently computed value.

Given Computer type must have a

void operator()(size_t curr_step, T& prev_val);

call operator that will be called to update the previous value in-place. Example Computers for ComputationIterator<std::string, Computer> may be

void str_computer(size_t curr_step, std::string& prev_val) {
// modify prev_val in-place to compute next value
}

or

class StrComputer {
public:
void operator()(size_t curr_step, std::string& prev_val) {
// modify prev_val in-place to compute next_value
}
}

See bnmf_algs::util::Generator for an easier and more automatic API when dealing with generator expressions.

Template Parameters
TType of the resulting values of the computation that will be performed at each step.
ComputerType of the invocable computer object. May be a functor, std::function, function pointer and so on.

Constructor & Destructor Documentation

template<typename T, typename Computer>
bnmf_algs::util::ComputationIterator< T, Computer >::ComputationIterator ( T *  init_val_ptr,
size_t *  step_count_ptr,
Computer *  computer_ptr 
)
inline

ComputationIterator constructor that takes pointers for initial value, current step count and the computer.

The actual values pointed by init_val_ptr and step_count_ptr are updated at each call to prefix increment operator (++it). If the type pointed by computer_ptr is a functor and its call operator mutates the object, then the computer functor is modified as well.

Note that all the pointers must be valid before a call to any of the methods of ComputationIterator. Hence, making sure that these pointers are valid is up to the programmer.

Parameters
init_val_ptrPointer pointing to the initial value of the computation.
step_count_ptrPointer pointing to the step count of the computation.
computer_ptrPointer pointing to the computer function/functor.
template<typename T, typename Computer>
bnmf_algs::util::ComputationIterator< T, Computer >::ComputationIterator ( size_t *  step_count_ptr)
inlineexplicit

ComputationIterator constructor that takes a pointer for the current step only.

If increment or dereference operators are not going to be used by this iterator, giving only the current step count is enough. On the other hand, if a ComputationIterator constructor using this constructor calls increment or dereference operators, the resulting behaviour is undefined. (Dereference nullptr)

Parameters
step_count_ptrPointer pointing to the step count of the computation.

Member Function Documentation

template<typename T, typename Computer>
bool bnmf_algs::util::ComputationIterator< T, Computer >::operator!= ( const ComputationIterator< T, Computer > &  other) const
inline

Inquality operator.

Two ComputationIterator objects are not equal if their step counts are not equal. The values computed during computation are not compared during inequality testing.

Parameters
otherOther ComputationIterator object.
Returns
true if this ComputationIterator is not equal to the other.
template<typename T, typename Computer>
const T& bnmf_algs::util::ComputationIterator< T, Computer >::operator* ( ) const
inline

Dereference operator to the get a const reference to the most recently computed value.

Returns
const reference to the most recently computed value.
template<typename T, typename Computer>
ComputationIterator& bnmf_algs::util::ComputationIterator< T, Computer >::operator++ ( )
inline

Pre-increment operator that computes the next value of the computation and updates step_count and curr_val.

A call to operator++ computes the next value from the previous value and step count using the computer function/functor. After this function executes, the values pointed by step_count_ptr and curr_val_ptr is updated.

If a copy of an iterator calls operator++, then the values pointed by the original are updated as well (they point to the same values). For example,

// ComputationIterator
int init = 0, beg_index = 0, end_index = 5;
Op computer;
ComputationIterator<int, Op> begin(&init, &beg_index, &computer);
ComputationIterator<int, Op> end(&end_index);
auto it = beg;
++beg;
// *it has changed as well
Returns
Return a reference to the current ComputationIterator object.
template<typename T, typename Computer>
const T* bnmf_algs::util::ComputationIterator< T, Computer >::operator-> ( ) const
inline

Member access operator to access the members of the most recently computed value.

Returns
const pointer to the most recently computed value.
template<typename T, typename Computer>
bool bnmf_algs::util::ComputationIterator< T, Computer >::operator== ( const ComputationIterator< T, Computer > &  other) const
inline

Equality operator.

Two ComputationIterator objects are equal if their step counts are equal. The values computed during computation are not compared during equality testing.

Parameters
otherOther ComputationIterator object.
Returns
true if this ComputationIterator is equal to the other.

The documentation for this class was generated from the following file: