2010-10-21 32 views
9

Tôi đang bối rối về những ưu điểm của việc sử dụng cácƯu điểm của việc sử dụng tăng :: mpl :: bool_ thay vì một bool const

bool_<true> 

bool_<false> 

loại chống chỉ đơn giản là sử dụng bools const trong bối cảnh lập trình meta mẫu.

Thư viện boost :: mpl rõ ràng thích cách tiếp cận đầu tiên và xác định các hàm trợ giúp như and_, or_ để giúp quản lý bool_ như vậy. Các metafitional có điều kiện như if_ "take" một đối số bool_ như là đầu tiên (mẫu), nhưng đằng sau hậu trường "gọi" một hàm if_c metaf mà dự kiến ​​một (const) bool là đối số đầu tiên (mẫu).

Các đối số đằng sau quyết định này là gì?

Cảm ơn bạn trước sự giúp đỡ của bạn!

Trả lời

11

Dưới đây là ví dụ ngắn, cách tôi sử dụng các loại này ngay bây giờ. Ví dụ này sẽ không thể thực hiện, sử dụng const bool:

void do_something(boost::mpl::bool_<true>) 
{ 
    ... 
} 

void do_something(boost::mpl::bool_<false>) 
{ 
    ... 
} 

Gọi một trong hai chức năng này tùy thuộc vào loại đối số:

template<class T> 
void doIt(void) 
{ 
    do_something(boost::mpl::bool_<boost::is_pointer<T>::val>()) 
} 

Trong trường hợp này hoặc là người đầu tiên hoặc chức năng thứ hai sẽ được gọi, tùy thuộc vào thực tế nếu loại T là một con trỏ hay không. Các kiểu này cho phép bạn sử dụng chức năng quá tải, nơi nó sẽ không thể sử dụng một bool const. Với một bool const bạn sẽ phải quyết định thời gian chạy, nhánh nào cần thực hiện. Điều này đặc biệt quan trọng nếu các hàm được gọi là các khuôn mẫu, các mẫu này sẽ không biên dịch chính xác, nếu chúng được khởi tạo cho các loại khác ngoài dự kiến, ví dụ: định nghĩa hàm đầu tiên ở trên có thể chứa mã, chỉ biên dịch cho con trỏ.

+0

Cảm ơn bạn đó là một ví dụ tốt! – stepelu

+0

Ồ vâng, tôi quên mất quá tải! – sbi

+2

Đây là một câu trả lời hay nhưng có nhiều chi tiết hơn là cần thiết. Bạn có thể viết 'do_something (boost :: is_pointer ())', sẽ làm điều tương tự theo cách tương tự. –

2

Tôi cho rằng một lý do là bool_<...> nhiều loại, và khi sử dụng chúng như kết quả của một chức năng meta, bạn sẽ không bao giờ phải dừng lại và suy nghĩ xem kết quả của bạn là một loại và bạn phải làm

typedef some_type result; 

hoặc giá trị, phải được trả lại là

const static ??? result = some_value; 

nơi bạn cũng phải theo dõi loại.

Ngoài ra, tôi nghi ngờ (Tôi chưa từng làm việc với Boost.MPL chưa) mà cả hai đều có một loại result lồng nhau đề cập đến bản thân, do đó bạn có thể viết các chức năng meta bằng cách chỉ bắt nguồn từ họ:

template< bool b > 
struct my_meta_func : bool_<b> {}; 

và có thể gọi my_meta_func::result.

+0

Bạn phải vào, chỉ có kết quả luôn được gọi là ':: type' trong MPL. –

8

Đó là tất cả về việc tạo tính đồng nhất đủ để thư viện có thể cung cấp chức năng hữu ích. Giao thức MPL là: "tất cả các đối số metafunction (và trả về) là các kiểu." Điều này cho phép chúng tôi viết một mẫu có thể hoạt động chung trên các metafunctions. Ví dụ, mẫu này chấp nhận bất kỳ metafunction (hoặc bất kỳ metafunction lên đến N đối số trong C++ 03):

template <template <class...> class some_metafunction> 
struct wrapper; 

Khi bạn cho phép một số các đối số mẫu là phi loại, viết một wrapper như vậy trở thành Không thể nào.Để có một ví dụ thực tế về lý do tại sao chúng ta quan tâm, tính đồng nhất này cho phép thư viện tách rời và đánh giá các biểu thức lambda của MPL. Nếu các đối số metafunction được phép không phải là loại, tính năng sẽ không thể thực hiện được, vì sẽ không có cách nào để viết ra tất cả các chuyên môn từng phần cần thiết để gỡ rối mẫu bên ngoài xxx khỏi các đối số của nó ai trong xxx<a1,a2,a3,...>.

Một điều ít thú vị, nếu không kém hợp lệ, một phần lý do là nhiều điều trở nên ít tiết lộ cách chúng tôi đã thực hiện trong MPL. so sánh:

and_<mf0<x,y>, mf1<z>, mf2<x,z> >::value 

vs

mf0<x,y>::value && mf1<z>::value && mf2<x,z>::value 
Các vấn đề liên quan