I have an STL-style iterator on a template sparse matrix class I wrote, YaleStorage<D>
. I have written an operator==
for the matrix class which allows for two matrices to be compared for which D
may differ.
My iterators are also templates -- so I can have const_iterator
and iterator
as specializations of iterator_T<RefType>
, where RefType
may be either const D&
or D&
.
I need these iterators to be comparable even when D
differs. I don't particularly need constness to differ (a const_iterator
does not need to be compared to an iterator
). Here's how I wrote the operator!=
and such:
template <typename D>
class YaleStorage {
template <typename RefType>
class iterator_T {
template <typename E, typename ERefType = typename enable_if_else<std::is_const<RefType>::value, const E&, E&>::type>
bool operator!=(const typename YaleStorage<E>::template stored_diagonal_iterator_T<ERefType>& rhs) const { /* some comparison code */ }
};
typedef iterator_T<D&> iterator;
typedef iterator_T<const D&> const_iterator;
const_iterator cbegin() const { /* returns a const_iterator */ }
const_iterator cend() const { /* returns the end const_iterator */ }
};
Note that I wrote my own enable_if_else
, since I couldn't find a similar function in the STL. Here is that:
template <bool B, typename TA, typename TB>
struct enable_if_else {};
template <typename TA, typename TB>
struct enable_if_else<true, TA, TB> { typedef TA type; };
template <typename TA, typename TB>
struct enable_if_else<false, TA, TB> { typedef TB type; };
Unfortunately, when I try to do a regular iterator comparison (where D=E
), I get a whole raft of errors, such as:
compiling ../../../../ext/nmatrix/storage/yale.cpp
../../../../ext/nmatrix/storage/yale.cpp: In instantiation of ‘VALUE nm::yale_storage::each_stored_with_indices(VALUE) [with DType = unsigned char; VALUE = long unsigned int]’:
../../../../ext/nmatrix/storage/yale.cpp:1686:3: required from here
../../../../ext/nmatrix/storage/yale.cpp:1567:83: error: no match for ‘operator!=’ in ‘d != nm::YaleStorage<D>::cend() const [with D = unsigned char; nm::YaleStorage<D>::const_iterator = nm::YaleStorage<unsigned char>::iterator_T<const unsigned char&>]()’
../../../../ext/nmatrix/storage/yale.cpp:1567:83: note: candidates are:
In file included from ../../../../ext/nmatrix/storage/yale.cpp:64:0:
../../../../ext/nmatrix/storage/yale.h:438:10: note: template<class E, class ERefType> bool nm::YaleStorage<D>::iterator_T::operator!=(const typename nm::YaleStorage<E>::iterator_T<ERefType>&) const [with E = E; ERefType = ERefType; RefType = const unsigned char&; D = unsigned char]
../../../../ext/nmatrix/storage/yale.h:438:10: note: template argument deduction/substitution failed:
../../../../ext/nmatrix/storage/yale.cpp:1567:83: note: couldn't deduce template parameter ‘E’
I've tried explicitly casting the result of cend()
so it knows what's on both sides of the comparison, but I can't see why it'd choke on this.
template <typename DType>
static VALUE each_with_indices(VALUE nm) {
YaleStorage<DType> y(s);
// The next line is 1567:
for (typename YaleStorage<DType>::const_iterator d = y.cbegin(); d != y.cend()); ++d) {
/* Do some stuff with d */
}
}
I know how to explicitly specify template parameters for non-operator
functions, but how do I do it for operators? Is there another, better approach? It seems to me that it should be obvious to the compiler what E
is here.