последовательность mpl и рекурсивная генерация кода

#c #boost #recursion #metaprogramming

#c #повышение #рекурсия #метапрограммирование

Вопрос:

Допустим, у меня есть последовательность MPL types длиной N
(например boost::variant<int,string,double> , и последовательность типов boost::variant::types ):

Я хотел бы рекурсивно сгенерировать следующий код для каждого возможного индекса. Именно то, что операторы if выполняются до w==N

 void make(int w){

    if(w == 0){
      typename boost::mpl::at_c<types,0>::type t;
      // Some code
    }else if (w==1){
      typename boost::mpl::at_c<types,1>::type t;
      // Some code
    }...
     .
     .
     .
    }else if(w==N){
      typename boost::mpl::at_c<types,2>::type t;
      // Some code
    }else{
      // Runtime ERROR
    }
}
 

Как я могу этого добиться?

Ответ №1:

Как общее эмпирическое правило, поскольку вы пытаетесь что-то делать во время компиляции, ваша рекурсия также будет выполняться во время компиляции. Это сразу подразумевает, что вам понадобится статическая (типовая) функция, которая реализует рекурсию и условие остановки.

Если вы хотите получить код, аналогичный тому, что показывает ваш псевдокод, вы можете использовать Boost Fusion, который содержит алгоритмы, имитирующие знакомые алгоритмы выполнения, например boost::fusion::for_each .

В Fusion также есть ассоциативные коллекции ( boost::fusion::map<...> ), которые могут соответствовать вашему варианту использования.

Комментарии:

1. (публикую это уже из-за нехватки времени. Возможно, я найду время для уточнения примера позже)

2. это было бы действительно полезно!

Ответ №2:

 template <int N>                                                                                                                                                                                          
void make(int w)                                                                                                                                                                                          
{                                                                                                                                                                                                         
  if(w>N)                                                                                                                                                                                                 
  {                                                                                                                                                                                                       
    make<-1>(w);                                                                                                                                                                                      
  }                                                                                                                                                                                                       
  if(w==N)                                                                                                                                                                                                
  {                                                                                                                                                                                                       
    typename boost::mpl::at_c<types, N>::type t;                                                                                                                                                    
    // Some code                                                                                                                                                                            
  }                                                                                                                                                                                                       
  else                                                                                                                                                                                                    
    make<N-1>(w);                                                                                                                                                                                         
}                                                                                                                                                                                                         

template <>                                                                                                                                                                                               
void make<-1>(int w)                                                                                                                                                                                      
{                                                                                                                                                                                                         
  // Runtime ERROR                                                                                                          
}
 

РЕДАКТИРОВАТЬ : включен комментарий sehe.

Комментарии:

1. вы могли бы удалить дублирование, вызвав make<-1>(0) if (w>N)