Доступ к итераторам std :: map внутри цикла на основе диапазона, например for_each

Только что испытал это.

Чтобы заставить его работать с помощью: (это можно поместить в статическом блочном intializer)

static{ // would have to be surrounded by try catch
    Class.forName("com.mysql.jdbc.Driver");   // this will load the class Driver
}

Также, получив соединение через:

conn = DriverManager.getConnection(DBURL,<username>,<password>);

вместо указания параметров входа

  Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/projects?user=user1&password=123");

С уважением.

0
задан Mandeep Singh 13 July 2018 в 14:40
поделиться

2 ответа

Оба цикла на основе диапазона и std::foreach предназначены для обработки элементов самостоятельно, независимо от других. Если вам нужен итератор для других элементов, вам нужно явно указать его:

auto next = infoMap.begin();
for(auto& prev: infoMap)
{
    ++next; // now points to element succeeding prev...
    if(next != infoMap.end())
    {
        // your code...
    }
}

Цикл, основанный на контуре, не выполняет итерацию в обратном порядке, но идея в конце одна и та же:

auto next = infoMap.rbegin(); 
std::for_each(infoMap.rbegin(), infoMap.rend(), [&infoMap, &next](auto& prev)
{
    ++next; // again one in advance compared to prev...
            // (other direction than in above loop, though!)
    if(next != infoMap.rend())
    {
        // your code...
    }
});

Я лично останусь с классическим циклом, хотя & ndash; это имеет то преимущество, что вы можете переместить if из него:

if(infoMap.size() >= 2)
{
    for (auto next = std::next(infoMap.rbegin()); next != infoMap.rend(); ++next)
    {
        prev = std::prev(next);
        // your code...
    }
}
0
ответ дан Aconcagua 17 August 2018 в 12:35
поделиться
template<class It>
struct range_t {
  It b, e;
  It begin() const { return b; }
  It end() const { return e; }
};
template<class It>
range_t<It> range( It s, It f ) { return {std::move(s), std::move(f)}; }

это минимальный тип для поддержки циклов for(:) в произвольных диапазонах.

Далее, что я называю индексированием iteroid:

template<class V>
struct indexing_iteroid {
  using self=indexing_iteroid;
  V value;

  // * just returns a copy of value
  V operator*() const& { return value; }
  V operator*()&&{ return std::move(value); }

  // ++ forwards to value:
  self& operator++() {
    ++value;
    return *this;
  }
  self operator++(int) {
    auto r = *this;
    ++*this;
    return r;
  }

  // == compares values:
  friend bool operator==(self const& lhs, self const& rhs) {
    return lhs.value == rhs.value;
  }
  friend bool operator!=(self const& lhs, self const& rhs) {
    return lhs.value != rhs.value;
  }
};

, если вы хотите вы можете распространить это на полноценный итератор ввода; Для этого, кроме того, для этого требуются резервные контейнеры.

Но этот итерайд достаточно хорош для петель for(:), которые не указаны в терминах категорий итераторов, а скорее конкретных операций.

template<class It>
range_t< indexing_iterator<It> > index_over_range( range_t<It> r ) {
  return {{r.begin()}, {r.end()}};
}

это принимает диапазон и создает диапазон над итераторами в нем.

for (auto it : index_over_range( range( infoMap.begin(), infoMap.end() ) ) )
{
}

теперь это for(:) цикл, который посещает каждый итератор в infoMap , а не каждый элемент из infoMap.

Мы можем немного почистить это с большим количеством шаблонов

namespace adl {
  namespace it_details {
    using std::begin; using std::end;
    template<class X>
    auto adl_begin( X&& x )
    -> decltype( begin( std::forward<X>(x) ) )
    { return begin( std::forward<X>(x) ); }
    template<class X>
    auto adl_end( X&& x )
    -> decltype( end( std::forward<X>(x) ) )
    { return end( std::forward<X>(x) ); }
  }
  template<class X>
  auto begin( X&& x )
  -> decltype( it_details::adl_begin( std::forward<X>(x) ) )
  { return it_details::adl_begin( std::forward<X>(x) ); }
  template<class X>
  auto end( X&& x )
  -> decltype( it_details::adl_end( std::forward<X>(x) ) )
  { return it_details::adl_end( std::forward<X>(x) ); }
}

, это дает adl::begin( x ) ( и adl::end( x )), который вызывает begin в x в контексте, где std::begin доступен, но так же зависит от поиска по запросу begin. Это почти идеально соответствует тому, как петли for(:) находят свои итераторы начала и конца.

template<class C>
auto iterators_of( C& c )
-> decltype( index_over_range( range( adl::begin(c), adl::end(c) ) ) )
{ return index_over_range( range( adl::begin(c), adl::end(c) ) ); }

теперь iterators_of(someMap) возвращает диапазон всех итераторов в someMap:

for (auto it : iterators_of( infoMap ) )
{
}

, и у нас есть хороший, чистый эффективный синтаксис.

Как в стороне, indexing_iteroid можно также использовать для создания итерации счетчика (так что для цикла для 0, 1, 2, 3), например:

using counting_iteroid = indexing_iteroid<std::size_t>;
auto zero_to_ten = range( counting_iteroid{0}, counting_iteroid{11} );
for (auto x : zero_to_ten) {
   std::cout << x << "\n";
}

выше, вероятно, имеет некоторые опечатки.

Существует категория типов, для которой indexing_iteroid может быть обернута; как целые числа, так и итераторы передают эту концепцию. Вы можете улучшить indexing_iteroid, чтобы быть ближе к случайному доступу, но из-за недостатков в том, как стандартизована концепция итератора произвольного доступа, он не позволяет вам достичь более высокой категории итераторов ввода итератора. 'Rangesv3 может исправить это.

0
ответ дан Yakk - Adam Nevraumont 17 August 2018 в 12:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: