Prev: Simplest MetaLoop
Next: Standard library pop()
From: PGK on 30 Oct 2009 04:26 Now that I'm rewriting all applicable nested loops as template versions, I asked myself: why do I need to separate the base and inductive cases into two lexically separate template constructs? The "Hello World" that I'm building on looks something like this: template<int i> struct Loop1 { static inline void foo() { std::cout << "i is " << i << ", "; Loop1<i-1>::foo(); } }; template<> struct Loop1<0> { static inline void foo() { std::cout << "i is " << 0 << std::endl; } }; So then I tried the following minimal example code, but it fails with "error: template instantiation depth exceeds maximum of 500"; even when the depth I test appears to me to be only 2. Can anyone please shed light on my grave misunderstanding of template instantiation? Must we have the two distinct templates? template<int i> struct Loop2 { static inline void foo() { if (i>0) { std::cout << "i is " << i << ", "; Loop2<i-1>::foo(); } else { std::cout << "i is " << i << std::endl; } } }; int main(int argc, char *argv[]) { Loop2<1>::foo(); return 0; } -- [ 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 30 Oct 2009 07:40 On 30 Okt., 20:26, PGK <graham.k...(a)gmail.com> wrote: > Now that I'm rewriting all applicable nested loops as template > versions, I asked myself: why do I need to separate the base and > inductive cases into two lexically separate template constructs? The > "Hello World" that I'm building on looks something like this: > > template<int i> > struct Loop1 { > static inline void foo() { > std::cout << "i is " << i << ", "; > Loop1<i-1>::foo(); > } > }; > > template<> > struct Loop1<0> { > static inline void foo() { > std::cout << "i is " << 0 << std::endl; > } > }; > > So then I tried the following minimal example code, but it fails with > "error: template instantiation depth exceeds maximum of 500"; even > when the depth I test appears to me to be only 2. Can anyone please > shed light on my grave misunderstanding of template instantiation? > Must we have the two distinct templates? Yes. Note that template instantiation is a process that happens during compile-time, but your code below uses a run-time test. Without a specialization that stops the recursion the compiler is supposed to instantiate every specialization that requires instantiation. Some examples of preconditions for instantiation are object creation or usage of members. The latter happens below. > template<int i> > struct Loop2 { > static inline void foo() { > if (i>0) { > std::cout << "i is " << i << ", "; > Loop2<i-1>::foo(); > } > else { > std::cout << "i is " << i << std::endl; > } > } > }; > > int main(int argc, char *argv[]) > { > Loop2<1>::foo(); > return 0; > } 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! ]
From: Neil Butterworth on 30 Oct 2009 07:41 PGK wrote: > Now that I'm rewriting all applicable nested loops as template > versions Would you care to explain why you would want to do this? Neil Butterworth -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Nick Hounsome on 31 Oct 2009 08:16 On 30 Oct, 19:26, PGK <graham.k...(a)gmail.com> wrote: > Now that I'm rewriting all applicable nested loops as template > versions, I asked myself: why do I need to separate the base and > inductive cases into two lexically separate template constructs? The > "Hello World" that I'm building on looks something like this: > > template<int i> > struct Loop1 { > static inline void foo() { > std::cout << "i is " << i << ", "; > Loop1<i-1>::foo(); > } > > }; > > template<> > struct Loop1<0> { > static inline void foo() { > std::cout << "i is " << 0 << std::endl; > } > > }; > > So then I tried the following minimal example code, but it fails with > "error: template instantiation depth exceeds maximum of 500"; even > when the depth I test appears to me to be only 2. Can anyone please > shed light on my grave misunderstanding of template instantiation? > Must we have the two distinct templates? > > template<int i> > struct Loop2 { > static inline void foo() { > if (i>0) { > std::cout << "i is " << i << ", "; > Loop2<i-1>::foo(); > } > else { > std::cout << "i is " << i << std::endl; > } > } > > }; > > int main(int argc, char *argv[]) > { > Loop2<1>::foo(); > return 0; > > } You need the Loop2<0> specialisation just as for Loop1 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: PGK on 1 Nov 2009 22:30
Thanks Daniel, yes that does help: > Yes. Note that template instantiation is a process that happens > during compile-time, but your code below uses a run-time test. > Without a specialization that stops the recursion the compiler > is supposed to instantiate every specialization that requires > instantiation. Some examples of preconditions for instantiation > are object creation or usage of members. The latter happens > below. The only question I am left with is, why exactly does the compiler stop there? By that I don't mean that it should, but rather, is it part of the C++ standard; or a design choice of my compiler? For example, it seems like in this example the compiler could determine that, as "i" is a constant, and the only instantiation is with a "1" ( i.e. Loop2<1>::foo() ), only two instances need to be built. Best regards, Graham template<int i> struct Loop2 { static inline void foo() { if (i>0) { std::cout << "i is " << i << ", "; Loop2<i-1>::foo(); } else { std::cout << "i is " << i << std::endl; } } }; int main(int argc, char *argv[]) { Loop2<1>::foo(); return 0; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |