I already use llvm::zip with std containers and I’m now trying to use it on some custom classes & iterators, but I’m encountering a compilation error that I can’t manage to solve.
This is the sample class and iterator (it’s a very stupid example, just to show the problem):
template<typename T>
class MyIterator;
template<typename T>
struct MyClass
{
using iterator = MyIterator<T>;
MyClass(std::initializer_list<T> data) : data(data) {}
T& operator[](int pos) { return data[pos]; }
iterator begin() { return { *this, 0 }; }
iterator end() { return { *this, -1 }; }
private:
llvm::SmallVector<T, 3> data;
};
template<typename T>
class MyIterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
MyIterator(MyClass<T> cls, int pos) : cls(cls), pos(pos) {
}
MyIterator<T>& operator++() {
pos++;
return *this;
}
T& operator*() { cls[pos]; }
T& operator*() const { return cls[pos]; }
T* operator->() { return &cls[pos]; }
T* operator->() const { return &cls[pos]; }
bool operator==(const MyIterator& other) const {
return pos == other.pos;
}
bool operator!=(const MyIterator& other) const {
return *this != other;
}
private:
MyClass<T>& cls;
nt pos;
};
If I try to iterate, the compilation fails on STLExtras.h : 652, that is when is trying to use the = operator from std::tuple.
MyClass a({ 1, 2, 3 });
MyClass b({ 4, 5, 6 });
for (auto pair : llvm::zip(a, b)) // fail
{ }
Using auto& / const auto& doesn’t solve the issue.
/mnt/c/llvm/debug/include/llvm/ADT/STLExtras.h: In instantiation of ‘ZipType& llvm::detail::zip_common<ZipType, Iters>::operator++() [with ZipType = llvm::detail::zip_shortest<MyIterator<int>, MyIterator<int> >; Iters = {MyIterator<int>, MyIterator<int>}]’:
../lib/mlirlowerer/test/src/MathOpsTest.cpp:126:40: required from here
/mnt/c/llvm/debug/include/llvm/ADT/STLExtras.h:652:15: error: use of deleted function ‘std::tuple<MyIterator<int>, MyIterator<int> >& std::tuple<MyIterator<int>, MyIterator<int> >::operator=(const std::tuple<MyIterator<int>, MyIterator<int> >&)’
...
/usr/include/c++/9/tuple:893:11: note: ‘std::tuple<MyIterator<int>, :MyIterator<int> >& std::tuple<:MyIterator<int>, MyIterator<int> >::operator=(const std::tuple<MyIterator<int>, MyIterator<int> >&)’ is implicitly declared as deleted because ‘std::tuple<MyIterator<int>, MyIterator<int> >’ declares a move constructor or move assignment operator
893 | class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
| ^~~~~~~~~~~~~~~
Am I missing something in the iterator definition?