2012-06-07 24 views
11

Giả sử tôi có một lớp học như thế này:Tại sao decltype không được phép trên các biến thành viên riêng tư?

class Foo 
{ 
    std::vector<int> bar; 

public: 
    std::vector<int>& get_bar() { return bar; } 
}; 

và sau đó trở đi, tôi muốn khác ở đâu đó biến khác mà có cùng loại như bar. Điều đó sẽ hợp lý với tôi nếu tôi chỉ có thể làm điều này:

decltype(Foo::bar) clone_of_bar; 

Nhưng điều đó không hiệu quả. Trình biên dịch cho tôi biết 'std :: vector < int> Foo :: bar' là riêng tư.

Vì vậy, tôi sẽ chỉ phải sử dụng một cái gì đó như thế này:

std::remove_reference<decltype(std::declval<Foo>().get_bar())>::type clone_of_bar; 

Những công trình, nhưng trông giống như một mớ hỗn độn đầy đủ. Có lẽ có một cách dễ dàng hơn để làm điều đó; Tôi không chắc lắm. Nhưng điều tôi thực sự muốn biết là tại sao tôi không thể sử dụng decltype(Foo::bar). Tại sao mọi người nên quan tâm rằng bar là riêng tư? Nó không giống như tôi đang thực sự truy cập vào biến.

decltype là tính năng mới của ngôn ngữ. Tôi chỉ không hiểu tại sao nó được thiết kế để không hoạt động trên các biến riêng tư.

+0

tôi thực sự sẽ đánh giá cao nếu bạn có thể cung cấp cho chúng tôi một số ** thực tế ví dụ ** trong đó bạn sẽ được hưởng lợi từ việc sử dụng decltype các thành viên tư nhân. – mfontanini

+0

Vâng, tôi có bất kỳ lý do thực sự vững chắc nào để làm điều này. Đó chỉ là sự tò mò. Nhưng trường hợp mà tôi đã cố gắng sử dụng nó là: Tôi đã sử dụng google protobuf, mà tôi định nghĩa một số loại sự kiện và sau đó protobuf tạo ra một số mã cho các loại đó. Mã được tạo ra trông giống như những gì tôi đã viết trong ví dụ câu hỏi của mình. Vấn đề là, tôi muốn có thể sao chép một số dữ liệu ra khỏi tin nhắn protobuf để làm một số công cụ và tôi không muốn phải thay đổi mã nếu tôi xảy ra để thay đổi loại trong thông điệp protobuf. Đó là điều tôi muốn làm. Không thực sự là một việc lớn mặc dù. – karadoc

+0

Bạn không thể chỉ sử dụng "auto x = somefoo.get_bar();" ? Bạn muốn sao chép, không cung cấp rõ ràng loại "x". – mfontanini

Trả lời

17

Trong điều khoản luật sư ngôn ngữ, bar là tên, để sử dụng nó trong biểu thức decltype trình biên dịch phải thực hiện tra cứu tên bình thường, tuân thủ kiểm soát truy cập.
Tại sao nên decltype được thiết kế khác với phần còn lại của ngôn ngữ? Bạn chưa trình bày bất kỳ lý lẽ thuyết phục nào về lý do tại sao nó không nhất quán với ví dụ. sizeof.

Là tác giả của lớp, tôi không muốn bạn có thể truy vấn chi tiết triển khai riêng tư như vậy. Nếu tôi muốn loại có thể sử dụng được bên ngoài lớp, tôi sẽ định nghĩa một typedef công khai cho bạn biết loại đó là gì.

và sau đó trở đi, tôi muốn khác ở đâu đó biến khác mà có cùng loại như bar

Bạn muốn "một biến" đó là loại giống như một chi tiết thực hiện tư nhân? Vì vậy, nếu tác giả của lớp Foo tái cấu trúc mã của họ và thay thế loại bằng một số chi tiết triển khai khác, đột nhiên mã của bạn thay đổi ý nghĩa và mã không liên quan có thể đột ngột ngừng biên dịch hoặc âm thầm có hành vi khác nhau, vì mã đó ngu ngốc dựa vào các chi tiết cá nhân không có kinh doanh của nó. Điều đó sẽ giới thiệu sự ghép nối giữa các chi tiết thực hiện riêng tư và mã không liên quan mà tác giả của Foo thậm chí có thể không biết tồn tại! Đó là một ý tưởng khủng khiếp.

+0

Điều đó có vẻ như là một ý tưởng hay. Bạn có bất kỳ tài liệu tham khảo mà khẳng định đây là trường hợp xin vui lòng? –

+3

Xác nhận điều gì? 'Thanh' đó là tên và phải được tìm thấy bằng tra cứu tên? Trình biên dịch sẽ biết 'Foo :: bar' như thế nào trong' decltype (Foo :: bar) 'nếu nó không tìm kiếm tên? –

+2

+1, cũng đề xuất sử dụng 'tự động clone = foo.get_bar()' hoặc 'decltype (foo.get_bar()) clone' có thể giúp người dùng? – Klaim

9

decltype(Foo::bar)làm hoạt động bên trong Foo.

Bên ngoài Foo, bạn thậm chí không phải biết rằng Foo có một thành viên mang tên bar (đó là những gì private phương tiện), nên dĩ nhiên nó sẽ không hoạt động.

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