stl — C ++ итератор для std :: set или std :: vector

Допустим, у меня есть это:

struct HoldStuff {
std::vector<StuffItem> items;
std::set<StuffItem, StuffItemComparator> sorted_items;
}

Теперь, во время рефакторинга, у меня могут быть вещи в items или я могу иметь это в sorted_items, но независимо от того, что я хочу сделать то же самое с каждым элементом. Я хочу сделать что-то вроде этого:

HoldStuff holder;  // assume it was filled earlier
auto iter = holder.items.empty() ? holder.sorted_items.begin() :
holder.items.begin();
auto iter_end = holder.items.empty() ? holder.sorted_items.end() :
holder.items.end();
for (; iter != iter_end; ++iter) {
auto& item = *iter;
// Do stuff
}

Когда я собираюсь скомпилировать это, я получаю сообщения об ошибках несовместимых типов операндов. Конечно, это возможно, нет?

0

Решение

У вас есть два варианта:

  • используйте тип-стирание, чтобы получить полиморфизм времени выполнения на итераторе (any_range или же any_iterator)
  • делегат do_stuff в шаблон функции, который принимает любой вид итератора

Вот иллюстрация с кодом:

#include <vector>
#include <set>
#include <iostream>

#include <boost/range/any_range.hpp>

template<typename Iterator>
void do_stuff(Iterator begin, Iterator end) {}

int main()
{
std::vector<int> items;
std::set<int> sorted_items;
// first option
typedef boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> my_any_range;
my_any_range r;
if(items.empty())
r = my_any_range(sorted_items);
else
r = my_any_range(items);
for (auto& x : r) {
std::cout << x << " ";
}

// second option
// this could also be a lambda and std::for_each
if(items.empty())
do_stuff(sorted_items.begin(), sorted_items.end());
else
do_stuff(items.begin(), items.end());
return 0;
}
1

Другие решения

Обе стороны троичного оператора должны иметь одинаковый тип. В вашем случае они разные — std :: vector<> :: iterator и std :: set<> Итератор. Подходящим решением, похоже, является своего рода обертка итератора, которая возвращает то или иное в зависимости от начального условия.

0

Ошибки верны: авто Ключевое слово работает во время компиляции. Проще говоря, он просто выводит тип назначения и использует это реальный тип. Но решение, является ли он векторным итератором или множеством, принимается во время выполнения. Так что типа нельзя вывести.

Как сказал SergeyA, я здесь не прав, сбой компилятора?: Оператор, до auto. Но причина все та же — он не знает, какой тип использовать для результата.

Возможно, вам следует использовать более общий тип итератора + полиморфизм, или вы можете сделать эту функцию параметризованной по типу, где T — это тип итератора. Я бы предпочел сделать это так:

template<class T> do_stuff(T &c) {  for (auto &el : c) { /*Whatever*/ } }

...

if (!items.empty()) {
do_stuff(items);
} else if (!sorted_items.empty()) {
do_stuff(sorted_items);
}

П.С .: Это концепция, я не тестировал код.

0

auto означает компилятор выведет тип того, что следует, во время компиляции.

Тип возврата тернарного условного оператора в данном случае следующий за знаком вопроса, поэтому std::set<StuffItem, StuffItemComparator>::iterator и компилятор пытается привести то, что следует за столбцом (std::vector<StuffItem>::iterator) к этому несовместимому типу, следовательно ошибка компилятора.

То, что вы можете сделать, это сделать ваш код обработки элементов универсальным, например, так:

auto doStuff = [] (StuffItem& item) {
// do stuff with item...
};
if( holder.items.size() )
for_each( holder.items.begin(), holder.items.end(), doStuff );
else if( holder.sorted_items.size() )
for_each( holder.sorted_items.begin(), holder.sorted_items.end(), doStuff );
0
По вопросам рекламы [email protected]