#include <iostream>
#include <unordered_map>
#include <utility>
#include <cmath>
#include <stdint.h>
template <class T>
struct Vec2
{
T x, y;
Vec2() : x(0) , y(0) { };
Vec2(T xn, T yn) : x(xn), y(yn) { };
bool operator==(const Vec2& vec) const
{
return (x == vec.x) and (y == vec.y);
}
};
struct HashVec2int
{
const uint32_t maximum;
// HashVec2int(const uint32_t& m) : maximum(m) { }
std::size_t operator()(const Vec2<int>& vec) const
{ return (vec.x * maximum) vec.y; }
};
int main() {
typedef Vec2<int> iVec2;
std::unordered_map<std::pair<iVec2, iVec2>,
float, HashVec2int{300}> umap;
umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))] = 3.14f;
std::cout << umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))];
return 0;
}
I want to initialize a hash function with a maximum x value to hash my implementation of vector.
I changed the struct to a class a couple of times and even marked maximum manually inside of HashVec2int. It gave me cryptic errors.
.\main.cpp:35:32: error: type/value mismatch at argument 3 in template parameter list for 'template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> class std::unordered_map'
float, HashVec2int{300}> umap;
^
.\main.cpp:35:32: note: expected a type, got 'HashVec2int{300u}'
.\main.cpp:37:6: error: no match for 'operator[]' (operand types are 'int' and 'std::pair<Vec2<int>, Vec2<int> >')
umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))] = 3.14f;
^
.\main.cpp:39:19: error: no match for 'operator[]' (operand types are 'int' and 'std::pair<Vec2<int>, Vec2<int> >')
std::cout << umap[std::make_pair(iVec2(1, 2), iVec2(2, 3))];
^
I followed cppreference tutorials on how to create a modified hash function.
CodePudding user response:
You have a map with keys of pairs of iVecs
but your hash is for single iVecs
, that doesnt match. Though this will only be the next error you will be getting after fixing the current one.
It seems you try to pass an instance HashVec2int{300}
as template argument when a type is expected.
If maximum
does not change (it should not for the hash to be consistent) you can do it like this:
template <uint32_t maximum>
struct HashVec2int
{
std::size_t operator()(const Vec2<int>& vec) const
{ return (vec.x * maximum) vec.y; }
};
int main() {
typedef Vec2<int> iVec2;
std::unordered_map<iVec2,
float, HashVec2int<200>> umap;
umap[iVec2(1, 2)] = 3.14f;
std::cout << umap[iVec2(1, 2)];
return 0;
}
If you do not want to make HashVec2int
a template you can still use it, then use its type Hashvec2Int
as argument for the unordered map template and pass an instance, eg HashVec2Int{200}
, to one of the constructors that takes a hash instance: https://en.cppreference.com/w/cpp/container/unordered_map/unordered_map