2016-04-25 12 views
8

Là một phần của băm, tôi cần phải chuyển đổi một con trỏ hàm thành một biểu diễn chuỗi. Với chức năng toàn cầu/tĩnh nó tầm thường:Làm thế nào để có được biểu diễn chuỗi cho hàm thành viên?

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

Và từ here:

2) Bất kỳ con trỏ có thể được chuyển đổi sang bất kỳ loại không thể thiếu đủ lớn để giữ giá trị của con trỏ (ví dụ để std::uintptr_t)

Nhưng tôi có một vấn đề với chức năng thành viên:

cout << &MyStruct::member; 

kết quả đầu ra 1 mặc dù trong trình gỡ lỗi tôi có thể thấy địa chỉ.

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

Cung cấp lỗi biên dịch cannot convert. Vì vậy, có vẻ như không phải bất kỳ con trỏ nào cũng có thể được chuyển đổi.

Tôi có thể làm gì khác để có được biểu diễn chuỗi?

+0

'1' có thể là giá trị chính xác. Con trỏ hàm thành viên là tương đối, sau khi tất cả. Điều này cũng có nghĩa là bạn có thể gặp phải rất nhiều xung đột nếu bạn không thêm thông tin bổ sung như băm của typeid của chính loại đó. Và khi bạn nói rằng * không phải bất kỳ con trỏ nào cũng có thể được chuyển đổi *, hãy nhớ rằng con trỏ hàm thành viên * không * con trỏ; chúng chính xác là * con trỏ hàm thành viên *. –

+1

"Vì vậy, có vẻ như không phải bất kỳ con trỏ nào cũng có thể được chuyển đổi. ..." Một con trỏ không giống với con trỏ tới thành viên, con trỏ có thể được chuyển đổi thành kiểu không thể tách rời, con trỏ thành thành viên không thể. – user657267

+5

Không có toán tử '' nào cho con trỏ tới thành viên. '& MyStruct :: member' là một con trỏ không thành viên. Bất kỳ con trỏ nào cũng có thể được chuyển đổi thành 'bool'. Các con trỏ không null chuyển thành 'true', in theo mặc định là' 1'. – molbdnilo

Trả lời

4
cout << &MyStruct::member; 

đầu ra 1 mặc dù trong debugger tôi có thể thấy địa chỉ.

Không có quá tải cho ostream::operator<<(decltype(&MyStruct::member)). Tuy nhiên, con trỏ hàm thành viên được chuyển đổi hoàn toàn thành bool và cho rằng, có tồn tại quá tải và đó là kết quả tốt nhất cho độ phân giải quá tải. Giá trị được chuyển đổi là true nếu con trỏ không rỗng. true được xuất dưới dạng 1.


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

Cung cấp cho một lỗi thời gian biên dịch không thể chuyển đổi. Vì vậy, có vẻ như không phải bất kỳ con trỏ nào cũng có thể được chuyển đổi.

lẽ gây nhầm lẫn, trong standardese con trỏ không phải là một khái niệm bao trùm cho con trỏ đối tượng, con trỏ-to-thành viên, con trỏ-to-chức năng, con trỏ-to-viên-chức năng. Con trỏ có nghĩa là chỉ con trỏ dữ liệu cụ thể.

Vì vậy, quy tắc được trích dẫn không áp dụng cho các hàm trỏ đến thành viên. Nó chỉ áp dụng cho con trỏ (đối tượng).


Tôi có thể làm gì khác để có được biểu diễn chuỗi?

Bạn có thể sử dụng bộ đệm unsigned char, đủ lớn để biểu thị con trỏ và sử dụng std::memcpy. Sau đó in nó theo định dạng của sự lựa chọn của riêng bạn. Tôi khuyên bạn nên thập lục phân. Như Martin Bonner chỉ ra, con trỏ tới thành viên có thể chứa đệm trong trường hợp hai giá trị trỏ đến cùng một thành viên thực sự có thể có một giá trị khác nhau trong bộ đệm.Do đó giá trị in không được sử dụng nhiều bởi vì hai giá trị không thể so sánh được mà không biết bit nào (nếu có) là vùng đệm - đó là việc thực hiện được xác định.


Đáng tiếc là tôi cần một giải pháp mạnh mẽ như vậy vì đệm này, tôi không thể sử dụng.

Không xách tay giải pháp mạnh mẽ tồn tại.

Như Jonathan Wakely chỉ ra, không có đệm trong Itanium ABI, vì vậy nếu trình biên dịch của bạn sử dụng, thì phương pháp memcpy được đề xuất sẽ hoạt động.

+0

Có nguy cơ rằng một số dữ liệu của * con trỏ đến thành viên * bị bỏ qua không gian đệm. Trong trường hợp đó, các biến khác nhau có chứa một con trỏ đến cùng một thành viên có thể có các giá trị đệm khác nhau - và in ra trong hex sẽ (không chính xác) mang lại một hash khác nhau. Tôi không chắc chắn đây là một vấn đề mà có thể được giải quyết (nói chung) mà không cần hỗ trợ trình biên dịch. (Trong thực tế tất nhiên, đề xuất của bạn có thể sẽ hoạt động.) –

+0

@MartinBonner điểm tốt. Tôi đã không xem xét những gì nikitablack có thể được sử dụng đại diện chuỗi cho. – user2079303

+0

Cảm ơn bạn. Thật không may tôi cần một giải pháp mạnh mẽ vì padding này tôi không thể sử dụng. Hơn nữa, tôi không biết cách sao chép nó. 'memcpy' chấp nhận' void * 'là nguồn nhưng * không thể chuyển đổi thành con trỏ thành thành viên *. – nikitablack

Các vấn đề liên quan