![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/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 Sun, 11 May 2008 20:35:50 +0200, Darren New <dne### [at] san rr com> wrote:
> The whole "export template" bit I don't understand. I have to believe
> that either there are restrictions on what a template can do and still
> be able to be an export template, or there are bits in the object file
> which are essentially getting recompiled at compile-time.
Read this paper to learn a little about what 'export' means, and why many
consider it to a bad idea:
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf
--
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: 11 May 2008 20:18:31
Message: <48278cd7@news.povray.org>
|
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> The whole "export template" bit I don't understand. I have to believe
> that either there are restrictions on what a template can do and still
> be able to be an export template, or there are bits in the object file
> which are essentially getting recompiled at compile-time.
AFAIK there are no restrictions on what an export template function
can contain.
The basic implementation of export templates, from the point of view
of the compiler, is that the template *source* code gets written to the
object file (either as raw source code or some kind of pre-parsed code
or whatever; I don't know how eg. gcc does it in practice). When the
linker sees that it needs a specific instance for a certain template
function, it calls the compiler and tells it "I need an instance of
this template function with these types", the compiler compiles the
function for those types, and then the linker uses the generated code.
As you might imagine this is far from trivial to implement, which is
the reason why so few compilers support this.
In theory you could distribute template code as "precompiled" object
files, without the original source. However, I assume that with most
implementations of export templates, creating a decompiler for those
object files is probably fairly trivial (because, after all, the object
file has to have the original source code in one form or another inside
it for the whole export template mechanism to be possible).
Btw, there's an additional advantage in export templates besides the
smaller simpler header files and object files, and it's one which cannot
be used with compilers which do not support export templates and it can
have very practical uses: Export template code can use functions and
types which are local to that compilation unit. This can be used to
increase modularity (by hiding implementation details).
--
- 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:
>> The whole "export template" bit I don't understand. I have to believe
>> that either there are restrictions on what a template can do and still
>> be able to be an export template, or there are bits in the object file
>> which are essentially getting recompiled at compile-time.
> object files is probably fairly trivial (because, after all, the object
> file has to have the original source code in one form or another inside
> it for the whole export template mechanism to be possible).
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.
In a language like Ada (which has generics but not templates), you
compile the generic down to object code, and when you instantiate it,
you don't need the source for the implementations. I believe it can work
by basically, at instantiation time, building a descriptor not too
different from a vtable. If the only difference is which overloaded
functions get used, the object code will expect a table of pointers to
be created for it to invoke those functions. If it expects a different
size, then the object code is (possibly) duplicated and the size filled
in (just as you would fix up external references at link time), or the
code is slightly less efficient and takes as one parameter the size it
needs to work with.
In Java, of course, it compiles down to the same code as you would have
without generics, and you compile it once and ship the bytecodes. The
compiler basically just does error checking if the declaration is in
scope and casts the result of operations at runtime if so needed.
--
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: 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) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |