2008-11-02 2 views
6

я использовал что-то вроде следующего, чтобы составить политику для моего приложения:Как использовать boost :: mpl для составления политик?

Классы политики выглядеть следующим образом:

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(); 
    } 
    //... 
}; 

Для создания политики:

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

Чтобы использовать MYPOLICY:

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

где они звонили:

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

и

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

По существу, Cons строит список типов здесь. Это довольно прямолинейно. Однако строка typedef cons выглядит некрасиво. Это будет идеально иметь политики сумматор, который может сделать это:

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

Поскольку мы можем иметь произвольное число политики, CombinePolicy потребуется VARIADIC поддержка шаблонов в C++ 0x, который доступен только экспериментально при резке краевых компиляторов. Тем не менее, кажется, что boost: библиотека mpl решила/работала над проблемой, используя трюки предварительной обработки пучка. Я предполагаю я мог бы использовать что-то вроде:

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

, а затем вызывает:

init_with<Policies>(...); 

которое затем будет использовать:

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

Очевидно, что у меня есть небольшая проблема, выясняя some_magic_lambda_expression здесь. Я уверен, что здесь довольно тривиально для экспертов mpl.

Заранее спасибо.

ответ

1

Я думаю, что ваша проблема скорее скорее вызовом во время выполнения, чем метафайлами, потому что вы хотите вызвать функции init на реальных объектах времени исполнения.

Вы можете попробовать алгоритмы среды выполнения MPL, как:

for_each<Policies>(InitPolicy()); 

с

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

Там есть немного ошибки в ваш пример. Это может сделать работу для примера. Я могу использовать for_each для каждого метода. Но я предпочитаю иметь одну комбинированную политику, которая может быть передана, т. Е. Я предпочитаю, чтобы порядок выполнялся во время компиляции, а не во время выполнения с помощью for_each. – ididak 2008-11-02 17:26:08

+0

Как я вижу, вы можете вызывать только метафайлы во время компиляции, я не вижу способа вызова init_options() или любой другой простой функции во время компиляции. Я понял, что вы хотите автоматическое применение всех политик в списке Policy, вызывая init_with во время выполнения, что и делает for_each. пожалуйста, уточните – tabdamage 2008-11-02 17:32:41

+0

Цель состоит в том, чтобы составить класс политики во время компиляции с порядком, установленным в моем первоначальном примере, и фактически методы действительно вызывается во время выполнения, например MyCombinedPolicy :: init_options() и т. д. – ididak 2008-11-02 17:39:09

1

Я думаю, что вы ищете что-то вроде:

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

Вы также возможно, захотите посмотреть в inherit_linearly<>, если вы используете какой-либо CRTP-код для вызова базовые функции жестко подключены во время компиляции.

9

Поскольку никто не ответил на вопрос удовлетворительно, я провел какое-то время в источнике boost :: mpl. Человек, это не красиво со слоями макросов и сотнями линий классов специализации.Теперь я больше благодарен авторам библиотек повышения, чтобы сделать метапрограммирование проще и более переносимым для нас. Надеюсь, C++ 0x облегчит жизнь библиотечным писателям.

В любом случае, решение оказывается простым и элегантным.

Первый iter_fold - это не то, что я хочу, поскольку я не мог понять, как указать итератор, который может быть отложен до нулевого типа. Таким образом, я возился со складными и найти следующее:

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

Для того, чтобы это работало, мне нужно, чтобы обеспечить Null типа и специализацию Минусы:

struct Null { }; 

template<class PolicyT> 
struct Cons<Null, PolicyT> { 
    static void init() { PolicyT::init(); } 
    static void cleanup() { PolicyT::cleanup(); } 
}; 
Смежные вопросы