находка hash_multimap работает не так, как должна

Я уже некоторое время пытаюсь использовать hash_multimap, но метод find продолжает давать мне итератор до конца контейнера, хотя я знаю, что он нашел соответствующий ключ. Что меня смущает, так это то, что раньше я использовал один и тот же код для другого проекта, и он отлично работает, но теперь он работает. Причина, по которой я знаю, что он что-то нашел, заключается в том, что я поместил несколько символов в хэш-функцию и сравнил хэш, что говорит мне о том, что ключ найден и что он совпадает с тем, что я дал hash_multimap :: find meathod, но все еще дает мне итератор.

сначала файл заголовка

//
//  HashGrid.h
//  Planetarium
//
//  Created by Taura J Greig on 24/08/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef _HASHGRID_
#define _HASHGRID_

#include <iostream>
#include <hash_map>
#include <deque>
#include "..//hashKey.h"

struct myTraits
{
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;

myTraits() { };

myHash hashfunction;
myEqualTo equal_to;

size_t operator() (const hashKey& key) const
{
size_t hashval = 0;
hashval = ((key.y * globalGridWidth) + key.x);

cout << "x : " << key.x << " y : " << key.y << endl;
cout << "hashVal : " << hashval << endl;

return hashval;
}

bool operator() (const hashKey& key1, const hashKey& key2) const
{
bool test = (key1.x == key2.x && key1.y == key2.y);
cout << "equal_to = " << test << endl;
return test;
}
};

using namespace std;
//using namespace stdext;using namespace stdext;

template <class T>
class HashGrid
{
public:
typedef deque<T *> localObjects;
typedef pair<hashKey, T *> addingPair;
typedef hash_multimap <hashKey, T *, myTraits> hashmMap;
typedef typename hash_multimap <hashKey, T *, myTraits> :: iterator hashmMapItor;
typedef pair<hashmMapItor, hashmMapItor> valueRange;

private:

hashKey keyOffsets[9];

int gridSize;
hash_multimap<hashKey, T*, myTraits> theMap;

inline bool exists(hashKey & theKey);
inline bool exists(hashKey & theKey, hashmMapItor & it);
public:
HashGrid();

void setup(int gridSize);
void update();
void draw(); // this is used for viusal debug,

void resize();

void addObject(T * object);

void getLocalObjects(float & x, float & y, int range, localObjects & p1);

};

template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey)
{
hashmMapItor it;
it = theMap.find(theKey);
if (it == theMap.end())
{
return false;
}
else
{
return true;
}
}

template <class T>
inline bool HashGrid<T>::exists(hashKey & theKey,
hashmMapItor & it)
{
it = theMap.find(theKey);
if (it == theMap.end())
{
return false;
}
else
{
return true;
}
}

#include "HashGrid.cpp"
#endif

и исходный файл

//
//  HashGrid.cpp
//  Planetarium
//
//  Created by Taura J Greig on 26/08/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef _HASHGRID_SOURCE_
#define _HASHGRID_SOURCE_

#include "HashGrid.h"#include "ofMain.h"

template<class T>
void HashGrid<T>::update()
{
theMap.clear();
}

template <class T>
void HashGrid<T>::addObject(T *obj)
{
hashKey tempKey;
tempKey.x = int(obj -> getPos().x) / gridSize;
tempKey.y = int(obj -> getPos().y) / gridSize;

cout << "tempKey.x : " << tempKey.x  << endl;
cout << "tempKey.y : " << tempKey.y  << endl;

theMap.insert(addingPair(tempKey, obj));
}

template <class T>
void HashGrid<T>::getLocalObjects(float & x, float & y, int range, localObjects & p1)
{
cout << "you are gettin local objects" << endl;

int gridX = (int(x) / gridSize);
int gridY = (int(y) / gridSize);

cout << "player x : " <<  x << endl;
cout << "player y : " <<  y << endl;
cout << "girdX " << gridX << endl;
cout << "girdY " << gridY << endl;for (int i = 0; i < 9; i++)
{
hashKey tempkey;

tempkey.x = gridX;
tempkey.y = gridY;

tempkey += keyOffsets[i];

cout << i << " tempKey : " << tempkey.x << " " << tempkey.y << endl;

cout << "exists " << exists(tempkey) << " ";

//this is where the problem lies, the exists function will always return
//false even when the key is found
if (exists(tempkey))
{
cout << "found" << endl;

hashmMapItor it;
valueRange elements;

elements = theMap.equal_range(tempkey);
for (it = elements.first; it != elements.second; it++)
{
p1.push_back(it->second);

}
}
else
{
cout << "not found" << endl;
}
}
}

#endif

Обратите внимание, что я вырезал много методов из вышеприведенного блока, чтобы сэкономить место, потому что они не связаны с рассматриваемой проблемой. Однако я оставил их объявления в заголовочном файле. Также я знаю, что есть несколько вещей, которые я делаю с шаблонами, которые ужасны. Просто разберись с этим сейчас.

Теперь я подробно расскажу о том, что происходит в коде и в чем заключается проблема. В методе getlocalobjects вызывается метод «exist (key)», чтобы определить, есть ли в hash_multimap элемент с предоставленным ключом. Я знаю, что он что-то находит, потому что, как я упоминал выше, потому что я поместил cout в функцию equal_to, чтобы сообщить мне, когда он использует, каков его результат.

Последовательно говорит мне, что да (через отладку equal_to) он что-то нашел, но существующий метод все равно вернет false Это наводит меня на мысль, что в hash_multimap :: find может быть ошибка, поскольку это означает, что даже если он что-то находит, он дает мне итератор для hash_multimap :: end

Таким образом, мой вопрос, я делаю ужасно неправильно относительно использования мультикарты? моя структура черт не имеет чего-то необходимого для правильной работы мультикарты

РЕДАКТИРОВАТЬ и реализация для hashKey, который я забыл, включает в себя

заголовок

#ifndef _HASHKEY_
#define _HASHKEY_

#include <iostream>

using namespace std;

static int globalGridSize = 1;

static int globalGridWidth = 1;
static int globalGridHeight = 1;

struct hashKey
{
public:
int x;
int y;

hashKey();
hashKey(int x, int y);

void set(int x, int y);
void set(hashKey & key);

void printKey()
{
cout << x << " " << y <<  endl;
}

bool operator < (const hashKey & key1) const;

bool operator == (const hashKey & key1) const;

hashKey& operator += (hashKey & key1);
};

#endif

и источник

#ifndef _HASHKEY_SOURCE_
#define _HASHKEY_SOURCE_

#include "hashKey.h"
hashKey::hashKey()
{
x = 0;
y = 0;
}

hashKey::hashKey(int x, int y)
{
hashKey::x = x;
hashKey::y = y;
}

void hashKey::set(int x, int y)
{
hashKey::x = x;
hashKey::y = y;
}

void hashKey::set(hashKey &key)
{
x = key.x;
y = key.y;
cout << "set: x = " << x << " y = " << y << endl;
}

bool hashKey::operator<(const hashKey &key1) const
{
if ( (this->x < key1.x) && (this->y < key1.y))
{
return true;
}
return false;
}

bool hashKey::operator == (const hashKey &key1) const
{
if ((this-> x == key1.x) && (this->y == key1.y))
{
return true;
}
return false;
}

hashKey& hashKey::operator+=(hashKey &key1)
{
this->x += key1.x;
this->y += key1.y;
return *this;
}

#endif

РЕДАКТИРОВАТЬ [SOVLED] Я изменил hash_multimap tp на unordered_multimap, и теперь он работает, поэтому первоначальное подозрение было верным, что в это время hash_multimap прослушивается, его метод find всегда будет давать итератор до конца. Обратите внимание, что я использую Visual Studio C ++ 2010, возможно, он не содержит ошибок на других платформах или других компиляторах, однако в моем случае он вызывающе прослушивался

0

Решение

Содержание ниже является предположением, поскольку не весь соответствующий код виден.

Кажется, у вас есть:

  • Хэш, который имеет тип size_t (как создано с первого operator() из myTraits)
  • Ключ типа hashKey (который не является хешем с точки зрения hash_multimap)

Вы не предоставили реализацию hashKeyпоэтому мой ближайший вопрос:

  • Вы предоставили оператор равенства для hashKey?
  • Или, альтернативно, вы переопределили equal_to<haskHey>?

Я вижу потенциальную проблему (и причину вышеуказанных вопросов) в том, что вы определили hashmMap как hash_multimap <hashKey, T *, myTraits> которая переопределяет функцию хеширования, но не переопределить равенство ключей (которое имеет тип hashKey). Итак, я предполагаю, что компаратор по умолчанию hashKey (а не тот, который определен в myTraits) может быть использован.
возможно hash_multimap <hashKey, T *, myTraits, myTraits> будет достаточно?


Обновление: я просто заметил, что VS hash_multimap имеет другую подпись, чем у STL. Для сравнения:

Последний имеет функцию хеширования и ключевой компаратор разделены. Это просто вызывает ужасные проблемы, когда вы переключаете компиляторы!

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]