Topic: Template instantiation question
Author: fjh@cs.mu.oz.au (Fergus Henderson)
Date: 1995/08/27 Raw View
clamage@Eng (Steve Clamage) writes:
>tony@online.tmx.com.au (Tony Cook) writes:
>
>>Steve Clamage (clamage@Eng) wrote:
>
>>: In the mean time, you could write a specialization of Foo<X>::compare
>>: that throws an exception or invokes "assert(0)" to allow your code
>>: to compile and link. That is, for example, if you use Foo<complex>,
>>: you could provide the specialization
>>: int Foo<complex>::compare(const complex&) { assert(0); return 0; }
>>: which will prevent the compiler from generating a version from the template,
>>: and will thus allow your program to compile and link.
>
>>Can we instead _declare_ the specialization and not define it:
>
>> extern int Foo<complex>::compare(const complex &);
>
>>So that we see an error at link time rather than run-time?
>
>No. The declaration does not prevent instantiation if any use is made
>of the function. That is, the declaration tells the compiler that
>particular compare function is supposed to exist. If it is needed
>but not found at link time, the system will generate it from the
>template definition.
However, if you're really keen on detecting the error at link time
rather than at runtime, it is possible to do so.
You can put the definition of Foo<complex>::compare() in a compilation
unit of its own, put that compilation unit in a library, and make sure
that the definition references some other bogus function which is
declared but not defined.
extern int Foo<complex>::compare(const complex &) {
extern void this_is_totally_bogus(); // declared but not defined
this_is_totally_bogus();
return 0;
}
That way, if Foo<complex>::compare is referenced, the above compilation
unit will be linked in, and hence you will get an undefined reference
to `this_is_totally_bogus()'.
All things considered, however, I'm not really sure that it's worth the effort.
--
Fergus Henderson | #define x t=a[i],a[i]=a[m],a[m]=t
| char a[]=" 12345678";main(m,i,j,t){for(i=m;i<
fjh@cs.mu.oz.au | 9;x,i++)for(x,j=m;--j?(t=a[m-j]-a[m])-j&&t+j:
http://www.cs.mu.oz.au/~fjh | main(m+1)*0;);m-9||puts(a+1);} /* 8 queens */
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/08/28 Raw View
Distribution:
ncm@netcom.com (Nathan Myers) writes:
>clamage@Eng (Steve Clamage) writes:
>>tony@online.tmx.com.au (Tony Cook) writes:
>>>Can we instead _declare_ the specialization and not define it:
>>
>>> extern int Foo<complex>::compare(const complex &);
>>
>>>So that we see an error at link time rather than run-time?
>>
>>No. The declaration does not prevent instantiation if any use is made
>>of the function. That is, the declaration tells the compiler that
>>particular compare function is supposed to exist. If it is needed
>>but not found at link time, the system will generate it from the
>>template definition.
>(I'm sorry to jump in late.)
>Sorry, I don't think this is right. As I understand it, declaring
>a specialization before every place it is used *does* prevent
>automatic instantiation. It's a violation of ODR (not required
>to be detected) if you miss declaring it first, though, in one or
>more places.
It seems I had two similar things confused. Thanks for the correction.
According to the 28 April draft, if you declare a NON-template
function that matches something that could be generated from the
function template, it does not prevent the generation of the
template instantiation. Example from the draft:
template<class T> T max(T a, T b) { return a > b ? a : b; }
int max(int, int);
The declaration does not prevent generation of max from the template
for type int, which is what I was originally thinking of. The
declaration allows you to write
char c; int i;
...
max(c, i);
and get the effect of
max(int(c), i);
via ordinary overload resolution. Without the declaration, you could
not compare an char with an int without an explicit cast. In this
case you must not define the function max(int,int) because that
function will be generated from the template.
But if you declare an explicit template specialization
int max<int>(int, int);
that DOES prevent the specialization from being generated
automatically. The declaration is in effect a promise that you
will supply a specialization. As Nathan says, you must be careful
to provide this declaration every place the specialization is
needed to prevent the compiler from generating it.
So the answer to the original question is "Yes, that should work".
Technically, the program is ill-formed if the program calls an
undefined function, but realistically the program will just
fail to link -- which is what was wanted.
--
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: Wil Evers <wil@ittpub.nl>
Date: 1995/08/30 Raw View
In article <41vlmh$kat@engnews2.Eng.Sun.COM>, stephen.clamage@Eng.sun.com (Steve
Clamage) wrote:
> In article i3d@engnews2.Eng.Sun.COM, "bnr (n.) postmaster" <postmast@bnr.ca>
writes:
[snip]
> >
> >template<class T>
> >class MyPtrClass {
> > T* ptr;
> >public:
> > // etc...
> > T* operator->(void) { return(ptr); }
> > // etc...
> >};
> >
> >
> >This causes problems on some compilers (e.g. Borland C++ v4.5) if type
> >'T' is does not have "operator->" defined, even if I never call the
> >"operator->" defined above.
>
> I believe the template declaration is valid only when T is a class type.
> Section 13.5.6 "Class Member Access" places requirements on the return type
> of operator->. When the class template is processed, the declaration would be
> invalid even if you never use the function.
>
> Possibly someone could point out something in the draft which makes the
> template valid as long is operator-> is never actually referenced.
Does anyone know why the restriction 'operator->() must return a class type' was
included in the standard, even when its result is never used to access a class
member? After all, this rule makes it impossible to write a smart pointer
template pointing to a type T that works both when T is a class type and when T
is something else.
If there is no clear rationale for this restriction, I think it should be
dropped.
[I think it *has* been dropped. -fjh (moderator).]
- Wil Evers (wil@ittpub.nl)
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1995/08/30 Raw View
Distribution:
In article AA05597@sun4nl.NL.net, Wil Evers <wil@ittpub.nl> writes:
>In article <41vlmh$kat@engnews2.Eng.Sun.COM>, stephen.clamage@Eng.sun.com (Steve
>Clamage) wrote:
>
>>
>> I believe the template declaration is valid only when T is a class type.
>> Section 13.5.6 "Class Member Access" places requirements on the return type
>> of operator->. When the class template is processed, the declaration would be
>> invalid even if you never use the function.
>>
>> Possibly someone could point out something in the draft which makes the
>> template valid as long is operator-> is never actually referenced.
>
>Does anyone know why the restriction 'operator->() must return a class type' was
>included in the standard, even when its result is never used to access a class
>member? After all, this rule makes it impossible to write a smart pointer
>template pointing to a type T that works both when T is a class type and when T
>is something else.
>If there is no clear rationale for this restriction, I think it should be
>dropped.
>
> [I think it *has* been dropped. -fjh (moderator).]
I did some more digging, and found that the rules for operator-> are
relaxed for templates. Section 14.3.3, "Instantiation of operator->" says:
"If a template has an operator->, that operator-> can have a return type that
cannot be dereferenced by -> as long as that operator-> is neither invoked,
nor has its address taken, isn't virtual, nor is explicitly instantiated."
So the orginal example, according to the draft standard if not current
compilers, is allowed.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/08/31 Raw View
Steve Clamage (stephen.clamage@Eng.sun.com) wrote:
: Possibly someone could point out something in the draft which makes the
: template valid as long is operator-> is never actually referenced.
See [temp.opref].
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: bmcphers@alias.com (Brent McPherson)
Date: 1995/08/21 Raw View
Distribution:
I've got a question regarding template instantiation and was wondering
if any of this behaviour is covered under the emerging C++ draft standard.
I have seen template classes that define methods that will only *work*
if the instantiation type provides certain methods/functionality.
ie.
template<class T>
class Foo {
public:
Foo (const T &t) : myT(T) {}
// etc...
int compare (const T &otherT)
{
return (myT < otherT ? -1 : myT > otherT ? 1 : 0);
}
// etc...
};
In this example the "compare" method relies on the object of type T
having comparison operators.
Is it legal to allow Foo to be instantiated with an object that does
not support comparison as long as the compare method is never called
for that particular instantiation?
Compilers with "demand-only" instantiation seem to allow this (as well
as not catching many syntax errors in template code but that is another
problem).
So, what is the verdict on this type of template usage?
Note: please provide supporting arguments relating to the emerging draft
standard instead of providing "I think..."-type reponses. (since I already
have my own theories on whether this *should* be legal)
Also, does anyone know if any template libraries like STL rely on this type
of template instantiation behaviour?
Thanks in advance!
--
Brent McPherson | Alias | Wavefront Inc.
Senior Software Engineer | 110 Richmond St. E.
E-Mail: bmcphers@aw.sgi.com | Toronto, CANADA M5C 1P1
Phone: (416) 362-8558 ext.212 | http://www.aw.sgi.com
--
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: tony@online.tmx.com.au (Tony Cook)
Date: 1995/08/22 Raw View
Steve Clamage (clamage@Eng) wrote:
: In article 95Aug21100336@physics10.Berkeley.EDU, bmcphers@alias.com (Brent McPherson) writes:
: >
: >I have seen template classes that define methods that will only *work*
: >if the instantiation type provides certain methods/functionality.
: >
: >ie.
: >
: > template<class T>
: > class Foo {
: > public:
: > Foo (const T &t) : myT(T) {}
: > // etc...
: > int compare (const T &otherT)
: > {
: > return (myT < otherT ? -1 : myT > otherT ? 1 : 0);
: > }
: > // etc...
: > };
: >
: >In this example the "compare" method relies on the object of type T
: >having comparison operators.
: >
: >Is it legal to allow Foo to be instantiated with an object that does
: >not support comparison as long as the compare method is never called
: >for that particular instantiation?
: The draft standard, 14.3.2 Point of Instantiation [temp.point], says
: the implementation shall not instantiate a class or function that does not
: require instantiation. A non-virtual function that is never called and
: never has its address taken does not require instantiation.
: In your example, if you create a variable of type Foo<X>, where X is
: some type, and never use the non-virtual compare function, that
: function, Foo<X>::compare, should not be instantiated.
: Details of template definition and instantiation have been modified or
: clarified recently, and it will take a while for compilers to catch up
: to what is in the draft standard.
: In the mean time, you could write a specialization of Foo<X>::compare
: that throws an exception or invokes "assert(0)" to allow your code
: to compile and link. That is, for example, if you use Foo<complex>,
: you could provide the specialization
: int Foo<complex>::compare(const complex&) { assert(0); return 0; }
: which will prevent the compiler from generating a version from the template,
: and will thus allow your program to compile and link.
Can we instead _declare_ the specialization and not define it:
extern int Foo<complex>::compare(const complex &);
So that we see an error at link time rather than run-time?
This may also need specialisations for any other function that call
compare - but these may be desirable anyway.
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: bill@amber.ssd.csd.harris.com (Bill Leonard)
Date: 19 Sep 1994 15:11:17 GMT Raw View
In article <Cw8F2J.3G0@borland.com>, pete@genghis.interbase.borland.com (Pete Becker) writes:
> In article <35c8b4$9pb@hawk.csd.harris.com>,
> Bill Leonard <Bill.Leonard@mail.csd.harris.com> wrote:
> >
> >I know at least some C++ compilers provide such a mechanism, at least as an
> >option. If I owned one of those compilers (which I don't), I would opt for
> >that mechanism.
> >
>
> No, you wouldn't. Not after struggling with the dependencies in your
> first complex project. This works fine for simple cases, but once you start
> using templates that use other templates the details become overwhelming.
"First complex project"? Ha ha ha ha ha ha! :-) :-)
Seriously, I may not be a genius, but I am pretty smart. I think I could
figure it out. :-)
Since I don't have a compiler that supports templates (yet), I use macros
as the poor man's template mechanism. In effect, I am already using the
scheme I outlined above, with no problems.
Similarly, I had brief access to a template-supporting compiler that
implemented the link-time instantiation (as an option). Even in a simple
little test, I had trouble getting things instantiated like I wanted.
I have no doubt that such a user-controlled mechanism can become complex.
But my experience indicates that the link-time instantiation is even worse.
This is especially true if you need to compile with special compiler
options, or you want to use shared libraries. The biggest difference I see
is that *I* have control over the complexity in the user-instantiation
scheme, but I don't in the link-time scheme.
--
Bill Leonard
Harris Computer Systems Division
2101 W. Cypress Creek Road
Fort Lauderdale, FL 33309
Bill.Leonard@mail.csd.harris.com
These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Harris Corporation.
------------------------------------------------------------------------------
More people run Windows on their home computers than on any other home
appliance.
------------------------------------------------------------------------------
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Fri, 16 Sep 1994 22:04:20 GMT Raw View
In article <35a629$4lg@ixnews1.ix.netcom.com> PGoodwin@ix.netcom.com (Phil Goodwin) writes:
>[... comments about link-time template instantiation omitted...]
>
>Considering the amount of effort that has been made to keep C++
>compatible with C's linker technology I find it hard to believe that
>a feature that would require the linker to be responsible for telling
>the compiler when to generate code would even be considered.
For whatever it's worth, I always felt that link-time instantiation was
hopelessly ugly and burdensome (on the implementation) also.
>So my question is: why wasn't this simpler route taken?
I don't think simplicity was in the goal set.
>And, just exactly what are the rules that govern the the generation of
>template code?
TBD
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Fri, 16 Sep 1994 22:18:25 GMT Raw View
In article <35aqi3$gov@engnews2.Eng.Sun.COM> clamage@Eng.Sun.COM writes:
>In article 4lg@ixnews1.ix.netcom.com, PGoodwin@ix.netcom.com (Phil Goodwin) writes:
>>I have been reading "The Design and Evolution of C++" wherein
>>Dr. Stroustrup explains that the declaration of a template
>>instantiation is implicit in it's first use and that the actual
>>definition of a particular instantiation, by the compiler, is postponed
>>until "the latest possible moment". He goes on to suggest that "the
>>latest possible moment" could possibly be some time during the linking
>>process. I don't understand why all of these convolutions are needed.
>>In the ARM (section 14.5 rationale) there is a description of a
>>relatively simple mechanism that puts the burden of both declaration
>>and point of instantiation on the programmer. This scheme seems to be
>>highly attractive to me.
>
>Suppose we follow your suggestion. To use a template, you must include
>not only the template declarations, but the implementation code in
>each compilation unit which refers to it. If you have a template
> template <class T> int compare(const T&, const T&);
>then in each compilation unit where you compare two X objects, the compiler
>must instantiate a version of 'compare' for X. If you compare X's in each
>of 100 modules, you get 100 copies of that compare function, and all the
>template code compiled 100 times...
This problem is not unique to templates, nor is it even unique to C++.
Try putting the definition of a static-linkage C function in a C header
file and then include _that_ in 100 different places and see what you
get.
So since this is a common problem, C++ gives us an elegant and well-
conceived common solution, right?
--
-- Ron Guilmette, Sunnyvale, CA ---------- RG Consulting -------------------
---- domain addr: rfg@netcom.com ----------- Purveyors of Compiler Test ----
---- uucp addr: ...!uunet!netcom!rfg ------- Suites and Bullet-Proof Shoes -
Author: bill@amber.ssd.csd.harris.com (Bill Leonard)
Date: 16 Sep 1994 13:59:00 GMT Raw View
In article <35aqi3$gov@engnews2.Eng.Sun.COM>, clamage@Eng.Sun.COM (Steve Clamage) writes:
> Suppose we follow your suggestion. To use a template, you must include
> not only the template declarations, but the implementation code in
> each compilation unit which refers to it. If you have a template
> template <class T> int compare(const T&, const T&);
> then in each compilation unit where you compare two X objects, the compiler
> must instantiate a version of 'compare' for X. If you compare X's in each
> of 100 modules, you get 100 copies of that compare function, and all the
> template code compiled 100 times. The linker then has to sort through the
> 100 copies of 'compare' and realize that although we don't normally allow
> multiple definitions of a function, it's ok for this one because it is a
> template function. The linker keeps one function and discards the rest.
>
> One alternative is for the compiler to assume that the needed instantiations
> are available, and at link time a "repository" is automatically searched
> for the needed functions.
>
> Another alternative is to keep more data in the repository. When a template
> instantiation is needed, the compiler checks the repository to see if it
> is already there.
Another alternative is to provide a language declaration that directs the
compiler to instantiate a particular template *now*, right here. So only
files that have instantiation directives need access to the template code,
and it is up to the programmer to make sure only one instantiation of each
template type is made.
I know at least some C++ compilers provide such a mechanism, at least as an
option. If I owned one of those compilers (which I don't), I would opt for
that mechanism.
One of the problems with the various "automatic" instantiation mechanisms
is integrating it with existing build procedures and tools, such as Unix
'make'. When the compiler gets invoked to instantiate a template, what
options are provided to the compiler? Since the compiler invocations are
not under direct control of the user, it's hard to predict the answer to
that question. And if you happen to want, or need, different options
supplied for different instantiations, you're probably just out of luck.
--
Bill Leonard
Harris Computer Systems Division
2101 W. Cypress Creek Road
Fort Lauderdale, FL 33309
Bill.Leonard@mail.csd.harris.com
These opinions and statements are my own and do not necessarily reflect the
opinions or positions of Harris Corporation.
------------------------------------------------------------------------------
More people run Windows on their home computers than on any other home
appliance.
------------------------------------------------------------------------------
Author: pete@genghis.interbase.borland.com (Pete Becker)
Date: Fri, 16 Sep 1994 16:56:43 GMT Raw View
In article <35c8b4$9pb@hawk.csd.harris.com>,
Bill Leonard <Bill.Leonard@mail.csd.harris.com> wrote:
>
>Another alternative is to provide a language declaration that directs the
>compiler to instantiate a particular template *now*, right here. So only
>files that have instantiation directives need access to the template code,
>and it is up to the programmer to make sure only one instantiation of each
>template type is made.
>
>I know at least some C++ compilers provide such a mechanism, at least as an
>option. If I owned one of those compilers (which I don't), I would opt for
>that mechanism.
>
No, you wouldn't. Not after struggling with the dependencies in your
first complex project. This works fine for simple cases, but once you start
using templates that use other templates the details become overwhelming.
-- Pete
Author: PGoodwin@ix.netcom.com (Phil Goodwin)
Date: 15 Sep 1994 19:07:53 GMT Raw View
I have been reading "The Design and Evolution of C++" wherein
Dr. Stroustrup explains that the declaration of a template
instantiation is implicit in it's first use and that the actual
definition of a particular instantiation, by the compiler, is postponed
until "the latest possible moment". He goes on to suggest that "the
latest possible moment" could possibly be some time during the linking
process. I don't understand why all of these convolutions are needed.
In the ARM (section 14.5 rationale) there is a description of a
relatively simple mechanism that puts the burden of both declaration
and point of instantiation on the programmer. This scheme seems to be
highly attractive to me. Not only would it be orthoganal to the rest of
the language, it would make the resulting code more maintainable and
would simplify implementation.
Virtually all other language constructs that generate code require an
explicit definition (or point of instantiation in the case of the
preprocessor macros that templates are supposed to replace), and, in
most cases, a declaration is also required before the generated code
can be used by other parts of a project. This requirement makes it
possible to organize projects into well-defined modules and to
maintain an inventory of the resources that each module needs and
where those resources are located. In the case of templates this
requirement would also allow maintenance engineers to estimate the
amount of code that a particular template is responsible for
generating. In addition to benifiting the programmer these kind of
restrictions simplify implementation issues by removing the burden of
deciding what code to generate when from the complier-linker.
Considering the amount of effort that has been made to keep C++
compatible with C's linker technology I find it hard to believe that
a feature that would require the linker to be responsible for telling
the compiler when to generate code would even be considered.
So my question is: why wasn't this simpler route taken? And, just
exactly what are the rules that govern the the generation of template
code?
Thanks,
Phil Goodwin PGoodwin@Netcom.com
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 16 Sep 1994 00:57:39 GMT Raw View
In article 4lg@ixnews1.ix.netcom.com, PGoodwin@ix.netcom.com (Phil Goodwin) writes:
>I have been reading "The Design and Evolution of C++" wherein
>Dr. Stroustrup explains that the declaration of a template
>instantiation is implicit in it's first use and that the actual
>definition of a particular instantiation, by the compiler, is postponed
>until "the latest possible moment". He goes on to suggest that "the
>latest possible moment" could possibly be some time during the linking
>process. I don't understand why all of these convolutions are needed.
>In the ARM (section 14.5 rationale) there is a description of a
>relatively simple mechanism that puts the burden of both declaration
>and point of instantiation on the programmer. This scheme seems to be
>highly attractive to me.
Suppose we follow your suggestion. To use a template, you must include
not only the template declarations, but the implementation code in
each compilation unit which refers to it. If you have a template
template <class T> int compare(const T&, const T&);
then in each compilation unit where you compare two X objects, the compiler
must instantiate a version of 'compare' for X. If you compare X's in each
of 100 modules, you get 100 copies of that compare function, and all the
template code compiled 100 times. The linker then has to sort through the
100 copies of 'compare' and realize that although we don't normally allow
multiple definitions of a function, it's ok for this one because it is a
template function. The linker keeps one function and discards the rest.
This is in fact a feasible implementation, and I believe the Borland compiler
does this, or something very similar. The disadvantages are having to compile
all the code for all your templates in every compilation unit and generate
perhaps thousands of functions which will be thrown away. Not bad if you
get paid by the hour, not so nice when you don't. It makes for the simplest
C++ implementation, and Borland was thus able to market a C++ compiler
with templates very early.
One alternative is for the compiler to assume that the needed instantiations
are available, and at link time a "repository" is automatically searched
for the needed functions. If any are missing, the compiler is invoked in
a special mode to generate the missing functions -- the system assumes that
the name of the source files follow a specified convention. You then
attempt to link again, and of course instantiating new functions might
require still more. Eventually this terminates, although the first time
you build a program it can take a l-o-o-o-o-o-o-n-g time. Later builds,
if the templates are not changed, don't require so many cycles, and are
reasonably fast. If you change a template, back to square 1, or perhaps
square 2. Notice this doesn't compile any more functions than are needed,
and user code does not need to include all the template instantiation code;
module compiles are faster.
Another alternative is to keep more data in the repository. When a template
instantiation is needed, the compiler checks the repository to see if it
is already there. If not, it generates it as part of the current compilation.
When you get to link time, all the needed functions have already been
generated, and there is exactly one copy of each. This requires quite a
lot of mechanism on the part of the C++ implementation, but it makes life
very simple for users. You include only headers in your files, and nothing
more than is needed gets compiled.
---
Steve Clamage, stephen.clamage@eng.sun.com
Author: esap@kaarne.cs.tut.fi (Pulkkinen Esa)
Date: 16 Sep 1994 08:35:46 GMT Raw View
Phil Goodwin (PGoodwin@ix.netcom.com) wrote:
: Dr. Stroustrup explains that the declaration of a template
: instantiation is implicit in it's first use and that the actual
: definition of a particular instantiation, by the compiler, is postponed
: until "the latest possible moment". He goes on to suggest that "the
: latest possible moment" could possibly be some time during the linking
: process. I don't understand why all of these convolutions are needed.
I think the basic reason is to remove all template code from the header
files. If the compiler was required to have access to all code contained
in the template, most of template code would have to be placed in
header files.
: Virtually all other language constructs that generate code require an
: explicit definition (or point of instantiation in the case of the
: preprocessor macros that templates are supposed to replace), and, in
: most cases, a declaration is also required before the generated code
: can be used by other parts of a project. This requirement makes it
True, but in non-templayr function declarations you currently need to have only
a declaration of a prototype telling which parameters the function takes,
not the whole definition of the function. And templates aren't supposed
to be "smart macros", but an alternative means for declaring and
defining a set of functions. Therefore, IMHO,
to preserve the consistency between function declarations and
definitions, it should be possible to declare
template classes and functions in header files, and move the definitions
from the header files, so that it's linker's responsibility (as in normal
functions) to produce correct code to call the functions, even if that would
imply calling the compiler or complicating the linker's implementation
in a significant way. The other alternative would imply that with every
change in the template function code would force recompiling the whole
program (i.e. everything that #includes the header files)
even if they didn't use the changed function or class.
: Considering the amount of effort that has been made to keep C++
: compatible with C's linker technology I find it hard to believe that
: a feature that would require the linker to be responsible for telling
: the compiler when to generate code would even be considered.
Well... We have to get over the old technology sometimes, and the
currently chosen alternative makes the transition from old linkers
as smooth as it's possible by allowing most of the functionality of the
linkers to be preserved.
--
Esa Pulkkinen | Disclaimer:
E-Mail: esap@cs.tut.fi | These opinions are mine, so
WWW : http://www.cs.tut.fi/~esap/ | don't blame others on them.