2012-02-02 24 views
8

Tôi cần truyền một biến số any cho loại ban đầu. tôi cần phải làm điều này:Boost.Any get original type

int i = 10; 
any a(i); 
int& i2 = any_cast<int &>(a); 

Nhưng tôi muốn rằng các cửa hàng gõ vào any biến. Và tôi viết điều này:

int i = 10; 
any a(i); 
a::type_value& i2 = any_cast<a::type_value &>(a); // there is no actually type_value 

Tôi có thể làm điều gì đó như thế? Hoặc làm thế nào tôi có thể trích xuất kiểu gốc từ biến số any? Boost.variant cũng thuận tiện.

Nếu tôi không thể làm điều đó, thì tôi có một câu hỏi khác về kỹ thuật và thư viện C++ có thể lưu trữ và nhận loại thông qua một hàm để giải quyết vấn đề này?

+1

Bạn chỉ đơn giản là _can't_ làm điều này với Boost.Any, do đó, sử dụng Boost.Variant thay vì sẽ là câu trả lời cơ bản. – ildjarn

+2

* Tại sao * bạn có cần phải làm điều này? – GManNickG

Trả lời

15

C++ là statically ngôn ngữ đã nhập. Loại số boost::any là giá trị thời gian hoạt động ; bất kỳ any cụ thể nào cũng có thể có bất kỳ loại nào. Đó là kinda điểm.

Không có any::type_value, vì đó sẽ phải là thời gian biên dịch . Và any là cấu trúc thời gian chạy.

Hãy xem xét điều này:

void TakeAnAny(boost::any a) 
{ 
    a::type_value& i2 = any_cast<a::type_value &>(a); 
} 

là loại gì any::type_value? Việc gọi TakeAnAny với hầu như bất kỳ loại nào là đều hợp pháp. Không có loại biên dịch đơn lẻ mà any::type_value có thể giảm xuống. Và do đó, không có cách nào để trình biên dịch xác định loại. Kể từ khi C++ được gõ tĩnh, bạn đang hosed.

Mục đích cuối cùng của bất kỳ là loại tẩy xóa. Tôi có một số giá trị. Và tôi muốn truyền điều đó cho một số chức năng khác. Quá trình này sẽ trải qua một số lớp giao tiếp khác nhau. Nhưng tôi không nhất thiết muốn tất cả những lớp khác nhau đó biết chính xác loại tôi đang sử dụng. Tôi chỉ cần bản thân mình và điểm đến dự định của tôi để biết loại. Vì vậy, bạn dính nó vào một any và bạn ổn. Mọi người khác chỉ nhìn thấy any và cả hai bạn đều biết nó kết thúc tốt đẹp.

Quy trình này chỉ hoạt động vì cả nguồn và đích đều biết loại giá trị thực. Nếu bạn không biết loại, thì bạn không nên sử dụng any. Mục đích của any không có chức năng ngồi ở đó và đưa nó vào một loạt các loại có thể (đó là những gì boost::variant là dành cho). Mục đích là để xóa các loại từ chữ ký của một hàm.

Điều này cho phép những thứ như tin nhắn và tín hiệu chung. Bạn đăng ký một số xử lý sự kiện với một hệ thống. Bạn kích hoạt sự kiện mất một tham số any. Người kích hoạt sự kiện biết rằng sự kiện "Nhấp chuột" luôn luôn có tham số vec2. Vì vậy, mọi trình xử lý "MouseClick" sẽ chuyển nó thành một số vec2. Sự kiện "KeyPress" có thể vượt qua int32_t. Vì vậy, những người xử lý đúc nó vào loại đó. Và kể từ đó trở đi. Mọi người đều biết những gì loại nó thực sự mất.

Việc này được thực hiện với void*. Vấn đề ở đây là bạn có các vấn đề về quyền sở hữu (any là một giá trị, trong khi void* là một con trỏ). Ngoài ra, một số void* được xóa theo kiểu mà không có cách nào để kiểm tra xem dàn diễn viên của bạn có chính xác hay không. any thực sự chỉ là một loại & giá trị an toàn void*; điều này ngăn bạn truyền sang loại sai.

Bạn thực sự không muốn any. Trường hợp sử dụng của bạn dường như không muốn variant. Những gì bạn muốn là một mẫu . Đó là một loại khác nhau của điều, và nó sẽ cho phép bạn làm những gì bạn thực sự muốn: có một chức năng có thể sử dụng bất kỳ loại cụ thể, trong khi vẫn có thể biết chính xác loại đó là gì.

Tất nhiên, các mẫu có giới hạn riêng.

1

Bạn có thể sử dụng bản đồ của std::type_info để std::function<void(boost::any const&)> đối tượng để xử lý các loại bạn biết và bạn muốn giải quyết: bạn sẽ tìm mục nhập trong bản đồ bằng cách sử dụng a.type() và gọi hàm tương ứng. đối phó với các đối số.

+2

Nếu ai biết về các loại họ sẽ xử lý, thì tại sao một người dùng Boost.Any thay vì Boost.Variant ngay từ đầu? – ildjarn

+1

Dường như một kiểu đơn giản hơn để truyền đi. Ngoài ra, có thể có các giao diện lấy 'boost :: any' làm đối số và cuối cùng gọi một hàm mà' boost :: any' được trả về dưới dạng nào đó. Ví dụ, có vẻ như việc gắn một 'boost :: any' vào một đối tượng để giữ thông tin tùy ý là một điều hợp lý và người dùng của lớp đó có thể biết rõ những kiểu mà anh ta có thể đính kèm. –

+0

Với _that kịch bản cụ thể_ sau đó tôi đồng ý rằng 'boost :: any <>' có thể phù hợp; sau khi tất cả, thư viện không tồn tại vì một lý do. Nhưng bằng cách nào đó tôi nghi ngờ OP là trong kịch bản cụ thể đó, và tôi vẫn sẽ bỏ phiếu cho Boost.Variant trừ khi OP có một lý do cụ thể không khả thi. ; -] – ildjarn