Рекурсия шаблона метапрограммирования не повторяется (отредактировано важно) - PullRequest
0 голосов
/ 12 января 2011


Я пытаюсь вызвать функцию void set (...) рекурсивно, используя метапрограммирование.
Проблема в том, что она вызывается только один раз.

template <int N>
struct GEN
{
    enum {value = GEN<N-1>::value};
    template <typename T> 
    static inline void set(T& tup, int l_item) 
    { 
        cout<<"item value: "<<l_item<<", N-1: "<< N-1 << ",  value: "<<value <<endl;
        typedef typename boost::tuples::element<N-1, T>::type _el_type;
        get<N-1>(tup) = atomic_item<N-1, _el_type>(l_item); 
    };
};

template<>
struct GEN<0>
{
    enum {value = 0};
    template <typename T> 
    static inline void set(T& tup, int l_item) 
    {
        typedef typename boost::tuples::element<0, T>::type _el_type;
        get<0>(tup) = atomic_item<0, _el_type>(l_item); 
    };
};

main(){
....
/** this is how i try to invoke it */
GEN<3>::set(w,1);
}

Вывод:

значение элемента: 1, N-1: 2, значение: 0

Функция вызывается только один раз ...

РЕДАКТИРОВАТЬ

Есть ли способ сделать цикл с for_each или что-то еще, чтобы получить что-то похожее:

for_each<range_c<int,0,3> f{operator()(T i)GEN<typename T::value>::set(w,1)}>

или что-то подобное для достижения вызова для всех этих элементов?

В частности, я хотел бы иметь это:

GEN<3>::set(w,1);
GEN<2>::set(w,1);
GEN<1>::set(w,1);

В цикле.

Ответы [ 2 ]

2 голосов
/ 12 января 2011

рекурсии нет. Рекурсия означает называть себя. Функция set в вашем коде делает , а не делает это.

Ваша value декларация делает рекурсивную (т. Е. GEN<N>::value определяется в терминах GEN<N -1>::value) - но довольно неинтересным образом она просто передает значение базового случая, 0 - и более Похоже, вы все равно не используете это значение.

/ РЕДАКТИРОВАТЬ: Вот очень простой пример для рассмотрения вопроса, поднятого вами в комментариях, то есть для достижения эффекта

GEN<3>::set(w,1);
GEN<2>::set(w,1);
GEN<1>::set(w,1);

Это на самом деле довольно просто:

template <unsigned N>
struct GEN {
    template <typename T>
    static void set(T& w, int value) {
        // Do something, e.g.:
        get<N - 1>(w) = value;
        // Recurse:
        GEN<N - 1>::set(w, value);
    }
};

template <>
struct GEN<0> {
    template <typename T>
    static void set(T&, int) { /* empty */ }
};

Теперь вы можете вызывать этот код через GEN<3>::set(w, 1), и он будет иметь желаемую семантику.

1 голос
/ 12 января 2011

Шаблон метапрограммирования, очевидно, сделал рекурсию, так как ваш код скомпилирован и запущен.

Вы ожидали рекурсивного вызова функции set? Вызванная вами функция GEN<3>::set не вызывает функцию set какого-либо другого класса, поэтому рекурсия во время выполнения отсутствует. Существует только рекурсия во время компиляции для создания экземпляров шаблонов. Но рекурсия во время компиляции не генерирует вывод во время выполнения.

...