2017-01-12 3 views
0

Я хотел бы реализовать оператор над вектором, который пропускает определенное значение. Это то, что я написал, с этой проблемой я столкнулся комментировал:Выполнение приращения пропущенного итератора

template<class MyVector> 
struct VectorSkipConstIterator : MyVector::const_iterator { 
    using Base = typename MyVector::const_iterator; 
    using ValueType = typename MyVector::value_type; 

    VectorSkipConstIterator(const ValueType &skip) : Base(), skip_(skip){}; 
    VectorSkipConstIterator(Base it_, const ValueType &skip) 
     : Base(it_), skip_(skip){}; 

    VectorSkipConstIterator &operator++() { 
     do { 
      Base::operator++(); 
     } while (/* have not reached the end */ && this->operator*() == skip_); 
     return *this; 
    } 
private: 
    ValueType skip_; 
}; 

Таким образом, проблема заключается в том, что оператор ++ должна остановиться где-нибудь (а именно, в конце), даже если последнее значение (s) в векторе необходимо пропустить. Как это можно достичь?

+3

Обычно вы проверяете, находитесь ли вы в конце кода клиента, а не в итераторе. И наследование от итератора часто является плохим Idea ™, поскольку это может быть просто указатель. – TartanLlama

ответ

1

Один из возможных способов достижения этого - просто передать конечный итератор в качестве аргумента VectorSkipConstIterator и сохранить его в поле.

template<class MyVector> 
struct VectorSkipConstIterator : MyVector::const_iterator { 
    using Base = typename MyVector::const_iterator; 
    using ValueType = typename MyVector::value_type; 

    VectorSkipConstIterator(const ValueType &skip, Base end) 
     : Base(), skip_(skip){}, end_(end) 
    { 
    } 

    VectorSkipConstIterator(Base it_, const ValueType &skip, Base end) 
     : Base(it_), skip_(skip), end_(end) 
    { 
    } 

    VectorSkipConstIterator &operator++() { 
     do { 
      Base::operator++(); 
     } while (*this != end_ && this->operator*() == skip_); 
     return *this; 
    } 
private: 
    ValueType skip_; 
    Base end_; 
}; 

Как сказал в комментариях TartanLlama в комментариях, наследование от итератора - не очень хорошая идея. Подумайте о том, как реализовать свой собственный класс итератора с нуля, удовлетворяя концепции RandomAccessIterator.


Другой возможный (и, на мой взгляд, лучше) способ достижения того, что вы хотите это используя higher-order function:

template <typename TContainer, typename TSkip, typename TF> 
void forEachExcept(TContainer&& c, TSkip&& s, TF&& f) 
{ 
    for(auto&& x : c) 
    { 
     if(x != s) f(x); 
    } 
} 

Вы можете использовать его следующим образом:

std::vector<int> v{1,2,5,1,6,2,1}; 

// skip all occurrences of `1` 
forEachExcept(v, 1, [](auto x){ std::cout << x; }); 

// prints "2562" 
Смежные вопросы