Сообщение Re: про итераторы от 27.03.2020 13:26
Изменено 27.03.2020 13:38 rg45
Re: про итераторы
Здравствуйте, qaz77, Вы писали:
Q>Делаю STL-совместимый самодельный контейнер, который обертка над стандартными контейнерами.
Q>Соответственно, потребовались iterator и const_iterator.
Q>Вопрос про то, как лучше/удобнее реализовать эту парочку, с минимумом копипасты и односторонней заменяемости от iterator к const_iterator.
Q>Что-то я не нашел гайдлайнов для такой задачи...
Я вот здесь набросал простейший proof-of-concept контейнера-враппера для std::vector и враппера для итераторов с использованием boost::iterator_adaptor. Как видишь, все, что потребовалось — это один единственный дополнительный конструктор. Даже операторы сравнения и вычитания не пришлось определять самому:
http://coliru.stacked-crooked.com/a/bfbaf2d3bd65bbd2
Q>Делаю STL-совместимый самодельный контейнер, который обертка над стандартными контейнерами.
Q>Соответственно, потребовались iterator и const_iterator.
Q>Вопрос про то, как лучше/удобнее реализовать эту парочку, с минимумом копипасты и односторонней заменяемости от iterator к const_iterator.
Q>Что-то я не нашел гайдлайнов для такой задачи...
Я вот здесь набросал простейший proof-of-concept контейнера-враппера для std::vector и враппера для итераторов с использованием boost::iterator_adaptor. Как видишь, все, что потребовалось — это один единственный дополнительный конструктор. Даже операторы сравнения и вычитания не пришлось определять самому:
http://coliru.stacked-crooked.com/a/bfbaf2d3bd65bbd2
#include <iostream>
#include <vector>
#include <boost/iterator/iterator_adaptor.hpp>
template <typename BaseIteratorT>
class MyIteratorBase
: public boost::iterator_adaptor<MyIteratorBase<BaseIteratorT>, BaseIteratorT>
{
using iterator_adaptor = boost::iterator_adaptor<MyIteratorBase<BaseIteratorT>, BaseIteratorT>;
public:
using iterator_adaptor::iterator_adaptor;
MyIteratorBase() = default;
template <typename U>
MyIteratorBase(const MyIteratorBase<U>& rhs) : iterator_adaptor(rhs.base()) {}
};
template <typename T>
class MyVector
{
public:
using iterator = MyIteratorBase<typename std::vector<T>::iterator>;
using const_iterator = MyIteratorBase<typename std::vector<T>::const_iterator>;
MyVector() = default;
MyVector(std::initializer_list<T> l) : m_v{l} {}
iterator begin() { return iterator(m_v.begin()); }
iterator end() { return iterator(m_v.end()); }
const_iterator begin() const { return const_iterator(m_v.begin()); }
const_iterator end() const { return const_iterator(m_v.end()); }
private:
std::vector<T> m_v;
};
int main() {
MyVector<int> my_v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (const auto& e : my_v)
{
std::cout << " " << e;
}
std::cout << std::endl;
MyVector<int>::iterator begin = my_v.begin();
MyVector<int>::const_iterator end = my_v.end();
std::cout << std::boolalpha;
std::cout << (begin == end) << std::endl; // false
std::cout << (begin != end) << std::endl; // true
std::cout << (begin <= end) << std::endl; // true
std::cout << (end - begin) << std::endl; // 10
}
Re: про итераторы
Здравствуйте, qaz77, Вы писали:
Q>Делаю STL-совместимый самодельный контейнер, который обертка над стандартными контейнерами.
Q>Соответственно, потребовались iterator и const_iterator.
Q>Вопрос про то, как лучше/удобнее реализовать эту парочку, с минимумом копипасты и односторонней заменяемости от iterator к const_iterator.
Q>Что-то я не нашел гайдлайнов для такой задачи...
Я вот здесь набросал простейший proof-of-concept контейнера-враппера для std::vector и враппера для итераторов с использованием boost::iterator_adaptor. Как видишь, все, что потребовалось — это один единственный дополнительный конструктор. Даже операторы сравнения и вычитания не пришлось определять самому:
http://coliru.stacked-crooked.com/a/dcd22f47ba5d7da7
Q>Делаю STL-совместимый самодельный контейнер, который обертка над стандартными контейнерами.
Q>Соответственно, потребовались iterator и const_iterator.
Q>Вопрос про то, как лучше/удобнее реализовать эту парочку, с минимумом копипасты и односторонней заменяемости от iterator к const_iterator.
Q>Что-то я не нашел гайдлайнов для такой задачи...
Я вот здесь набросал простейший proof-of-concept контейнера-враппера для std::vector и враппера для итераторов с использованием boost::iterator_adaptor. Как видишь, все, что потребовалось — это один единственный дополнительный конструктор. Даже операторы сравнения и вычитания не пришлось определять самому:
http://coliru.stacked-crooked.com/a/dcd22f47ba5d7da7
#include <iostream>
#include <vector>
#include <boost/iterator/iterator_adaptor.hpp>
template <typename BaseIteratorT>
class MyIterator
: public boost::iterator_adaptor<MyIterator<BaseIteratorT>, BaseIteratorT>
{
using iterator_adaptor = boost::iterator_adaptor<MyIterator<BaseIteratorT>, BaseIteratorT>;
public:
using iterator_adaptor::iterator_adaptor;
MyIterator() = default;
template <typename U>
MyIterator(const MyIterator<U>& rhs) : iterator_adaptor(rhs.base()) {}
};
template <typename T>
class MyVector
{
public:
using iterator = MyIterator<typename std::vector<T>::iterator>;
using const_iterator = MyIterator<typename std::vector<T>::const_iterator>;
MyVector() = default;
MyVector(std::initializer_list<T> l) : m_v{l} {}
iterator begin() { return iterator(m_v.begin()); }
iterator end() { return iterator(m_v.end()); }
const_iterator begin() const { return const_iterator(m_v.begin()); }
const_iterator end() const { return const_iterator(m_v.end()); }
private:
std::vector<T> m_v;
};
int main() {
MyVector<int> my_v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (const auto& e : my_v)
{
std::cout << " " << e;
}
std::cout << std::endl;
MyVector<int>::iterator begin = my_v.begin();
MyVector<int>::const_iterator end = my_v.end();
std::cout << std::boolalpha;
std::cout << (begin == end) << std::endl; // false
std::cout << (begin != end) << std::endl; // true
std::cout << (begin <= end) << std::endl; // true
std::cout << (end - begin) << std::endl; // 10
}