![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 12 May 2008 12:57:37
Message: <48287701@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> OK, that would be my second statement, then. The template is actually
> getting recompiled down to object code each time you instantiate it,
> even if it's an "export" template.
But it's compiled only once even if the same template function is used
with a given type at several places in the program. (Without the export
template mechanism the function would be compiled every time it's used.)
And, as I said, I can imagine that compilers could implement optimizations
where they cache compiled export templates. IOW, if you compile your project
for the first time, the template code gets compiled, but if you recompile
the project a second time, the already-compiled template code is used.
(But I doubt any C++ compiler so far uses this kind of optimization.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> wrote:
>> OK, that would be my second statement, then. The template is actually
>> getting recompiled down to object code each time you instantiate it,
>> even if it's an "export" template.
>
> But it's compiled only once even if the same template function is used
> with a given type at several places in the program. (Without the export
> template mechanism the function would be compiled every time it's used.)
Even if the places it's used are in different compilation units? As in,
if I invoke the compiler 12 times with 12 instantiations of the same
template in 12 different .cpp files, isn't that code going to have to
get translated into object code 12 different times?
To phrase it differently, say it took one minute to compile the program
with the template inline. Could I compile 12 compilation units that
instantiate the template in 2 minutes? Or is it going to take on the
order of 12 minutes?
> And, as I said, I can imagine that compilers could implement optimizations
> where they cache compiled export templates. IOW, if you compile your project
> for the first time, the template code gets compiled, but if you recompile
> the project a second time, the already-compiled template code is used.
> (But I doubt any C++ compiler so far uses this kind of optimization.)
From the link Fredrik posted, it looks like you can't really do this,
because the environment that invokes the instantiation may be different.
(E.g., there may be different overloaded functions in scope that would
change the meaning of the template.)
--
Darren New / San Diego, CA, USA (PST)
"That's pretty. Where's that?"
"It's the Age of Channelwood."
"We should go there on vacation some time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 13 May 2008 05:56:34
Message: <482965d2@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> > But it's compiled only once even if the same template function is used
> > with a given type at several places in the program. (Without the export
> > template mechanism the function would be compiled every time it's used.)
> Even if the places it's used are in different compilation units?
Yes. The compiler couldn't compile the template function even if it wanted
because it only has its declaration, not the implementation (which is in
its own compilation unit).
> As in,
> if I invoke the compiler 12 times with 12 instantiations of the same
> template in 12 different .cpp files, isn't that code going to have to
> get translated into object code 12 different times?
We are talking about export templates here, not regular ones.
> To phrase it differently, say it took one minute to compile the program
> with the template inline. Could I compile 12 compilation units that
> instantiate the template in 2 minutes? Or is it going to take on the
> order of 12 minutes?
If the function is an export template, it will only be compiled once,
not 12 times. (Well, naturally assuming all those 12 times use the same
type with that template.)
> > And, as I said, I can imagine that compilers could implement optimizations
> > where they cache compiled export templates. IOW, if you compile your project
> > for the first time, the template code gets compiled, but if you recompile
> > the project a second time, the already-compiled template code is used.
> > (But I doubt any C++ compiler so far uses this kind of optimization.)
> From the link Fredrik posted, it looks like you can't really do this,
> because the environment that invokes the instantiation may be different.
> (E.g., there may be different overloaded functions in scope that would
> change the meaning of the template.)
The environment doesn't change with export templates because they are
in their own compilation units. The only environment is that compilation
unit in question. They are basically no different from regular functions.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Tue, 13 May 2008 11:56:34 +0200, Warp <war### [at] tag povray org> wrote:
> The environment doesn't change with export templates because they are
> in their own compilation units. The only environment is that compilation
> unit in question. They are basically no different from regular functions.
The instantiation context changes, and thus the exported template must be
recompiled. When compiling a template, name lookup of dependent names is
performed both in the definition context and in the instantiation context.
--
FE
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> wrote:
>>> But it's compiled only once even if the same template function is used
>>> with a given type at several places in the program. (Without the export
>>> template mechanism the function would be compiled every time it's used.)
>
>> Even if the places it's used are in different compilation units?
>
> Yes. The compiler couldn't compile the template function even if it wanted
> because it only has its declaration, not the implementation (which is in
> its own compilation unit).
Um, OK. That's not what the folks who implemented it in their compiler
seemed to be saying.
>> As in,
>> if I invoke the compiler 12 times with 12 instantiations of the same
>> template in 12 different .cpp files, isn't that code going to have to
>> get translated into object code 12 different times?
>
> We are talking about export templates here, not regular ones.
Right. That's why I'm asking. :-)
> If the function is an export template, it will only be compiled once,
> not 12 times. (Well, naturally assuming all those 12 times use the same
> type with that template.)
Um, ok.
> The environment doesn't change with export templates because they are
> in their own compilation units. The only environment is that compilation
> unit in question. They are basically no different from regular functions.
But if in A.cpp I have xyz:MyTemplate<T> and in the body of MyTemplate
it invokes T.x(i), isn't the code generated going to depend on the
declarations of T.x that are available at the point I instantiate the
template? If x is an overloaded function, doesn't it have to know all
the overloaded functions in scope to pick the one most likely to be the
one I meant by passing whatever type "i" is?
That seemed to be what the paper about the compiler was talking about.
--
Darren New / San Diego, CA, USA (PST)
"That's pretty. Where's that?"
"It's the Age of Channelwood."
"We should go there on vacation some time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 13 May 2008 15:58:54
Message: <4829f2fe@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> But if in A.cpp I have xyz:MyTemplate<T> and in the body of MyTemplate
> it invokes T.x(i), isn't the code generated going to depend on the
> declarations of T.x that are available at the point I instantiate the
> template? If x is an overloaded function, doesn't it have to know all
> the overloaded functions in scope to pick the one most likely to be the
> one I meant by passing whatever type "i" is?
I can't think of any way how a certain type T can change in different
compilation units without causing a linker error.
If you have a class T, it will have a certain declared interface. That
interface doesn't change depending on the context. If you give the template
some other class, for example one derived from T, that's a *different* type,
and thus requires its own instantiation of the template function.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Tue, 13 May 2008 21:58:54 +0200, Warp <war### [at] tag povray org> wrote:
> I can't think of any way how a certain type T can change in different
> compilation units without causing a linker error.
>
> If you have a class T, it will have a certain declared interface. That
> interface doesn't change depending on the context. If you give the
> template
> some other class, for example one derived from T, that's a *different*
> type,
> and thus requires its own instantiation of the template function.
If you change the set of functions that take objects of type T as a
parameter, the instantiation context changes for a template with T as a
type parameter, even though the signature of the template remains the same.
--
FE
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 14 May 2008 06:45:17
Message: <482ac2bc@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> If you change the set of functions that take objects of type T as a
> parameter, the instantiation context changes for a template with T as a
> type parameter, even though the signature of the template remains the same.
Can you give me a concrete example?
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Can you give me a concrete example?
I probably have all the syntax mixed up, and maybe you need to do
something more complicated with friend functions and everything else,
but this is my understanding of what they were talking about in the
paper? Basically, the environment in which X<T> is expanded is
different, so the xyz.xx(4) would promote 4 to a long in main1 and not
main2.
*** A.h
void X<T>(void);
class A {
void xx(long i) {
cout << "Alpha!\n";
}
}
*** X.cpp
void X<T>(void) {
T xyz;
xyz.xx(4);
}
*** Main1.cpp
#include <A.h>
void main1(void) {
X<A>();
}
*** Main2.cpp
#include <A.h>
void A::xx(int i) {
cout << "Beta!\n";
}
void main2(void) {
X<A>();
}
--
Darren New / San Diego, CA, USA (PST)
"That's pretty. Where's that?"
"It's the Age of Channelwood."
"We should go there on vacation some time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Wed, 14 May 2008 18:23:54 +0200, Darren New <dne### [at] san rr com> wrote:
>
> *** Main2.cpp
>
> #include <A.h>
>
> void A::xx(int i) {
> cout << "Beta!\n";
> }
This will fail to compile, because you cannot redefine A::xx.
What I had in mind is something like this (untested, for obvious reasons):
// g.hpp
template <typename T> void g(T t) { /* Do whatever */ }
// end g.hpp
// main.cpp
export template <typename T> void f();
int main(){ f<int>(); }
// end main.cpp
// export.cpp
#include "g.hpp"
template <typename T> void f(){ g( T() ); }
// end export.cpp
Now make a small change to main.cpp:
// main.cpp
export template <typename T> void f();
#include "g.hpp"
template <> void g(int i) { /* Do something completely different */ }
int main(){ f<int>(); }
// end main.cpp
The instantiation context for the exported template changes, because there
is now an additional function participating in name lookup. In this case
the behaviour also changes because the new function is a better match.
Note that the signature of the exported template remains the same.
Note: I think the same should apply even if 'g' was not a template, but
GCC disagrees (tested without 'export' of course). VC does what I expect
though. I wish I knew which is right.
--
FE
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |