Только что испытал это.
Чтобы заставить его работать с помощью: (это можно поместить в статическом блочном 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");
С уважением.
Оба цикла на основе диапазона и 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...
}
}
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
, чтобы быть ближе к случайному доступу, но из-за недостатков в том, как стандартизована концепция итератора произвольного доступа, он не позволяет вам достичь более высокой категории итераторов ввода итератора. c ++ 2a 'Rangesv3 может исправить это.