我正在嘗試使用以下自定義 unordered_map
using pair = std::pair<char, QColor>;
using cache = std::unordered_map<pair, QPixmap, boost::hash<pair>>;
cache _cache;
我為 QColor 定義了哈希函式如下
template<>
struct std::hash<QColor>
{
std::size_t operator()(const QColor &color) const noexcept
{
return std::hash<QRgb>{}(color.rgb());
}
};
但無論我把它放在哪里,無論是頭檔案還是源檔案,我都會從 boost 得到一個冗長的編譯時錯誤
C:\boost_1_77_0\boost\container_hash\extensions.hpp:305: error: C2665: 'boost::hash_value': none of the 3 overloads could convert all the argument types
C:\boost_1_77_0\boost/container_hash/hash.hpp(550): note: could be 'size_t boost::hash_value(const std::error_condition &)'
C:\boost_1_77_0\boost/container_hash/hash.hpp(543): note: or 'size_t boost::hash_value(const std::error_code &)'
C:\boost_1_77_0\boost/container_hash/hash.hpp(536): note: or 'size_t boost::hash_value(std::type_index)'
C:\boost_1_77_0\boost/container_hash/extensions.hpp(305): note: while trying to match the argument list '(const T)'
這是最后的訊息。我認為 boost 的散列函式沒有看到我定義的散列函式。我需要在 boost 的命名空間中定義它嗎?一般來說,定義模板特定版本的規則是什么?為什么模板必須只在頭檔案中定義的規則在這里不適用?
UPD:我的專案結構如下
// foo.h
#include <QtWidgets>
#include <boost/functional/hash.hpp>
#include <unordered_map>
template<>
struct std::hash<QColor>
{
std::size_t operator()(const QColor &color) const noexcept
{
return std::hash<QRgb>{}(color.rgb());
}
};
class Foo
{
private:
using Pair = std::pair<char, QColor>;
const QPixmap &getPixmapForPair(Pair c);
using CharsCache = std::unordered_map<Pair, QPixmap, boost::hash<Pair>>;
CharsCache _cache;
}
// foo.cpp
const QPixmap &Foo::getPixmapForPair(Pair c)
{
auto it = _cache.find(c);
if (it != _cache.end())
return it->second;
}
非常簡單化,但提供了總體思路。
uj5u.com熱心網友回復:
boost::hash<>可能使用boost::hash_combinewhich 使用hash_value多載并且它沒有一個QColor可能是問題的多載所以我建議您std::hash<Pair>通過將別名移出類定義然后boost::hash_combine直接在您的operator():
using Pair = std::pair<char, QColor>;
namespace std {
template<>
struct hash<Pair> {
std::size_t operator()(const Pair &p) const noexcept {
std::size_t seed = 0;
boost::hash_combine(seed, p.first);
boost::hash_combine(seed, p.second.rgb());
return seed;
}
};
} // namespace std
您可能可以使用它std::size_t seed = p.first;而不是初始化0并在hash_combine之后呼叫。
然后,您可以std::hash<Pair>在創建地圖時使用默認散列器 ( ):
class Foo {
private:
const QPixmap &getPixmapForPair(const Pair &c) const;
using CharsCache = std::unordered_map<Pair, QPixmap>;
CharsCache _cache;
};
請注意,該函式必須回傳一個值。如果找不到匹配項,我建議您拋出例外:
const QPixmap& Foo::getPixmapForPair(const Pair &c) const {
auto it = _cache.find(c);
if (it != _cache.end()) return it->second;
throw std::runtime_error("getPixmapForPair"); // must return a value
}
另一種選擇是為 提供多載hash_value(const QColor&)而不是專門化std::hash<Pair>:
std::size_t hash_value(const QColor& c) {
return std::hash<QRgb>{}(c.rgb());
}
class Foo {
private:
using Pair = std::pair<char, QColor>;
const QPixmap& getPixmapForPair(const Pair& p) const;
using CharsCache = std::unordered_map<Pair, QPixmap, boost::hash<Pair>>;
CharsCache _cache;
};
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/371192.html
