From: PGK on
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
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
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
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
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! ]

 |  Next  |  Last
Pages: 1 2
Prev: Simplest MetaLoop
Next: Standard library pop()