2012-01-28 3 views
6

в последнее время я больше пользователя языка программирования Scala, чем C++, А теперь я разочарован в портировании очень простой строки кодаGLM :: ivec2 как ключ в неупорядоченной карте

val map = new HashMap[Vec2i,Entity] 

он просто отказывается компилировать в C++ со странными ошибками шаблонов. Эквивалентом Vec2i в C++ является glm :: ivec2, это, в основном, структура с двумя целыми числами и некоторыми операторами для математики.

это, как далеко я получил:

#include <iostream> 
#include <unordered_map> 
#include <glm/glm.hpp> 

using namespace std; 
using namespace glm; 

struct KeyTraits { 
size_t operator()(const ivec2& k) { 
     return std::hash<int>()(k.x)^std::hash<int>()(k.y); 
    } 

bool operator()(const ivec2& a, const ivec2& b) { 
     return a.x == b.x && a.y == b.y; 
    } 
}; 

typedef unordered_map<ivec2,int,KeyTraits,KeyTraits> MyMap; 

int main(int argc, char **argv) 
{ 
    MyMap map; 

    map[ivec2(2,3)] = 7; 
    map[ivec2(3,4)] = 8; 

    for(auto it = map.begin(); it != map.end(); it++) { 
     cout << it->second << endl; 
    } 
} 

Текущая ошибка компиляции является:

In file included from /usr/include/c++/4.5/bits/hashtable.h:35:0, 
      from /usr/include/c++/4.5/unordered_map:45, 
      from /home/arne/codelite/LanguageTest/main.cpp:2: 
/usr/include/c++/4.5/bits/hashtable_policy.h: In member function ‘std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_M_hash_code(const _Key&) const [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type = long unsigned int]’: 
/usr/include/c++/4.5/bits/hashtable_policy.h:535:74: instantiated from ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator[](const _Key&) [with _Key = glm::detail::tvec2<int>, _Pair = std::pair<const glm::detail::tvec2<int>, int>, _Hashtable = std::_Hashtable<glm::detail::tvec2<int>, std::pair<const glm::detail::tvec2<int>, int>, std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, KeyTraits, KeyTraits, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’ 
/home/arne/codelite/LanguageTest/main.cpp:24:16: instantiated from here 
/usr/include/c++/4.5/bits/hashtable_policy.h:727:25: error: passing ‘const KeyTraits’ as ‘this’ argument of ‘size_t KeyTraits::operator()(const glm::core::type::ivec2&)’ discards qualifiers 
/usr/include/c++/4.5/bits/hashtable_policy.h: In member function ‘bool std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_M_compare(const _Key&, std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type, std::__detail::_Hash_node<_Value, false>*) const [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type = long unsigned int]’: 
/usr/include/c++/4.5/bits/hashtable.h:879:2: instantiated from ‘std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node* std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_find_node(std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node*, const key_type&, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type) const [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _Allocator = std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node = std::__detail::_Hash_node<std::pair<const glm::detail::tvec2<int>, int>, false>, key_type = glm::detail::tvec2<int>, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type = long unsigned int]’ 
/usr/include/c++/4.5/bits/hashtable_policy.h:540:53: instantiated from ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator[](const _Key&) [with _Key = glm::detail::tvec2<int>, _Pair = std::pair<const glm::detail::tvec2<int>, int>, _Hashtable = std::_Hashtable<glm::detail::tvec2<int>, std::pair<const glm::detail::tvec2<int>, int>, std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, KeyTraits, KeyTraits, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’ 
/home/arne/codelite/LanguageTest/main.cpp:24:16: instantiated from here 
/usr/include/c++/4.5/bits/hashtable_policy.h:742:48: error: passing ‘const KeyTraits’ as ‘this’ argument of ‘bool KeyTraits::operator()(const glm::core::type::ivec2&, const glm::core::type::ivec2&)’ discards qualifiers 
/usr/include/c++/4.5/bits/hashtable_policy.h: In member function ‘size_t std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_M_bucket_index(const std::__detail::_Hash_node<_Value, false>*, size_t) const [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, size_t = long unsigned int]’: 
/usr/include/c++/4.5/bits/hashtable.h:1170:59: instantiated from ‘void std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_rehash(std::_Hashtable::size_type) [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _Allocator = std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable::size_type = long unsigned int]’ 
/usr/include/c++/4.5/bits/hashtable.h:911:8: instantiated from ‘std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::iterator std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_insert_bucket(const value_type&, std::_Hashtable::size_type, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type) [with _Key = glm::detail::tvec2<int>, _Value = std::pair<const glm::detail::tvec2<int>, int>, _Allocator = std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, _ExtractKey = std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, _Equal = KeyTraits, _H1 = KeyTraits, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::iterator = std::__detail::_Hashtable_iterator<std::pair<const glm::detail::tvec2<int>, int>, false, false>, value_type = std::pair<const glm::detail::tvec2<int>, int>, std::_Hashtable::size_type = long unsigned int, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type = long unsigned int]’ 
/usr/include/c++/4.5/bits/hashtable_policy.h:543:24: instantiated from ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator[](const _Key&) [with _Key = glm::detail::tvec2<int>, _Pair = std::pair<const glm::detail::tvec2<int>, int>, _Hashtable = std::_Hashtable<glm::detail::tvec2<int>, std::pair<const glm::detail::tvec2<int>, int>, std::allocator<std::pair<const glm::detail::tvec2<int>, int> >, std::_Select1st<std::pair<const glm::detail::tvec2<int>, int> >, KeyTraits, KeyTraits, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’ 
/home/arne/codelite/LanguageTest/main.cpp:24:16: instantiated from here 
/usr/include/c++/4.5/bits/hashtable_policy.h:737:55: error: passing ‘const KeyTraits’ as ‘this’ argument of ‘size_t KeyTraits::operator()(const glm::core::type::ivec2&)’ discards qualifiers 

ответ

5

Вам нужно указать класс hash и класс компаратора в вашем typedef. знакомства шаблона Params Hash и KeyEqual здесь: http://en.cppreference.com/w/cpp/container/unordered_map

это будет выглядеть (рассмотрим константные отборочные в конце подписи метода):

struct KeyFuncs 
{ 
    size_t operator()(const ivec2& k)const 
    { 
     return std::hash<int>()(k.x)^std::hash<int>()(k.y); 
    } 

    bool operator()(const ivec2& a, const ivec2& b)const 
    { 
      return a.x == b.x && a.y == b.y; 
    } 
}; 


typedef unordered_map<ivec2,int,KeyFuncs,KeyFuncs> MyMap; 
+0

Прошу прощения, я допустил ошибку при экспорте моей проблемы в переполнение стека. Программа должна быть прямо сейчас. Моя проблема в том, что эти сообщения об ошибках шаблонов для меня совершенно бесполезны, потому что я не могу их прочитать. – Arne

+0

Вы решили? Взгляните на квалификаторы const (см. Править). – Sam

+0

Добро пожаловать. В этом случае я сделал редактирование для более подходящего именования. – Sam

2

Просто посмотрите на ошибки линкера, он говорит вам, что вы должны реализовать или предоставить в списке аргументов шаблона:

std::hash<glm::detail::tvec2<int> >::operator()(glm::detail::tvec2<int>) const 

Программа не знает, как создать хэш на основе вектора объект. Вам нужно будет рассчитать свой собственный хеш, чтобы код карты мог различать векторы.

Редактировать: Редактировать: Я бы использовал указатели на векторы, так как это может испортиться, если вы добавите какой-то элемент и впоследствии измените его (так что вы должны добавить объекты const).


Edit 2: С новым сообщением кода/ошибок, кажется, что вы забыли сделать методы внутри KeyTaits сопзЬ, поэтому их this указатель типа KeyTraits*, но значение, передаваемое предназначается, чтобы быть const KeyTraits* ,

+0

Я изменил мою проблему немного, потому что первая ошибка messege здесь не была моей реальной проблемой, было более ошибочным при портировании ее правильно во внешнем проекте. – Arne

+0

Обновлен мой ответ. – Mario

+0

В этом случае указатели не выполняют работу, потому что я вычисляю вектор где-то еще, и вам нужно проверить погоду, чтобы ключ для этого объекта существовал. Выполнение этого с помощью указателей всегда не придавало значения, потому что их адреса различны. – Arne