Ибо у объектов set и map есть член-данное — компаратор, и этот член используется из константных методов. Следовательно, его метод operator() должен быть константным.
Кстати, "мало кто знает", разные экземпляры одного и того же типа map можно наделять разными компараторами (одного и того же типа, но сконструированными с разными параметрами).
Менять настройки компаратора на ходу, разумеется, нельзя (UB). http://codepad.org/GhWQTZZB
struct AZOrder
{
bool m_ascending;
explicit AZOrder(bool ascending) : m_ascending(ascending) {}
template<class T> bool operator() (T const& a, T const& b) const
{
return m_ascending ? a<b : b<a;
}
};
int main()
{
set<int,AZOrder> az(AZOrder(true)), za(AZOrder(false));
// наполняем
az.insert(10); za.insert(10);
az.insert(30); za.insert(30);
az.insert(20); za.insert(20);
// az упорядочен по возрастанию
copy(az.begin(), az.end(), ostream_iterator<int>(cout," ")); // 10 20 30
cout << endl;
// za - по убыванию
copy(za.begin(), za.end(), ostream_iterator<int>(cout," ")); // 30 20 10
cout << endl;
// копируем - и данные, и компаратор
az = za;
az.insert(40);
// az упорядочен по убыванию
copy(az.begin(), az.end(), ostream_iterator<int>(cout," ")); // 40 30 20 10
cout << endl;
set<int,AZOrder> by(AZOrder(true));
by.insert(za.begin(), za.end()); // копируем только данные
// by упорядочен по возрастанию
copy(by.begin(), by.end(), ostream_iterator<int>(cout," ")); // 10 20 30
cout << endl;
}
Перекуём баги на фичи!
Re: multimap и функция сравнения - помогите. Это КОШМАР!
A>typedef struct {
A> int InsId;
A> double Price;
A>} AggrKey;
A>typedef struct {
A> int vol;
A> long ReplID;
A>} RecInfo;
A>struct CCompareBid
A>{
A> bool CompareBid()(const AggrKey& key1, const AggrKey& key2)const
A> {
A> if (key1.InsId != key2.InsId)
A> return (key1.InsId < key2.InsId);
A> else
A> {
A> return (key1.Price > key2.Price);
A> }
A> }
A>};
A>typedef multimap<AggrKey, RecInfo, CCompareBid> BidMap;
A>// Хочу вставить элемент - на операцию вставки компилятор дает ошибку
A>// term does not evaluate to a function taking 2 arguments
A>// и расстилает в окне ошибок портянку, ссылающуюся на код вставки элемента в библиотечном файле xtree
A>AggrKey aKey;
A>MakeKey(isin_id, price, aKey);
A>RecInfo rInfo;
A>MakeRecInfo(volume, ReplID, rInfo);
A>std::pair<AggrKey, RecInfo> aPair(aKey, rInfo);
A>BidMap::value_type vt(aPair);
A>_BidRates.insert(vt);
A>
Здравствуйте, Erop, Вы писали:
V>>Мультмап третьим аргументом принимает функциональный объект или функтор. У функктора должен быть определен опереатор (), а не конструктор копирования. E>А! Я тоже сначала подумал, что это какой-то конструктор. Только у конструктора не бывает типа возвр. значения E>Присмотрись! Это просто метод с названием похожим на название класса.
Прекрасные граблb для нубов, надо бы ещё гвоздик на конце сделать.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
E>>Присмотрись! Это просто метод с названием похожим на название класса. V>Прекрасные граблb для нубов, надо бы ещё гвоздик на конце сделать.
Практичнее и педагогичнее обрезать ручку вдвое
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
multimap и функция сравнения - помогите. Это КОШМАР!
дОБРЫЙ ДЕНЬ! Я уже лоб себе разбил, а компилятор все не пропускает:
typedef struct {
int InsId;
double Price;
} AggrKey;
typedef struct {
int vol;
long ReplID;
} RecInfo;
class CCompareBid
{
bool CompareBid(const AggrKey& key1, const AggrKey& key2)
{
if (key1.InsId != key2.InsId)
return (key1.InsId < key2.InsId);
else
{
return (key1.Price > key2.Price);
}
}
};
typedef multimap<AggrKey, RecInfo, CCompareBid> BidMap;
// Хочу вставить элемент - на операцию вставки компилятор дает ошибку
// term does not evaluate to a function taking 2 arguments
// и расстилает в окне ошибок портянку, ссылающуюся на код вставки элемента в библиотечном файле xtree
AggrKey aKey;
MakeKey(isin_id, price, aKey);
RecInfo rInfo;
MakeRecInfo(volume, ReplID, rInfo);
std::pair<AggrKey, RecInfo> aPair(aKey, rInfo);
BidMap::value_type vt(aPair);
_BidRates.insert(vt);
Видимо ему не нравится функция сравнения, но что в ней не так?! А если причина не в ней — то я вообще не знаю что делать. Мне нужно определить такой multimap! HE-E-ELP PLease
Re: multimap и функция сравнения - помогите. Это КОШМАР!
В любом случае, как ты планировал сообщить мультимапу название метода CompareBid?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Vamp, Вы писали:
V>Мультмап третьим аргументом принимает функциональный объект или функтор. У функктора должен быть определен опереатор (), а не конструктор копирования.
А! Я тоже сначала подумал, что это какой-то конструктор. Только у конструктора не бывает типа возвр. значения
Присмотрись! Это просто метод с названием похожим на название класса.
V>Во-вторых, не забудь его сделать открытым — сейчас твой конструктор закрытый.
Я предпочитаю просто struct писать и не париться.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: multimap и функция сравнения - помогите. Это КОШМАР!
Здравствуйте, Кодт, Вы писали:
К>Ибо у объектов set и map есть член-данное — компаратор, и этот член используется из константных методов. Следовательно, его метод operator() должен быть константным.
А можно static?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: multimap и функция сравнения - помогите. Это КОШМАР!
Здравствуйте, Erop, Вы писали:
К>>Ибо у объектов set и map есть член-данное — компаратор, и этот член используется из константных методов. Следовательно, его метод operator() должен быть константным.
E>А можно static?
static operator() ? щас я узнаю что-то новое про синтаксис С++...
Перекуём баги на фичи!
Re[5]: multimap и функция сравнения - помогите. Это КОШМАР!
Здравствуйте, Кодт, Вы писали:
К>static operator() ? щас я узнаю что-то новое про синтаксис С++...
Упс! А я-то никак не мог понять, что меня раздражает в функторах. А они же действительно не могут быть static.
Так что если не хочется передавать лишний this, то выход один --
typedef int function_t( int, int );
struct my_functor {
static int impl( int, int );
operator function_t& () const { return impl; }
};
Только это, скорее всего, может помешать inline-подстановкам.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: multimap и функция сравнения - помогите. Это КОШМАР!
A>class CCompareBid
A>{
A> bool CompareBid(const AggrKey& key1, const AggrKey& key2)
A> {
A> if (key1.InsId != key2.InsId)
A> return (key1.InsId < key2.InsId);
A> else
A> {
A> return (key1.Price > key2.Price);
A> }
A> }
A>};
Как уже выше объяснили:
Во-первых, функтор сравнения должен определять операцию вызова функции (operator()).
Во-вторых, её должно быть можно вызвать на константном объекте с двумя константными параметрами сравниваемого типа.
В-третьих, результат должен приводиться к bool.
А в-четвёртых, полезно наследовать функторы от стандартных шаблонов std::unary_function и std::binary_function, чтобы функторы можно было связывать при помощи std::bind1st и std::bind2nd.
И в-пятых, называть классы с буквы C — дорога к конфликтам с идентификаторами Microsoft’а.
U>Компаратор может быть указателем на обычную функцию
Так не интересно -- не будет inline подстановок.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском