我正在 C -11 中創建一個模板快取庫,我想在其中對鍵進行哈希處理。我想將默認值std::hash用于原始/預定義型別,如int, std::string, etc.用戶定義型別的用戶定義哈希函式。我的代碼目前如下所示:
template<typename Key, typename Value>
class Cache
{
typedef std::function<size_t(const Key &)> HASHFUNCTION;
private:
std::list< Node<Key, Value>* > m_keys;
std::unordered_map<size_t, typename std::list< Node<Key, Value>* >::iterator> m_cache;
size_t m_Capacity;
HASHFUNCTION t_hash;
size_t getHash(const Key& key) {
if(t_hash == nullptr) {
return std::hash<Key>(key); //Error line
}
else
return t_hash(key);
}
public:
Cache(size_t size) : m_Capacity(size) {
t_hash = nullptr;
}
Cache(size_t size, HASHFUNCTION hash) : m_Capacity(size), t_hash(hash) {} void insert(const Key& key, const Value& value) {
size_t hash = getHash(key);
...
}
bool get(const Key& key, Value& val) {
size_t hash = getHash(key);
...
}
};
我的主要功能如下所示:
int main() {
Cache<int, int> cache(3);
cache.insert(1, 0);
cache.insert(2, 0);
int res;
cache.get(2, &res);
}
在編譯上面的代碼時,我收到以下錯誤:
error: no matching function for call to ‘std::hash<int>::hash(const int&)’
return std::hash<Key>(key);
誰能在這里幫助我并指出我遺漏了什么或做錯了什么?
uj5u.com熱心網友回復:
在此呼叫中,您提供std::hash<Key>with的建構式key:
return std::hash<Key>(key);
你想使用它的成員函式,size_t operator()(const Key&) const;:
return std::hash<Key>{}(key);
一些注意事項:散列和快取用于提供快速查找,并且std::function為此使用物件可能會減慢一點速度。它帶有一些開銷:
typedef std::function<size_t(const Key &)> HASHFUNCTION;
getHash()每次使用時進行的簽入也是如此:
if(t_hash == nullptr) {
為所需的哈希器型別添加模板引數可能會更好。對于具有特化的型別std::hash,這可能是默認值。否則size_t(*)(const Key&)可能是默認值。std::function<size_t(const Key &)>如果確實需要,用戶仍然可以覆寫默認值并要求哈希函式為 a 。
如果要使用散列函式,我建議在Cache構造a 時要求用戶提供它。這樣,您可以在if(t_hash == nullptr)每次使用散列函式時跳過檢查。
首先是一個小型別特征來檢查是否std::hash<Key>存在:
#include <functional>
#include <type_traits>
#include <utility>
template <class T>
struct has_std_hash {
static std::false_type test(...); // all types for which the below test fails
template <class U>
static auto test(U u) -> decltype(std::declval<std::hash<U>>()(u),
std::true_type{});
static constexpr bool value = decltype(test(std::declval<T>()))::value;
};
然后,添加的模板引數Cache可以有條件地默認為std::hash<Key>or ,size_t(*)(const Key&)并且Cache當需要指向哈希函式的指標時,您可以禁止僅使用大小構造 a :
template <
typename Key, typename Value,
class HASHFUNCTION = typename std::conditional<
has_std_hash<Key>::value, std::hash<Key>, size_t(*)(const Key&)>::type>
class Cache {
public:
// a bool that tells if HASHFUNCTION is a pointer type
static constexpr bool hash_fptr = std::is_pointer<HASHFUNCTION>::value;
Cache(size_t size) : m_Capacity(size) {
static_assert(!hash_fptr, "must supply hash function pointer");
}
Cache(size_t size, HASHFUNCTION hash) : m_Capacity(size), t_hash(hash) {}
private:
// No `if` is needed in getHash() - in fact, this function isn't needed.
// You could just do `t_hash(key)` where you need it.
size_t getHash(const Key& key) const { return t_hash(key); }
HASHFUNCTION t_hash;
};
用法與以前相同,只是您不能在Cache沒有哈希器的情況下構造 a :
struct Foo {};
size_t hashit(const Foo&) { return 0; }
int main() {
Cache<int, int> cache(3); // ok, HASHFUNCTION is std::hash<int>
Cache<Foo, int> c2(3, hashit); // ok, HASHFUNCTION is size_t(*)(const Foo&)
// Cache<Foo, int> c3(3); // error: must supply hash function pointer
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/408005.html
標籤:
