2008-11-02 22 views
6

Tôi đã sử dụng một cái gì đó như sau để soạn chính sách cho ứng dụng của tôi:Làm thế nào để sử dụng boost :: mpl để soạn chính sách?

Các lớp chính sách giống như thế này:

struct Policy { 
    static void init(); 
    static void cleanup(); 
    //... 
}; 

template <class CarT, class CdrT> 
struct Cons { 
    static void init() { 
    CarT::init(); 
    CdrT::init(); 
    } 
    static void cleanup() { 
    CdrT::cleanup(); 
    CarT::cleanup(); 
    } 
    //... 
}; 

Để soạn chính sách:

typedef Cons<Policy1, Cons<Policy2, Cons<Policy3, Policy4> > > MyPolicy; 

Để sử dụng MyPolicy:

init_with<MyPolicy>(...); 
//... 
cleanup_with<MyPolicy>(...); 

nơi họ sẽ gọi:

MyPolicy::init_options(); // calls Policy1 to 4's init in order 

MyPolicy::cleanup(); // calls Policy1 to 4's cleanup in reverse order 

Về cơ bản, Nhược điểm xây dựng một danh sách loại ở đây. Nó khá thẳng về phía trước. Tuy nhiên dòng consedef cons là kinda xấu xí. Nó sẽ là lý tưởng để có bộ kết hợp chính sách có thể làm điều này:

typedef CombinePolicy<Policy1, Policy2, Policy3, Policy4> MyPolicy; 

Kể từ khi chúng ta có thể có số lượng tùy ý các chính sách, các CombinePolicy sẽ cần mẫu hỗ trợ variadic trong C++ 0x, mà chỉ có sẵn nghiệm trong việc cắt giảm biên dịch cạnh. Tuy nhiên, có vẻ như là tăng: thư viện mpl giải quyết/làm việc xung quanh vấn đề bằng cách sử dụng một thủ thuật tiền xử lý bó. Tôi đoán tôi có thể sử dụng một cái gì đó như:

typedef mpl::list<Policy, Policy2, Policy3, Policy4> Policies; 

và sau đó gọi:

init_with<Policies>(...); 

mà sau đó sẽ sử dụng:

typedef iter_fold<Policies, begin<Policies>::type, 
        some_magic_lambda_expression>::type MyPolicy; 

Rõ ràng, tôi có một chút rắc rối tìm ra some_magic_lambda_expression tại đây. Tôi chắc rằng nó khá tầm thường đối với các chuyên gia mpl ở đây.

Xin cảm ơn trước.

Trả lời

1

Tôi nghĩ rằng vấn đề của bạn là yêu cầu thời gian chạy khá hơn so với metafunctions, bởi vì bạn muốn gọi hàm init trên các đối tượng thời gian thực tế.

Bạn có thể thử các thuật toán thời gian chạy của mpl, như:

for_each<Policies>(InitPolicy()); 

với

struct InitPolicy() { 
    template<class Policy> 
    void operator() (Policy& p) { p.init_options(); } 
}; 
+0

Có một lỗi nhỏ trong ví dụ của bạn. Điều này có thể làm cho ví dụ. Tôi có thể sử dụng for_each cho mỗi phương pháp. Nhưng những gì tôi thích có một chính sách kết hợp có thể được thông qua xung quanh, nghĩa là, tôi thích thứ tự được thực thi tại thời gian biên dịch hơn là thời gian chạy với for_each. – ididak

+0

Như tôi thấy, bạn chỉ có thể gọi các metafunctions tại thời gian biên dịch, tôi không thấy cách gọi init_options() hoặc bất kỳ hàm thuần nào khác tại thời gian biên dịch. Tôi hiểu rằng bạn muốn tự động áp dụng tất cả các Chính sách trong danh sách Chính sách bằng cách gọi init_with khi chạy, đó là những gì for_each thực hiện. xin vui lòng làm rõ – tabdamage

+0

Mục đích là để soạn một lớp chính sách tại thời gian biên dịch với lệnh được thực thi như trong ví dụ ban đầu của tôi và các phương thức thực sự được gọi vào thời gian chạy như MyCombinedPolicy :: init_options() v.v. – ididak

1

Tôi nghĩ rằng bạn đang tìm kiếm cái gì đó như:

typedef 
    iter_fold< 
    Policies, 
    begin<Policies>::type, 
    Cons<_1,_2> 
    >::type 
    MyType; 

Bạn cũng có có thể muốn xem xét inherit_linearly<> nếu bạn đăng nhập một số loại CRTP để gọi các chức năng của cơ sở có dây cứng tại thời gian biên dịch.

+0

Đó là dự đoán ban đầu của tôi, nhưng tôi không nghĩ rằng điều này là chính xác (sẽ không biên dịch vv) mặc dù. Ngoài ra tôi không nghĩ rằng inherit_linearly phù hợp với mô hình ở đây. Tôi muốn làm thành phần tầm thường và khai báo. Một chuỗi loại sẽ là dễ nhất. – ididak

9

Vì không ai trả lời câu hỏi một cách thỏa đáng, tôi đã dành đôi khi đào vào nguồn tăng :: mpl. Người đàn ông, nó không đẹp với các lớp macro và hàng trăm dòng chuyên môn.Bây giờ tôi có sự đánh giá cao hơn cho các tác giả của các thư viện tăng cường để làm cho lập trình meta dễ dàng hơn và dễ dàng hơn cho chúng ta. Hy vọng rằng C++ 0x sẽ làm cho cuộc sống của các nhà văn thư viện trở nên dễ dàng hơn.

Dù sao, giải pháp hóa ra trở nên đơn giản và thanh lịch.

Lần đầu tiên iter_fold không phải là những gì tôi muốn, vì tôi không thể tìm ra cách chỉ định một trình lặp có thể được trì hoãn đến một loại null. Vì vậy, tôi fiddled xung quanh với lần và tìm như sau:

typedef fold<Policies, Null, Cons<_1, _2> >::type MyPolicy; 

Để cho tiện làm việc, tôi cần phải cung cấp các loại Null và chuyên môn hóa cho Nhược điểm:

struct Null { }; 

template<class PolicyT> 
struct Cons<Null, PolicyT> { 
    static void init() { PolicyT::init(); } 
    static void cleanup() { PolicyT::cleanup(); } 
}; 
+0

thanh lịch, tôi đồng ý. trông giống như Alexandrescus type_list. Ở một mức độ nhất định, phép thuật cần thiết để làm cho mọi thứ vô hình đối với người dùng khá là phiền phức ... – tabdamage

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