В таком виде она выдает, что ключ найден. Почему?
Если CKey(6,-6), то ключ также найден, а если CKey(-6,-6), то не найден.
На вызов (2) компилятор (VC6) выдает ошибку
c:\program files\microsoft visual studio\vc98\include\algorithm(43) : error C2784:
'bool __cdecl std::operator ==(const class std::basic_string<_E,_Tr,_A> &,const _E *)'
: could not deduce template argument for 'const class std::basic_string<_E,_Tr, _A> &' from 'struct std::pair<class CKey const ,int>' Почему?
Что я сделал не так?
E>В таком виде она выдает, что ключ найден. Почему? E>Если CKey(6,-6), то ключ также найден, а если CKey(-6,-6), то не найден.
Для операции меньше должны выполняться все условия, как для математической операции меньше (транзитивность, коммутативность и т.д.)
В частности (если a != b), то (a <b) == !(b < a)
А у тебя:
(1, 0) < (0, 1) — true
(0, 1) < (1, 0) — true
Поменяй лучше операцию меньше на следующее
if (f1<right.f1)
return true;
if (right.f1 < f1)
return false;
if (f2 < right.f2)
return true;
if (right.f2 < f2)
return false;
return true;
E> CKey k(-6,6); E> it=data.find(k); //(1)
E>В таком виде она выдает, что ключ найден. Почему? E>Если CKey(6,-6), то ключ также найден, а если CKey(-6,-6), то не найден.
Если я возьму ключи CKey(6, -6) и CKey(-6, 6) и попробую сравнить их при помощи твоего твоего оператора '<', то я получу, что
Т.е. ни первый не меньше, ни второй не меньше. Это означает, что, согласно твоему оператору сравнения, CKey(6, 6) и CKey(6, -6) — эквивалентны. Поэтому, когда ты просишь найти CKey(6, -6), находится CKey(6, 6). Сделай нормальный оператор сравнения '<' и все заработает.
E> //it=find(data.begin(), data.end(), k); //(2)
E> if (it==data.end()) E> cout << "Not find" << endl; E> else E> cout << "Find" << endl; E> E>}
E>[/ccode]
E>На вызов (2) компилятор (VC6) выдает ошибку E>c:\program files\microsoft visual studio\vc98\include\algorithm(43) : error C2784: E>'bool __cdecl std::operator ==(const class std::basic_string<_E,_Tr,_A> &,const _E *)' E> : could not deduce template argument for 'const class std::basic_string<_E,_Tr, _A>> &' from 'struct std::pair<class CKey const ,int>' Почему? E>Что я сделал не так?
В твоем 'std::map' хранятся элементы типа 'std::pair<class CKey const ,int>'. Именно такой аргумент надло передавать в 'find'. Но в использовании 'std::find' для поиска по ключу в 'std::map' — это бессмыслица. Исаправь свой оператор '<' и пользуйся 'std::map::find'
Здравствуйте eklmn, Вы писали: E>class CKey { E>public: E> bool operator<(const CKey& right) const { E> if (f1<right.f1 && f2<right.f2) E> return true; E> else E> return false; E> } E> bool operator==(const CKey &right) const { E> if (f1==right.f1 && f2==right.f2) E> return true; E> else E> return false; E> } E> CKey(){} E> CKey(int a, int b) : f1(a), f2(b) {} E>public: E> int f1; E> int f2; E>};
Попробуем интерпретировать товою ситуацию:
Представим себе множество, единицами которого являются объекты класса CKey. CKey ставится в соответствие 2 целых числа. Забудем на секунду о том, что диапазон int в С++ — конечен. Таким образом, рассматривается множество всех точек на плоскости, имеющих целые координаты. Так?
Дальше. Так как координаты точко на плоскости — целые, рискну предположить, что это именно координаты точки на плоскости. Тогда, операцию сравнения можно определить как сравнение расстояний от точек до нуля (точки с координатами (0,0).
Формула: sqrt(f1*f1 + f2*f2) — расстояние от точки до начала координат, или модуль.
Это — не очень хорошая операция в таком случае, т.к. все точки, которые лежат на одинаковом удалении от центра — будут отождествляться. Что и продемонстрировано Андреем Тарасевичем рядом.
Но введенная тобой операция еще мене точная.
Она считает, что для точки A(xa,ya) все точки, лежащие в круге радиуса строго меньшего минимума 2-х координат min(xa,ya) — меньше ее, а все остальные — не меньше. Посему, не только приведенный тобой пример не работает, т.к. контейнер содержит точки A(6,-6) и B(-6,6), которые хоть и не удовлетворяют опреатору ==, но зато дают одинаковые результаты: A<B, B<A => A==B
В твоей же формуле A(xa,ya) < B(xb,yb) <=> max(xa,xb) < min(xb,yb)
От такой стратегии сравнения кто угодно с ума сойдет :-))
Так что ответ на твой вопрос "Почему?" — неправильная формула. В паре с операцией сравнения она не дает операцию "больше", а должна.
С уважением
Алексей Кирдин
Re[2]: Параметр-ключ в map в виде структуры/класса
Большое спасибо всем ответившим.
Но! Тот исходник который я привел не то, что мне реально было нужно.
По своей наивности я подумал, что этого примера будет достаточно,
а все остальное я сделаю по аналогии... :)
Проблема немного шире, а именно мне нужно иметь соответствие
одной структуре другой структуре. В общем случае, в структуре,
которая будет рассматриваться как ключ, количество полей может
меняться, но в каждом конкретном случае я буду знать сколько
их и какого они типа. Стоит еще сказать, что тип данных полей
в структуре-ключе не обязательно int. Часть полей могут быть int,
а другая часть, скажем, string. Так же понятно, что мне придется
в каждом случае писать функции поиск/вставка/удаление.
А спросить хочу вот что: как мне все это лучше сделать???
Разумеется, что исходников я даже и не жду. Был бы очень
благодарен за просто советы о том в каком направлении копать.
Спасибо.
Re[3]: Параметр-ключ в map в виде структуры/класса
Здравствуйте eklmn, Вы писали:
E>А спросить хочу вот что: как мне все это лучше сделать???
Нужна более точная постановка вопроса. Так оно все слишком на пальцах. Я сразу могу несколько интерпретаций написанному привести, и половина из них сразу неправильная.
1. Разное кол-во полей внутри одной структуры/класса — невозможно.
2. Возможно, но хранение и доступ к ним надо организовывать вручную, а не с помощью доступа по имени. Для этого нужно сделать внутри класса массивчик, который должен содержать некоторые последовательности байт, одни из которых будут содержать данные (читай — поля), а другие (обычно их делают заголовками к данным) — содержат информацию о данных: тип, если надо — размер, и т.д. Доступ к полям в общем случае осуществляется по индексу через какую-то функцию-член типа GetField, а в производных классах знание конкретного местоположения полей приводит к появлению методов типа GetSomeInfo, которые будут звать GetField предка. Для каждого потомка приделать опреации сравнения. Все. Но без подробностей.
С уважением
Алексей Кирдин
Re[3]: Параметр-ключ в map в виде структуры/класса
Здравствуйте eklmn, Вы писали:
E>Проблема немного шире, а именно мне нужно иметь соответствие E>одной структуре другой структуре. В общем случае, в структуре, E>которая будет рассматриваться как ключ, количество полей может E>меняться, но в каждом конкретном случае я буду знать сколько E>их и какого они типа. Стоит еще сказать, что тип данных полей E>в структуре-ключе не обязательно int. Часть полей могут быть int, E>а другая часть, скажем, string. Так же понятно, что мне придется E>в каждом случае писать функции поиск/вставка/удаление.
E>А спросить хочу вот что: как мне все это лучше сделать???
Т.е., существует дерево классов — ключей, и дерево классов — значений.
Поскольку напрямую сделать pair<CKey, CValue> не получится (хотя бы из-за варьирующихся размеров объектов), то в map'е должны храниться некие свертки.
Для CValue и его потомков — это может быть указатель (потребуется следить за созданием-удалением!)
Для CKey — придется озаботиться универсальным сравнивателем.
1) если возможно — написать операторы сравнения всех классов со всеми (например, если объекты не содержат указатели и под-объекты, — можно побайтно сравнить экземпляры)
2) придумать хэш-функцию и перекрыть ее вычисление для каждого класса
3) двухступенчатый механизм сравнения:
объекты различных классов сравниваются по именам классов
в одном классе идет развернутое сравнение
Подобный же прием можно применить и к хэш-функции, чтобы избежать коллизий (ложных совпадений) для разных классов (пользующихся разными алгоритмами).