C++ unordered_map 中 double 作key如何在模板參數中實現?
這麼寫編譯器一直報錯,不知道神馬原因,請指教。
auto comp_dbl_eq = [] (const double lhs, const double rhs) {
return abs(lhs - rhs) &< DBL_EPSILON; }; unordered_map&, decltype(comp_dbl_eq)&> dbl_map;
問題出在lambda,每一個lambda都是獨一無二的類型,所以即使你命名了這個lambda,也無法再次給第二個需要lambda需要的地方用,於是你可以改用functional來存儲。
std::function&
return abs(lhs - rhs) &< DBL_EPSILON;
};
unordered_map&
或者也可以使用一個functor
struct KeyEqual
{
bool operator()(const double lhs, const double rhs) const
{
return abs(lhs - rhs) &< DBL_EPSILON;
}
};
unordered_map&
問題出在:note: a lambda closure type has a deleted default constructor。你應該同時把 comp_dbl_eq 傳遞給 dbl_map 的構造函數。
就算你編譯過了,你的寫法也達不到想要的效果。因為你認為相等的兩個double值,其hash很可能不等,因此很可能不會碰撞,根本就調用不到你的comp_dbl_eq。怎樣判斷浮點數是否相等並保證同一性? - Milo Yip 的回答
糾正我之前的錯誤
藍色大大的回答其實是切入本質的下面是我實現的一個簡單示例#include &
template &
class Map
{
public:
Map() :
mComparator
{
[]
(_Key const a,_Key const b) -&> int
{
if (a &> b) return 1;
else if (a &< b) return -1;
else return 0;
}
}
{}
template &
Map(__Comparator comparator) :
mComparator{std::forward&<__Comparator&>(comparator)}
{}
private:
_Comparator mComparator;
};
auto comp = [] (double const a,double const b) -&> int
{
return 0;
};
int main()
{
Map&
//Map&
Map&
Map&
{
[] (double const a,double const b) -&> int
{
return 0;
}
};
return 0;
}
注意之所以
Map&
這是錯誤的
是因為展開後的代碼等價於class Map
{
public:
Map() :
mComparator
{
[]
(_Key const a,_Key const b) -&> int
{
if (a &> b) return 1;
else if (a &< b) return -1;
else return 0;
}
}
{}
private:
decltype(comp) mComparator;
};
[] (_Key const a,Key const b) -&> int
{
if (a &> b) return 1;
else if (a &< b) return -1;
else return 0;
}
對其進行初始化
可以直接理解成auto comp = [] (double const a,double const b) -&> int
{
return 0;
};
decltype(comp) mComparator
{
[] (_Key const a,Key const b) -&> int
{
if (a &> b) return 1;
else if (a &< b) return -1;
else return 0;
}
};
auto lambda = [] () {};
decltype(lambda) lambda2 = [] () {};//這是錯誤的
就像藍色所說的 每個lambda都是一個獨立的類型
也就是說錯誤的原因是因為
第二句中[] () {}的類型和decltype(lambda)是不同的所以無法通過[] () {}構造lambda2這裡類比一下auto i = int{0};
decltype(i) i2 = int{0};//完全正確
很奇怪吧 所以我一開始想當然的以為 相同捕獲和簽名的lambda應該是相同的類型
我還是不理解為什麼標準要讓他們成為不同的類型如何讓代碼正確呢?請看下面代碼auto lambda = [] () {};
decltype(lambda) lambda2 = lambda;//這樣就可以通過
請注意這裡 lambda 就和decltype(lambda)是相同的類型 所以可以通過lambda構造lambda2
這就是Map&
正確的原因
因為這裡直接調用的是第二個構造函數
效果等同於上面的代碼類型是一樣的 所以可以通過所以LZ只需要把代碼修改成auto comp_dbl_eq = [] (const double lhs, const double rhs)
{
return abs(lhs - rhs) &< DBL_EPSILON;
};
std::unordered_map&
{
10,//桶的大小
std::hash&
comp_dbl_eq,//這裡傳入比較器的實例 通過這個實例去初始化map內部的比較器就就沒有問題了
};
std::unordered_map&
{
10,//桶的大小
std::hash&
[] (const double lhs, const double rhs)
{
return abs(lhs - rhs) &< DBL_EPSILON;
}
};
所有浮點運算都應當定義運算的精度,一旦確定了精度,所有浮點的問題自然變成了字元串問題或者一定乘法因子下的整數問題。
推薦閱讀:
※C++ std::set 的實現中對於iterator的這個強制轉換是如何進行的?
※C# 為什麼去掉了C++中頭文件的概念?
※如何使用C++編寫一個模板,可以同時適用於數組和vector<int>類型且避免數據的複製?
※C++獲取數組長度只返回1?
※構造函數不能是虛函數?
TAG:C |