Re[2]: multimap и функция сравнения - помогите. Это КОШМАР!
От: Кодт Россия  
Дата: 27.05.10 16:55
Оценка: 9 (4) +1 :))
Здравствуйте, Erop, Вы писали:

E>по идее метод должен называться как-то так:
bool operator() (const AggrKey& key1, const AggrKey& key2) const

Ибо у объектов 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 и функция сравнения - помогите. Это КОШМАР!
От: Vamp Россия  
Дата: 27.05.10 16:20
Оценка: +1 :)
Мультмап третьим аргументом принимает функциональный объект или функтор. У функктора должен быть определен опереатор (), а не конструктор копирования.

Во-вторых, не забудь его сделать открытым — сейчас твой конструктор закрытый.
Да здравствует мыло душистое и веревка пушистая.
Re: multimap и функция сравнения - помогите. Это КОШМАР!
От: Ka3a4oK  
Дата: 27.05.10 16:26
Оценка: :))
Здравствуйте, agendus, Вы писали:

A>
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>
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Re[3]: Привет венграм!!!
От: Vain Россия google.ru
Дата: 27.05.10 16:29
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

V>>Мультмап третьим аргументом принимает функциональный объект или функтор. У функктора должен быть определен опереатор (), а не конструктор копирования.

E>А! Я тоже сначала подумал, что это какой-то конструктор. Только у конструктора не бывает типа возвр. значения
E>Присмотрись! Это просто метод с названием похожим на название класса.
Прекрасные граблb для нубов, надо бы ещё гвоздик на конце сделать.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[4]: Привет венграм!!!
От: Erop Россия  
Дата: 27.05.10 16:40
Оценка: :))
Здравствуйте, Vain, Вы писали:

E>>Присмотрись! Это просто метод с названием похожим на название класса.

V>Прекрасные граблb для нубов, надо бы ещё гвоздик на конце сделать.

Практичнее и педагогичнее обрезать ручку вдвое
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
multimap и функция сравнения - помогите. Это КОШМАР!
От: agendus  
Дата: 27.05.10 16:12
Оценка:
дОБРЫЙ ДЕНЬ! Я уже лоб себе разбил, а компилятор все не пропускает:

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 и функция сравнения - помогите. Это КОШМАР!
От: Erop Россия  
Дата: 27.05.10 16:24
Оценка:
Здравствуйте, agendus, Вы писали:

A>[ccode]

A>class CCompareBid
A>{
A> bool CompareBid(const AggrKey& key1, const AggrKey& key2)
//...
A>};

по идее метод должен называться как-то так:
bool operator() (const AggrKey& key1, const AggrKey& key2)


В любом случае, как ты планировал сообщить мультимапу название метода CompareBid?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Привет венграм!!!
От: Erop Россия  
Дата: 27.05.10 16:26
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Мультмап третьим аргументом принимает функциональный объект или функтор. У функктора должен быть определен опереатор (), а не конструктор копирования.


А! Я тоже сначала подумал, что это какой-то конструктор. Только у конструктора не бывает типа возвр. значения
Присмотрись! Это просто метод с названием похожим на название класса.


V>Во-вторых, не забудь его сделать открытым — сейчас твой конструктор закрытый.

Я предпочитаю просто struct писать и не париться.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: multimap и функция сравнения - помогите. Это КОШМАР!
От: Vain Россия google.ru
Дата: 27.05.10 16:26
Оценка:
Здравствуйте, agendus, Вы писали:

A>дОБРЫЙ ДЕНЬ! Я уже лоб себе разбил, а компилятор все не пропускает:

bool operator() (const AggrKey& key1, const AggrKey& key2) const;
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: multimap и функция сравнения - помогите. Это КОШМАР!
От: Erop Россия  
Дата: 27.05.10 18:14
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ибо у объектов set и map есть член-данное — компаратор, и этот член используется из константных методов. Следовательно, его метод operator() должен быть константным.


А можно static?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: multimap и функция сравнения - помогите. Это КОШМАР!
От: Кодт Россия  
Дата: 27.05.10 20:15
Оценка:
Здравствуйте, Erop, Вы писали:

К>>Ибо у объектов set и map есть член-данное — компаратор, и этот член используется из константных методов. Следовательно, его метод operator() должен быть константным.


E>А можно static?


static operator() ? щас я узнаю что-то новое про синтаксис С++...
Перекуём баги на фичи!
Re[5]: multimap и функция сравнения - помогите. Это КОШМАР!
От: Erop Россия  
Дата: 27.05.10 20:50
Оценка:
Здравствуйте, Кодт, Вы писали:

К>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 и функция сравнения - помогите. Это КОШМАР!
От: Centaur Россия  
Дата: 28.05.10 07:08
Оценка:
Здравствуйте, agendus, Вы писали:

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’а.

class CompareBid : public std::binary_function<AggrKey, AggrKey, bool>
{
public:
    bool operator()(const AggrKey& key1, const AggrKey& key2) const
    {
        if (key1.InsId != key2.InsId)
            return (key1.InsId < key2.InsId);
        else 
        {
            return (key1.Price > key2.Price);
        }        
    }
};
Re[4]: multimap и функция сравнения - помогите. Это КОШМАР!
От: uzhas Ниоткуда  
Дата: 28.05.10 07:36
Оценка:
Здравствуйте, Erop, Вы писали:

E>А можно static?

Можно вот так:
#include <set>
struct A
{
  int Member;

  A()
    : Member(0)
  {
  }
};

struct Comparer
{
  static bool CompareByMember(const A& left, const A& right)
  {
    return left.Member < right.Member;
  }
};

int main()
{
  std::set<A, bool (*)(const A&, const A&)> as(&Comparer::CompareByMember);
  A a;
  as.insert(a);
  return 0;
}

Компаратор может быть указателем на обычную функцию
Re[5]: multimap и функция сравнения - помогите. Это КОШМАР!
От: Erop Россия  
Дата: 28.05.10 08:52
Оценка:
Здравствуйте, uzhas, Вы писали:


U>Компаратор может быть указателем на обычную функцию

Так не интересно -- не будет inline подстановок.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.