2016-04-25 71 views
8

作爲哈希的一部分,我需要將函數指針轉換爲字符串表示形式。隨着全球/靜態函數是微不足道:如何獲取成員函數的字符串表示形式?

string s1{ to_string(reinterpret_cast<uintptr_t>(&global)) }; 

而且從here

2)任何指針可以轉換爲任何整數類型足夠大,以 將指針(如以std::uintptr_t值)

但我有一個問題,成員函數:

cout << &MyStruct::member; 

輸出1雖然在調試器中我可以看到地址。

string s{ to_string(reinterpret_cast<uintptr_t>(&MyStruct::member)) }; 

給出一個編譯時錯誤cannot convert。所以似乎沒有任何指針可以轉換。

我還能做些什麼來獲得字符串表示?

+0

'1'很可能是正確的值。畢竟,成員函數指針是相對的。這也意味着如果你不添加額外的信息,比如類型自身的typeid的散列,你可能會遇到很多衝突。當你說*沒有任何指針可以被轉換*時,請記住成員函數指針*不是*指針;他們正是*成員函數指針*。 –

+1

「所以看起來沒有任何指針可以被轉換......」指針與指向成員的指針不同,指針可以轉換爲整型,指向成員的指針不能。 – user657267

+5

指針到成員沒有'operator <<'。 '&MyStruct :: member'是一個非空的指向成員的指針。任何指針都可以隱式轉換爲「bool」。非空指針轉換爲'true',默認打印爲'1'。 – molbdnilo

回答

4
cout << &MyStruct::member; 

輸出1雖然在調試器可以看我的地址。

ostream::operator<<(decltype(&MyStruct::member))沒有超載。但是,成員函數指針可以隱式轉換爲bool,爲此,存在重載並且這是重載解析的最佳匹配。如果指針不爲空,轉換後的值爲truetrue輸出爲1


string s{ to_string(reinterpret_cast<uintptr_t>(&MyStruct::member)) }; 

給出一個編譯時錯誤不能轉換。所以似乎沒有任何指針可以轉換。

或許令人混淆,在standardese 指針不是對象指針的總稱,指針到成員,指針到功能和指針到成員函數。指針特指數據指針。

所以,引用的規則不適用於指向成員函數的指針。它只適用於(對象)指針。


還有什麼我能做得到的字符串表示?

您可以使用unsigned char緩衝區,大到足以代表指針,並使用std::memcpy。然後以您自己選擇的格式打印。我推薦十六進制。

正如Martin Bonner指出的那樣,指向成員的指針可能包含填充,在這種情況下,指向同一成員的兩個值實際上可能在緩衝區中具有不同的值。因此,打印值沒有多大用處,因爲如果不知道哪些位(如果有的話)是填充(padding) - 這是實現定義的,則兩個值不具有可比性。


不幸的是,我需要一個強大的解決方案,因爲這樣可以填充我不能使用。

便攜式存在健壯的解決方案。

正如Jonathan Wakely指出的那樣,Itanium ABI中沒有填充,所以如果你的編譯器使用它,那麼建議的memcpy方法就可以工作。

+0

存在*指針指向的成員*的某些數據被忽略填充空間的風險。在這種情況下,包含指向同一成員的指針的不同變量可能具有不同的填充值 - 並以十六進制打印出來(不正確)會產生不同的散列值。我不確定這是否是一個無需編譯器支持即可解決的問題(一般情況下)。 (當然在實踐中,你的建議可能會起作用。) –

+0

@MartinBonner好點。我沒有考慮過nikitablack可能使用的字符串表示方式。 – user2079303

+0

謝謝。不幸的是,我需要一個強大的解決方案,因爲這個填充我不能使用。而且,我不知道如何複製它。 'memcpy'接受'void *'作爲源,但*指向成員*不能轉換爲它。 – nikitablack

相關問題