Prev: Is this correct C++?
Next: Simplester MetaLoop
From: PGK on 28 Oct 2009 08:13 I've written a simple template metaprogramming loop (below) using a struct template which requires a loop index, and two function signatures; one for the base (zero) case, and one for the inductive (ith) case. As you can see below, I start things off with a call like this: Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); and the output is: Hello from f1(2). Hello from f1(1). Hello from f2(0.123). My question is, can I reconfigure this code so that I don't have to explicitly specify the types of the two function pointers? For example, something "like": Loop2<2>::foo(f2,f1); Cheers, P. inline void f1(int i) { std::cout << "Hello from f1(" << i << ")." << std::endl; } inline double f2(double d) { std::cout << "Hello from f2(" << d << ")." << std::endl; } template<typename BaseFunc, typename InductiveFunc, int i> struct Loop2 { static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { iFunc(i); Loop2<BaseFunc,InductiveFunc,i-1>::foo(bFunc,iFunc); } }; template<typename BaseFunc, typename InductiveFunc> struct Loop2<BaseFunc,InductiveFunc,0> { static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { bFunc(0.123); } }; int main(int argc, char *argv[]) { Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); return 0; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mateusz Adamczyk on 29 Oct 2009 01:51 On 29 Paź, 00:13, PGK <graham.k...(a)gmail.com> wrote: > ... For example, something "like": Loop2<2>::foo(f2,f1); You can use fact, that for functions template parameters can be deducted by compiler. So when You change both function types from being parameters of struct Loop2, to be parameters of its member function foo, You get desired syntax (see example). Regards, Mateusz > > inline void f1(int i) { std::cout << "Hello from f1(" << i << > ")." << std::endl; } > inline double f2(double d) { std::cout << "Hello from f2(" << d << > ")." << std::endl; } > > template<typename BaseFunc, typename InductiveFunc, int i> > struct Loop2 { > static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { > iFunc(i); > Loop2<BaseFunc,InductiveFunc,i-1>::foo(bFunc,iFunc); > } > > }; template<int i> struct Loop2 { template<typename BaseFunc, typename InductiveFunc> static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { iFunc(i); Loop2<i-1>::foo(bFunc,iFunc); } }; > template<typename BaseFunc, typename InductiveFunc> > struct Loop2<BaseFunc,InductiveFunc,0> { > static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { > bFunc(0.123); > } > > }; template<> struct Loop2<0> { template<typename BaseFunc, typename InductiveFunc> static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { bFunc(0.123); } }; > > int main(int argc, char *argv[]) { > Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); > return 0; > > } int main(int argc, char *argv[]) { Loop2<2 >::foo(f2,f1); return 0; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 29 Oct 2009 04:53 On 29 oct, 00:13, PGK <graham.k...(a)gmail.com> wrote: > > Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); > > and the output is: > > Hello from f1(2). > Hello from f1(1). > Hello from f2(0.123). > > My question is, can I reconfigure this code so that I don't have to > explicitly specify the types of the two function pointers? For > example, something "like": Loop2<2>::foo(f2,f1); Sure, just use a template function that will be able to infer the template parameters. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Vidar Hasfjord on 29 Oct 2009 04:54 On Oct 28, 11:13 pm, PGK <graham.k...(a)gmail.com> wrote: > I've written a simple template metaprogramming loop [...] > > [Loop2 <double (*)(double), void (*)(int), 2>::foo (f2,f1);] > > My question is, can I reconfigure this code so that I don't have to > explicitly specify the types of the two function pointers? For > example, something "like": Loop2<2>::foo(f2,f1); Sure, you can exploit function template argument deduction: template <int i, typename BaseFunc, typename InductiveFunc> void static_loop (BaseFunc fb, InductiveFunc fi) { Loop2 <BaseFunc, InductiveFunc, i>::foo (fb, fi); } int main (int, char*[]) { static_loop <2> (f2, f1); return 0; } Regards, Vidar Hasfjord -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 29 Oct 2009 04:56
On 29 Okt., 00:13, PGK <graham.k...(a)gmail.com> wrote: > I've written a simple template metaprogramming loop (below) using a > struct template which requires a loop index, and two function > signatures; one for the base (zero) case, and one for the inductive > (ith) case. As you can see below, I start things off with a call like > this: > > Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); > > and the output is: > > Hello from f1(2). > Hello from f1(1). > Hello from f2(0.123). > > My question is, can I reconfigure this code so that I don't have to > explicitly specify the types of the two function pointers? For > example, something "like": Loop2<2>::foo(f2,f1); > > Cheers, > P. > > inline void f1(int i) { std::cout << "Hello from f1(" << i << > ")." << std::endl; } > inline double f2(double d) { std::cout << "Hello from f2(" << d << > ")." << std::endl; } A function that returns a non-void result which normally exits without return causes undefined behaviour. > template<typename BaseFunc, typename InductiveFunc, int i> > struct Loop2 { > static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { > iFunc(i); > Loop2<BaseFunc,InductiveFunc,i-1>::foo(bFunc,iFunc); > } > }; > > template<typename BaseFunc, typename InductiveFunc> > struct Loop2<BaseFunc,InductiveFunc,0> { > static inline void foo(BaseFunc bFunc, InductiveFunc iFunc) { > bFunc(0.123); > } > }; > > int main(int argc, char *argv[]) { > Loop2<double (*)(double), void (*)(int), 2 >::foo(f2,f1); > return 0; > } My first idea would be to split the iteration template parameter from the actual functor types: template<int i> struct Loop2 { template<typename BaseFunc, typename InductiveFunc> static void foo(BaseFunc bFunc, InductiveFunc iFunc) { iFunc(i); Loop2<i-1>::foo(bFunc,iFunc); } }; template<> struct Loop2<0> { template<typename BaseFunc, typename InductiveFunc> static void foo(BaseFunc bFunc, InductiveFunc iFunc) { bFunc(0.123); } }; int main() { Loop2<2>::foo(f2,f1); } HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |