for (set
setStrPtr.begin(); p != setStrPtr.end(); ++p)
cout << **p << endl; // Разыменовываем итератор и то, на что
// он указывает
}
strPtrLess
p1
, меньше, чем та, на которую указывает p2
. Это делает его двоичным предикатом, так как он принимает два аргумента и возвращает bool
. Так как operator<
определен для string
, для сравнения я использую именно его. На самом деле, если требуется использовать более общий подход, используйте для предиката сравнения шаблон классаtemplate
class ptrLess {
public:
bool operator()(const T* p1,
const T* p2) {
assert(p1 && p2);
return(*p1 < *p2);
}
};
Это работает для указателей на любые объекты, для которых определен operator<
set
set
begin
, end
, size
, max_size
) и другими ассоциативными контейнерами (например, insert
, erase
, clear
, find
).При использовании set
vector
или list
и сортируйте его только тогда, когда это необходимо, что обычно имеет сложность порядка n*log(n).6.9. Хранение контейнеров в контейнерах
Имеется несколько экземпляров стандартного контейнера (list
set
и т.п.) и требуется сохранить их в еще одном контейнере.Сохраните в главном контейнере указатели на остальные контейнеры. Например, можно использовать map
string
и указателя на set
как значения. Пример 6.12 показывает простой класс журналирования транзакций, который хранит данные как map из пар, состоящих из string
и указателей на set
.#include
#include
#include
#include
using namespace std;
typedef set
typedef map
// Фиктивный класс базы данных
class DBConn {
public:
void beginTxn() {}
void endTxn() {}
void execSql(string& sql) {}
};
class SimpleTxnLog {
public:
SimpleTxrLog() {}
~SimpleTxrLog() {purge();}
// Добавляем в список выражение SQL
void addTxn(const string& id
const string& sql) {
SetStr* pSet = log_[id]; // Здесь создается запись для
if (pSet == NULL) { // данного id, если ее еще нет
pSet = new SetStr();
log_[id] = pSet;
}
pSet->insert(sol);
}
// Применение выражений SQL к базе данных, по одной транзакции
// за один раз
void apply() {
for (MapStrSetStr::iterator p = log_.begin();
p != log_.end(); ++p) {
conn_->beginTxn();
// Помните, что итератор отображения ссылается на объект
// типа pair
for (SetStr::iterator pSql = p->second->begin();
pSql != p->second->end(); ++pSql) {
string s = *pSql;
conn_->execSql(s);
cout << "Executing SQL: " << s << endl;
}
conn_->endTxn();
delete p->second;
}
log_.clear();
}
void purge() {
for (MapStrSetStr::iterator p = log_.begin();
p != log_.end(); ++p)
delete p->second;
log_.clear();
}
//...
private:
MapStrSetStr log_;
DBConn* conn_;
}