У меня есть шаблонный класс myClass
, которому принадлежит экземпляр std::vector
, и я перегрузил оператор []
, чтобы принять в качестве аргумента std::vector<int>
индексов вектора-члена и вернуть вторичный класс mySubset
.
template <typename _type>
class myClass {
// ...
std::vector<_type> data;
// ...
class mySubset {
myClass<_type>* mc;
const std::vector<int>::iterator &idx;
public:
//constructor
mySubset(myClass<_type> * _m, const std::vector<int>& _idx);
// input operator overloads (for data and range input)
template <typename _input_type> mySubset& operator=(const std::vector<_input_type>& _vals);
mySubset& operator=(const mySubset& _sbst);
};
public:
myClass();
~myClass();
// ...
//acess operator
mySubset operator[](const std::vector<int>& _idx) { return mySubset(_idx); };
// ...
//iterator
typename std::vector<_type>::iterator begin() {return data.begin();};
typename std::vector<_type>::iterator end(); {return data.end(); };
// ...
}
Я могу получать и устанавливать значения напрямую с помощью оператора []
, но я хотел бы иметь возможность использовать циклы на основе диапазонов, например
// ...
myClass<float> foo;
// ...
std::vector<int> indices (3);
indices[0] = 3;
indices[1] = 6;
indices[2] = 10;
// ...
foo[indices] = std::vector<float> (3, 0.47);
for (auto& fval : foo[indices]) { /* do stuff*/}
Из того, что я собрал, мне понадобится advance( InputIt& it, Distance n );
для достижения того, что я хочу, и добавить члены begin()
и end()
в mySubset
, которые возвращают объект типа итератора с оператором ++
, увеличивающим итератор, глядя на вектор индекса:
class myIterator {
mySubset * sb;
std::vector<_type> it; // myClass::data iterator
public:
myIterator(mySubset * _sb, int pos): sb(_sb) { it = sb->mc->data.begin() + sb->idx[0]; } ;
myIterator& operator++() { };
myIterator& operator!=(myIterator& _other) { };
};
//.. mySubset
myIterator begin();
myIterator end();
Но на данный момент мне сложно понять, какой фактический синтаксис требуется для этого?
Я буду ленивым.
Пойдите и внедрите _type& operator[](size_t)
и .size()
на mySubset
.
template<class C>
struct range_for_helper{
using self=range_for_helper;
C* c=0;
std::size_t i = 0;
self(C* cin, std::size_t idx):c(cin),i(idx){}
friend bool operator==(self lhs, self rhs){return lhs.i==rhs.i;}
friend bool operator!=(self lhs, self rhs){return lhs.i!=rhs.i;}
void operator++(){++i;}
decltype(auto) operator*(){ return (*c)[i]; }
};
Затем добавьте
на mySubset
и готово.
Это не настоящий итератор, но его достаточно для циклов for(:)
. Его можно расширить до настоящего итератора, как я уже сказал, ленивого.
Также :
range_for_helper<mySubset> begin() const { return {this,0}; }
range_for_helper<mySubset> end() const { return {this,size()}; }
просто работает, если ваш []
перегружен для const
, так что это хорошо.
@joaocandre Во-первых, const std::vector<int>::iterator & idx
избавься от const&
там. Не существует способа, которым можно было бы определить поведение на практике; вы передаете вектор в ctor, возможно, вызываете begin, этот начальный итератор истекает, когда ctor завершен. Во-вторых, очевидно, что вы можете получить n-й элемент, это то, что должен делать ваш operator=
. В-третьих, (mc-> data)[idx[i]]
.
"этот начальный итератор истекает, когда ctor завершен" ну, это имеет смысл, и я не знал об этом. Кроме того, я рассматривал i
как фиксированный размер вектора индекса вместо индекса Текущий.
Достаточно справедливо, кажется, достаточно простое решение. Однако как именно
_type& operator[](size_t)
должен возвращать значение данных из размера вектора индекса?