2010-11-09 31 views
8

Tôi đang gặp phải vấn đề sau. Hãy xem xét các lớp sau:Không cho phép lấy con trỏ/tham chiếu đến const đến một đối tượng tạm thời trong C++ (không có C++ 0X)

//Will be similar to bost::reference_wrapper 
template<class T> 
class Ref { 
public: 
    explicit Ref(T& t) : m_ptr(&t) {} 
private: 
    T* m_ptr; 
}; 

và chức năng này trả về một đôi

double fun() {return 1.0;} 

Nếu bây giờ chúng ta có

double x = 1.0; 
const double xc = 1.0; 

Ref<double> ref1(x); //OK 
Ref<const double> refc1(cx); //OK 

tốt cho đến nay, tuy nhiên:

//Ref<double> ref2(fun()); //Fails as I want it to 
Ref<const double> refc2(fun()); //Works but I would like it not to 

Is có cách sửa đổi Ref (cách bạn thích) nhưng không phải là chức năng thú vị, để dòng cuối cùng trả về một lỗi biên dịch thời gian? Xin lưu ý rằng bạn có thể sửa đổi chữ ký hàm tạo (miễn là tôi có thể khởi tạo Ref như dự định).

Trả lời

2

Bạn có thể không thích cú pháp để sử dụng, nhưng làm cho hàm tạo lấy con trỏ thay vì tham chiếu. Bạn không thể lấy ngay cả một con trỏ const đến một tạm thời.

Ít nhất, không phải không có buôn lậu nó thông qua một wrapper mà hy vọng làm cho đoạn code rõ ràng là sai (TM): template <typename T> T *reftoptr(T &t) { return &t; }

Điều đó nói rằng, nếu bạn đang sử dụng theo cách này reference_wrapper được sử dụng, người dùng của bạn có thể thực sự muốn để ghi lại thời gian. Miễn là đối tượng Ref cũng là một tạm thời trong cùng một biểu thức đầy đủ như tạm thời nó chụp, tôi nghĩ rằng đó là OK. Ví dụ:

some_algorithm(iterator, anotherit, static_cast<Ref<const double> >(fun())); 
+0

Đây là (đối với tôi) gần nhất với vấn đề đã nêu (với những cân nhắc thú vị, đặc biệt là mới nhất), cảm ơn sự giúp đỡ của bạn! – stepelu

3

Không và mã của bạn có thể bị hỏng ngay cả khi có tham chiếu bình thường. Đơn giản chỉ cần ghi lại sự thật, rằng đối tượng được truyền phải kiên trì.

double *x = new double; 
Ref<double> ref(*x); 
delete x;  
+0

+1. Ghi rõ trong tài liệu hướng dẫn cách sử dụng. Nhưng đó không phải là trách nhiệm của bạn đối với việc lạm dụng lớp học của bạn. – ereOn

+0

Mục đích của hạn chế này là giúp người dùng. Vì nó khá dễ dàng để giúp người dùng trong trường hợp này, tôi không nghĩ rằng nó nên được loại bỏ khỏi tầm tay. Loại bỏ nó theo chiều dài, đầy đủ chi tiết, nếu có một số lý do tại sao nó không giúp người dùng sau khi tất cả ;-) –

1

Sử dụng đối số con trỏ để khởi tạo thành viên trỏ chuột của bạn. Không sử dụng tham chiếu (const) cho điều này - sử dụng một con trỏ để khởi tạo một con trỏ.

Tôi đã có một số vấn đề với sự tham khảo theo dõi trong quá khứ, và trong khi nó không liên quan trực tiếp đến câu hỏi của bạn, bạn có thể tìm thấy hai chủ đề này thú vị:

0

Bạn có thể sử dụng mẫu. U& được khấu trừ thành double& và điều đó sẽ không ràng buộc với giá trị.

template<class T> 
class Ref { 
public: 
    template<typename U> 
    explicit Ref(U& t, 
       typename boost::enable_if< 
       boost::is_convertible<U, T&> 
       >::type * = 0) 
    : m_ptr(&t) {} 
private: 
    T* m_ptr; 
}; 
Các vấn đề liên quan