f



Simplest MetaLoop

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! ]

0
PGK
10/28/2009 5:13:50 PM
comp.lang.c++.moderated 10738 articles. 1 followers. allnor (8506) is leader. Post Follow

6 Replies
449 Views

Similar Articles

[PageSpeed] 14

On 29 Paź, 00:13, PGK <graham.k...@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! ]

0
Mateusz
10/29/2009 10:51:15 AM
On 29 oct, 00:13, PGK <graham.k...@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! ]

0
Mathias
10/29/2009 1:53:26 PM
On Oct 28, 11:13 pm, PGK <graham.k...@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! ]

0
Vidar
10/29/2009 1:54:34 PM
On 29 Okt., 00:13, PGK <graham.k...@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! ]

0
ISO
10/29/2009 1:56:58 PM
On Oct 29, 1:13 am, PGK <graham.k...@gmail.com> wrote:
> 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);

Just add this:
template<int N, typename BASE_FUNC, typename INDUCTIVE_FUNC>
void Repeat(BASE_FUNC bFunc, INDUCTIVE_FUNC iFunc) {
	Loop2<BASE_FUNC, INDUCTIVE_FUNC, N>::foo(bFunc, iFunc);
}

Which can be called like this:
    Repeat<2>(f2, f1);


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
tohava
10/29/2009 2:17:32 PM
PGK 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);

You could provide a simple helper function that re-orders the template
parameters and uses template argument deduction to deduce the function pointers
for you. As, for example:

    // ...

    template<int i, typename BaseFunc, typename InductiveFunc>
    void loop2_foo(BaseFunc bFunc, InductiveFunc iFunc)
    {
       Loop2<BaseFunc, InductiveFunc, i>::foo(bFunc, iFunc);
    }

    int main()
    {
       loop2_foo<2>(f2, f1);

       // ...
    }

Regards

Paul Bibbings

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Paul
10/30/2009 12:27:09 AM
Reply: