Tiêu chuẩn nói
Các toán hạng phải có một loại con trỏ, hoặc một loại lớp có một hàm chuyển đổi duy nhất (12.3.2) cho một loại con trỏ. Nếu toán hạng có loại lớp, toán hạng được chuyển thành kiểu con trỏ bằng cách gọi hàm chuyển đổi được đề cập ở trên và toán hạng được chuyển đổi được sử dụng thay cho toán hạng gốc cho phần còn lại của phần này.
Bạn có thể (ab) - sử dụng sự vắng mặt của độ phân giải quá tải bằng cách khai báo phiên bản const của hàm chuyển đổi. Trên một trình biên dịch phù hợp đó là đủ để làm cho nó không hoạt động nữa với delete
:
struct A {
operator int*() { return 0; }
operator int*() const { return 0; }
};
int main() {
A a;
int *p = a; // works
delete a; // doesn't work
}
Kết quả trong những điều sau
[[email protected] cpp]$ clang++ main1.cpp
main1.cpp:9:3: error: ambiguous conversion of delete expression of type 'A' to a pointer
delete a; // doesn't work
^ ~
main1.cpp:2:3: note: candidate function
operator int*() { return 0; }
^
main1.cpp:3:3: note: candidate function
operator int*() const { return 0; }
^
1 error generated.
trên trình biên dịch được ít phù hợp trong vấn đề đó (EDG/Comeau, GCC) bạn có thể làm cho chức năng chuyển đổi thành một mẫu. delete
không mong đợi một loại đặc biệt, vì vậy đây sẽ làm việc:
template<typename T>
operator T*() { return /* ... */ }
Tuy nhiên, điều này có nhược điểm là smartpointer của bạn bây giờ là chuyển đổi thành bất kỳ con trỏ-type. Mặc dù chuyển đổi thực tế vẫn được đánh máy, nhưng điều này sẽ không loại trừ các chuyển đổi ở phía trước mà thay vào đó sẽ cung cấp một lỗi thời gian biên dịch sau này. Đáng buồn thay, SFINAE dường như không thể với chức năng chuyển đổi trong C++ 03 :) Một cách khác nhau là để trả về một con trỏ lồng nhau kiểu tin từ các chức năng khác
struct A {
operator int*() { return 0; }
private:
struct nested { };
operator nested*() { return 0; }
};
Vấn đề duy nhất là bây giờ với một chuyển đổi void*
, trong trường hợp cả hai hàm chuyển đổi đều có khả năng tương đương nhau. Một công việc được đề xuất bởi @Luther là trả về một kiểu con trỏ hàm từ hàm chuyển đổi khác, hoạt động với cả GCC và Comeau và loại bỏ vấn đề void*
trong khi không có vấn đề gì khác trên đường dẫn chuyển đổi thông thường, không giống như giải pháp mẫu
struct A {
operator int*() { return 0; }
private:
typedef void fty();
operator fty*() { return 0; }
};
Lưu ý rằng các giải pháp này chỉ cần cho các trình biên dịch không phù hợp.
Bạn sẽ làm điều đó, đúng không. – GManNickG
g ++ chưa được quyết định, 4.4 không biên dịch, 4.5. Nếu tôi thay đổi loại chuyển đổi thứ hai thành kiểu con trỏ hàm, thì g ++ sẽ chuyển nó thành đúng và dừng lại ở 'delete a'. –
@ Xin cảm ơn, đã thêm :) –