Transposer and Indexer are implemented in such a way that a partial template specialization is provided for each possible RANK
(up to BLITZ_ARRAY_LARGEST_RANK), and the corresponding code is automatically generated by the Boost.Preprocessor library. This can be seen in the trailing part of BlitzArraySliceIterator.tcc. To actually see what code is generated, this file needs to be preprocessed. Issue the following command from the root directory of the distribution:
~~~ To store and manipulate the heterogenous collection of slicing indices like 0,a,2,a,4,5,a,a,8,a,10
in Indexer::index, the vector
class of the Boost.Fusion library is used.
Iterator is implemented in terms of the above two helper classes. Each Iterator invokes a Transposer::transpose at its construction, and – if RANK
is larger than Size<V>::value
– an Indexer::index @ the point of its dereferencing when the actual slicing occurs.
Iterator is a forward iterator, implemented with the help of forward_iterator_helper
from Boost.Operator. For this to work, we need to define only 3 operations:
V
equals RANK
because in this case actually no slicing takes place, only transposition. For this, as at several other places in the framework, we apply conditional inheritance: Iterator inherits from either of two classes (details::Base or details::BaseSpecial), the decision being made @ compile time with the help of boost::mpl::if_c
.The iteration over dummy indices is implemented with the help of cpputils::MultiIndexIterator.
In the following we analyse a metaprogramming example typical for the framework: how the compile-time vector 0,3,2,6,4,5,1,9,8,7,10
for the self-transposition in Transposer::transpose is prepared.
This is done by the following snippet in utils/BlitzArraySliceIterator.tcc
:
fold
metaalgorithm from Boost.MPL. Here, it iterates over the sequence of ordinals (tmptools::Ordinals) between 0
and RANK-1
. V
. These two are “zipped” into a compile-time pair. At the end, the first element of this pair will hold the result.
The rest expresses the forward operation of the fold algorithm in the form of a compile-time lambda expression. After each step, the new state will again be a pair composed of
V
pointed to by the iterator (Line 13), or the current ordinal (Line 14), depending on whether V
tmptools::numerical_contains this ordinal.