如何解决std :: find无法使用自定义迭代器进行编译
我发现了一个experimental circular buffer implementation的迭代器,看起来像这样:
struct my_iterator
{
using iterator_category = std::random_access_iterator_tag;
using difference_type = long long;
using reference = typename std::conditional_t< isconst,T const &,T & >;
using pointer = typename std::conditional_t< isconst,T const *,T * >;
using vec_pointer = typename std::conditional_t<isconst,std::vector<T> const *,std::vector<T> *>;
...
pointer operator->() { return &(operator *()); }
my_iterator& operator++ ()
{
++index;
return *this;
};
my_iterator operator ++(int)
{
my_iterator iter = *this;
++index;
return iter;
}
...
};
迭代器的实现有些奇怪,但至少它可用于基于范围的循环。唯一的问题是它不能与std::find
一起编译:
ring<int> mybuf(10);
auto i = std::find(mybuf.begin(),mybuf.end(),100);
/usr/include/c++/9/bits/stl_algo.h: In instantiation of ‘_Iterator std::__find_if(_Iterator,_Iterator,_Predicate) [with _Iterator = ring<int>::my_iterator<false>; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const int>]’:
/usr/include/c++/9/bits/stl_algo.h:3938:28: required from ‘_IIter std::find(_IIter,_IIter,const _Tp&) [with _IIter = ring<int>::my_iterator<false>; _Tp = int]’
/home/def/repos/Awl/Tests/RingTest.cpp:71:60: required from here
/usr/include/c++/9/bits/stl_algo.h:162:34: error: no matching function for call to ‘__iterator_category(ring<int>::my_iterator<false>&)’
162 | std::__iterator_category(__first));
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/usr/include/c++/9/bits/stl_iterator_base_types.h:205:5: note: candidate: ‘template<class _Iter> constexpr typename std::iterator_traits<_Iterator>::iterator_category std::__iterator_category(const _Iter&)’
205 | __iterator_category(const _Iter&)
这与iterator_category
有关,但不清楚它有什么问题。
EDIT1:
完整源代码:
#include <stdexcept>
#include <cassert>
#include <vector>
#include <initializer_list>
template <class T>
class ring
{
using value_type = T;
using reference = T & ;
using const_reference = const T &;
using size_type = size_t;
using circularBuffer = std::vector<value_type>;
circularBuffer m_array;
size_type m_head;
size_type m_tail;
size_type m_contents_size;
size_type m_array_size;
template <bool isconst> struct my_iterator;
public:
ring(size_type size) :
m_array(size),m_array_size(size),m_head(1),m_tail(0),m_contents_size(0)
{
assert(m_array_size > 1 && "size must be greater than 1");
}
ring(std::initializer_list<T> l) :
m_array(l),m_array_size(l.size()),m_head(0),m_tail(l.size() - 1),m_contents_size(l.size())
{
assert(m_array_size > 1 && "size must be greater than 1");
}
reference front() { return m_array[m_head]; }
reference top() { return front(); }
reference back() { return m_array[m_tail]; }
const_reference front() const { return m_array[m_head]; }
const_reference back() const { return m_array[m_tail]; }
void clear();
void push_back(const value_type &item);
void push(const value_type &item) { push_back(item); }
void pop_front() { increment_head(); }
void pop() { pop_front(); }
size_type size() const { return m_contents_size; }
size_type capacity() const { return m_array_size; }
bool empty() const;
bool full() const;
size_type max_size() const { return size_type(-1) / sizeof(value_type); }
reference operator[](size_type index);
const_reference operator[](size_type index) const;
reference at(size_type index);
const_reference at(size_type index) const;
using iterator = my_iterator<false>;
using const_iterator = my_iterator<true>;
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const;
iterator rbegin();
const_iterator rbegin() const;
iterator end();
const_iterator end() const;
const_iterator cend() const;
iterator rend();
const_iterator rend() const;
private:
void increment_tail();
void increment_head();
template <bool isconst = false>
struct my_iterator
{
using iterator_category = std::random_access_iterator_tag;
using difference_type = long long;
using reference = typename std::conditional_t< isconst,std::vector<T> *>;
private:
vec_pointer ptrToBuffer;
size_type offset;
size_type index;
bool reverse;
bool comparable(const my_iterator & other) {
return (reverse == other.reverse);
}
public:
my_iterator() : ptrToBuffer(nullptr),offset(0),index(0),reverse(false) {} //
my_iterator(const ring<T>::my_iterator<false>& i) :
ptrToBuffer(i.ptrToBuffer),offset(i.offset),index(i.index),reverse(i.reverse) {}
reference operator*() {
if (reverse)
return (*ptrToBuffer)[(ptrToBuffer->size() + offset - index) % (ptrToBuffer->size())];
return (*ptrToBuffer)[(offset + index) % (ptrToBuffer->size())];
}
reference operator[](size_type index) {
my_iterator iter = *this;
iter.index += index;
return *iter;
}
pointer operator->() { return &(operator *()); }
my_iterator& operator++ ()
{
++index;
return *this;
};
my_iterator operator ++(int)
{
my_iterator iter = *this;
++index;
return iter;
}
my_iterator& operator --()
{
--index;
return *this;
}
my_iterator operator --(int) {
my_iterator iter = *this;
--index;
return iter;
}
friend my_iterator operator+(my_iterator lhs,int rhs) {
lhs.index += rhs;
return lhs;
}
friend my_iterator operator+(int lhs,my_iterator rhs) {
rhs.index += lhs;
return rhs;
}
my_iterator& operator+=(int n) {
index += n;
return *this;
}
friend my_iterator operator-(my_iterator lhs,int rhs) {
lhs.index -= rhs;
return lhs;
}
friend difference_type operator-(const my_iterator& lhs,const my_iterator& rhs) {
lhs.index -= rhs;
return lhs.index - rhs.index;
}
my_iterator& operator-=(int n) {
index -= n;
return *this;
}
bool operator==(const my_iterator &other)
{
if (comparable(other))
return (index + offset == other.index + other.offset);
return false;
}
bool operator!=(const my_iterator &other)
{
if (comparable(other)) return !this->operator==(other);
return true;
}
bool operator<(const my_iterator &other)
{
if (comparable(other))
return (index + offset < other.index + other.offset);
return false;
}
bool operator<=(const my_iterator &other)
{
if (comparable(other))
return (index + offset <= other.index + other.offset);
return false;
}
bool operator >(const my_iterator &other)
{
if (comparable(other)) return !this->operator<=(other);
return false;
}
bool operator>=(const my_iterator &other)
{
if (comparable(other)) return !this->operator<(other);
return false;
}
friend class ring<T>;
};
};
template<class T>
void ring<T>::push_back(const value_type & item)
{
increment_tail();
if (m_contents_size > m_array_size) increment_head(); // > full,== comma
m_array[m_tail] = item;
}
template<class T>
void ring<T>::clear()
{
m_head = 1;
m_tail = m_contents_size = 0;
}
template<class T>
bool ring<T>::empty() const
{
if (m_contents_size == 0) return true;
return false;
}
template<class T>
inline bool ring<T>::full() const
{
if (m_contents_size == m_array_size) return true;
return false;
}
template<class T>
typename ring<T>::const_reference ring<T>::operator[](size_type index) const
{
index += m_head;
index %= m_array_size;
return m_array[index];
}
template<class T>
typename ring<T>::reference ring<T>::operator[](size_type index)
{
const ring<T>& constMe = *this;
return const_cast<reference>(constMe.operator[](index));
// return const_cast<reference>(static_cast<const ring<T>&>(*this)[index]);
}
//*/
template<class T>
typename ring<T>::reference ring<T>::at(size_type index)
{
if (index < m_contents_size) return this->operator[](index);
throw std::out_of_range("index too large");
}
template<class T>
typename ring<T>::const_reference ring<T>::at(size_type index) const
{
if (index < m_contents_size) return this->operator[](index);
throw std::out_of_range("index too large");
}
template<class T>
typename ring<T>::iterator ring<T>::begin()
{
iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = 0;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::begin() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = 0;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::cbegin() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = 0;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::iterator ring<T>::rbegin()
{
iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_tail;
iter.index = 0;
iter.reverse = true;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::rbegin() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_tail;
iter.index = 0;
iter.reverse = true;
return iter;
}
template<class T>
typename ring<T>::iterator ring<T>::end()
{
iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = m_contents_size;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::end() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = m_contents_size;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::cend() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_head;
iter.index = m_contents_size;
iter.reverse = false;
return iter;
}
template<class T>
typename ring<T>::iterator ring<T>::rend()
{
iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_tail;
iter.index = m_contents_size;
iter.reverse = true;
return iter;
}
template<class T>
typename ring<T>::const_iterator ring<T>::rend() const
{
const_iterator iter;
iter.ptrToBuffer = &m_array;
iter.offset = m_tail;
iter.index = m_contents_size;
iter.reverse = true;
return iter;
}
template<class T>
void ring<T>::increment_tail()
{
++m_tail;
++m_contents_size;
if (m_tail == m_array_size) m_tail = 0;
}
template<class T>
void ring<T>::increment_head()
{
if (m_contents_size == 0) return;
++m_head;
--m_contents_size;
if (m_head == m_array_size) m_head = 0;
}
int main()
{
ring<int> mybuf(10);
auto i = std::find(mybuf.begin(),100);
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。