2016-11-24 47 views
17

我有以下問題:如何避免const轉換爲map訪問?

std::map<A*,double> map; 

void getColor(A const * obj){ 
    double d = map[obj]; // does not compile wihtout const_cast<A*>(obj) 
    // do something 
} 

我有地圖std::map(的地方),存儲對象指針A。 我有一個功能getColor其中操縱對象A,因此需要一個指針作爲輸入const A

函數getColor不會使用const_cast進行編譯。

的const的轉換是一個設計問題,但我不知道如何來規避它,如果我不想使按鍵在map常量

任何幫助表示讚賞。

+14

出於好奇:你爲什麼不想讓鍵爲const? –

+4

爲什麼你不想把鍵作爲'const A *'? – Gonmator

+0

相關:http://stackoverflow.com/a/17639764/4181011 –

回答

18

這裏有兩種可能的情況:

  1. 功能知道/期望obj已經出現在地圖上,你正在使用[]爲了方便。

  2. 您正在使用[]充分發揮潛力,即您希望它將obj添加到地圖中(如果尚未存在)。

在情況2中,您在getColor簽名中有錯誤。由於它可能會將obj傳遞到將存儲爲A*的地方,因此它僅接受const A*是錯誤的。請注意,即使函數不修改對象本身,但將其傳遞到可以修改的地方,它將間接有效地對其進行修改,因此應該將其作爲非const

在情況1中,它取決於您的C++版本。 C++ 14引入了template overload of findstd::map的相關成員函數,其中Key相當,而不是僅與Key相當。因此,你可以修改的功能是這樣的:

void getColor(A const * obj){ 
    doubel d = map.find(obj)->second; 
    // do something 
} 

注意,對於這個工作,你還需要更改地圖的類型使用一個透明的比較:std::map<A*,double, std::less<>> map;(作爲第一所指出的@Leon's answer)。

如果您遇到C++ 11或更早的版本,那麼您運氣不好,您將不得不忍受const_cast。請注意,通過合適的評論,const_cast在這種情況下是完全安全和可接受的(更不用說在不改變map類型的情況下繼續進行的唯一方法)。再次,您應該使用find或者at而不是[],因爲您不想插入到地圖中。

+0

'less <>'在通過時保證正確的事情指針? – Yakk

+0

@Yakk是的,與'operator <'不同,'std :: less'保證即使指向不相關的對象也能工作。 – Angew

+1

@angew「爲任何指針類型產量總計順序特,即使內置的操作符'<', '>','<=', '> ='沒有。對於模板特'更大','少','greater_equal ' ,'less_equal ',如果調用操作符調用比較​​指針的內置操作符,則調用操作符產生全部的指令。「好的,這裏的標準很明確! – Yakk

6

如果你能負擔得起切換到C++ 14,那麼你可以配置你的地圖使用transparent comparator(這會工作,因爲一個const指針可以用非const指針相比較):

std::map<A*,double, std::less<>> map; 
//     ^^^^^^^^^^^ 
//     enable transparent comparator on this map 

void getColor(A const * obj){ 
    auto it = map.find(obj); 
    assert(it != map.end()); 
    double d = it->second; 
    // do something 
} 

請注意,您將不得不使用std::map::find()而不是std::map::operator[],因爲後者爲doesn't have a transparent version