From: Bart van Ingen Schenau on
PGK wrote:

> 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?

The limit on the template instantiation limit is a design choice by the
compiler, and I believe there are options for GCC to change that
maximum.
The reason they have a maximum at all, is because people prefer to get a
nice message that something is wrong with their code rather than a
computer that crawls to a halt or a crashing 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.

But, when the compiler is instantiating the templates, it must assume
that every line in the templated code will be present in the final
executable (because there are some compilers around that don't eliminate
unreachable code, and you don't want the validity of a construct to
depend on the optimisations that a compiler might or might not perform),
so when instantiating Loop2<1>::foo(), the compiler sees it needs
Loop2<0>::foo(), that in turn needs Loop2<-1>::foo(), that in turn needs
.... (ad nauseam).

>
> Best regards,
> Graham
>
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

[ 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 2 Nov., 16:30, PGK <graham.k...(a)gmail.com> wrote:
> 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.

Your compiler behaves according to the rules of the standard.
Regarding the situation in your example it is completely
irrelevant, whether there is an if branch or not, the compiler
is supposed to instantiate the complete code in the foo
function, if this is instantiated. There is no concept of
partial instantiation of the implementation of a function in C++.

> 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;
> }

The compiler is supposed to do the following:
Your main function /uses/ Loop2<1> in a way that
requires instantiation (call of a member function).
This usages requires a complete definition of
Loop2<1>::foo(). Now the compiler starts instantiating
the *implementation* of Loop2<1>::foo(). During that
process it recognizes that this implementation
/uses/ Loop2<0>::foo() (again: Call of a member function)
etc. ad infinitum, because each such foo again /uses/ one
not yet instantiated specialization of Loop2.

There are situations where a template shall not be
instantiated, e.g. consider a (quite useless) variant of
your example:

template<int i>
struct Loop2 {
static void foo() {
typedef Loop2<i-1> type;
if (i>0) {
std::cout << "i is " << i << std::endl;
}
}
};

I present it just to point out the difference between
/using/ an entity in C++ and not using one. The
typedef above does not require instantiation and
a compiler is not allowed to try to perform instantiation
in this specific situation.

Your reasoning regarding that i is a constant does not
help here, because in C++ there is no concept of a
compile-time sub-block. You can realize the same effect
with a bit more work by using a compile-time-if.

#include <iostream>

template<bool value, class TrueT, class FalseT>
struct if_c {
typedef FalseT type;
};

template<class TrueT, class FalseT>
struct if_c<true, TrueT, FalseT> {
typedef TrueT type;
};

template<int i>
struct Stop {
static void foo(){
std::cout << "i is " << i << std::endl;
}
};

template<int i>
struct Loop2 {
static void foo() {
std::cout << "i is " << i << ", ";
if_c<(i>0), Loop2<i-1>, Stop<i> >::type::foo();
}
};

int main()
{
Loop2<1>::foo();
}

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

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