2013-11-16 4 views
3

Я пытаюсь реализовать μ-recursive function на шаблонах C++ 11, но у меня проблема с функцией замещения. S<f, g_1, .... g_m>::apl(x_1,... x_n) = f::apl(g_1(x_1,... x_n), ... g_m(x_1,... x_n)); Из-за любого возможного n (числа args) я использую вариационные шаблоны. Я не могу сделать рекурсию в частной функции S, используйте шаблон шаблона шаблона типа S's. Возможно ли это исправить или сделать другим способом? Может быть, с помощью вложенных структур, но функций?Развернуть шаблон шаблона шаблона шаблона в его статической рекурсивной функции

Проблема Код:

template<typename F, typename g, typename ... G> 
struct S{ 
      static void get_g_results(arguments const & input, arguments& output) 
      { 
      } 

/* error is here :no matching function for call to 'get_g_results' 
get_g_results<G...>(v, output); 
candidate template ignored: "could't infer template argument 'q'"*/ 

      template<typename q, typename ... Q> 
      static void get_g_results(arguments const & input, arguments& output) { 
        output.push_back(q::apply(input)); 
        get_g_results<Q...>(input, output); 
      } 

      static nat apply(arguments const & v) { 
        arguments output(1, g::apply(v)); 
        get_g_results<G...>(v, output); 
        return F::apply(output); 
      } 
      template<typename ... T> 
      static nat apl(T ... ret) { 
        return apply(get_arguments(ret...)); 
      } 
} 

S<N,U<2, 1> >::apl(5, 3); 

Все Код:

using namespace std; 
typedef unsigned nat; 
typedef vector<nat> arguments; 
    void get_arguments(arguments &a) 
{ 
    a.size(); 
} 

template<typename ... T> 
void get_arguments(arguments& a,nat first, T ... rest) 
{ 
    a.push_back(first); 
get_arguments(a, rest...); 

} 


template<typename ... T> 
arguments get_arguments(nat first, T ... rest) 
{ 
    arguments a(1, first); 
get_arguments(a, rest...); 
return a; 
} 

template <nat n, nat m> 
struct U{ 
    static const nat arg_num = n; 
    static_assert(n != 0 && m != 0 && n >= m, "invalid template parametrs "); 

    static nat apply(arguments const & v) { 
     assert(v.size() == arg_num); 
     return v[m - 1]; 
    } 

    template<typename ... T> 
    static nat apl(T ... ret) { 
      return apply(get_arguments(ret...)); 
    } 

}; 

struct N { 

    static const nat arg_num = 1; 
    static nat apply(arguments const & v) { 
     assert(v.size() == arg_num); 
     return v[0] + 1; 
    } 

    template<typename ... T> 
    static nat apl(T ... ret) { 
     return apply(get_arguments(ret...)); 
    } 

}; 



template<typename F, typename g, typename ... G> 
struct S{ 
     static const nat arg_num = g::arg_num; 
     static const nat f_arg_num = F::arg_num; 
private: 
     static void get_g_results(arguments const & input, arguments& output) 
     { 
     } 

/* error is here :no matching function for call to 'get_g_results' 
    get_g_results<G...>(v, output); 
    candidate template ignored: "could't infer template argument 'q'"*/ 

     template<typename q, typename ... Q> 
     static void get_g_results(arguments const & input, arguments& output) { 
       output.push_back(q::apply(input)); 
       get_g_results<Q...>(input, output); 

     } 

     static nat apply(arguments const & v) { 
       assert(v.size() == arg_num); 
       arguments output(1, g::apply(v)); 
       get_g_results<G...>(v, output); 
       return F::apply(output); 
     } 
public: 
     template<typename ... T> 
     static nat apl(T ... ret) { 
       return apply(get_arguments(ret...)); 
     } 

}; 


int main(int argc, const char * argv[]) { 
    cout << U<4, 3>::apl(1, 2, 3, 4) << endl;// output: 3 
    cout << N::apl(4) << endl; // output: 5 
    cout << S<N,U<2, 1> >::apl(5, 3) << endl; 
    // error:could't infer template argument 'q' 

    return 0; 
} 
+0

Что такое 'N' в' N :: apl (4) 'и' S > '? (Я не вижу никаких деклараций ..) – dyp

+0

Ну, ошибка возникает здесь: 'get_g_results (v, output);' Когда вы не предоставили никаких аргументов шаблона для 'G', вы не укажете какой-либо шаблон аргумент для 'get_g_results', а' q' требует один (который не может быть выведен из аргументов функции). – dyp

+0

Извините, я забыл про N. Исправлено. Но как я могу это исправить? – Skipor

ответ

2

Это должно сделать трюк:

template<typename F, typename... G> 
struct S { 

    static nat apply(arguments const & args) { 
     arguments output = { G::apply(args)... }; 
     return F::apply(output); 
    } 

    template<typename... T> 
    static nat apl(T... x) { 
     arguments args = { static_cast<nat>(x)... }; 
     return apply(args); 
    } 
}; 

увидеть live demo here!

+0

Ничего себе! Действительно приятное решение. Благодаря!!! – Skipor

Смежные вопросы