Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Implementability of export

92 views
Skip to first unread message

Kiril Avdeiv

unread,
Jan 3, 2002, 10:34:20 AM1/3/02
to
I have the following question -- Is it really possible to implement
the keyword export with all its semantics as specified in the
standard?

It's been nearly 5 years since the feature appeared in the draft C++
standard. The only team, as far as I know, that made an attempt to
implement it was Comeau with their 'Countdown to "export" expected
December 1, 2001'. Apparently the attempt didn't work out, as the
countdown is still ticking.

Seeing the high quality of their compiler I presume they have come up
against something not foreseen when the keyword was conceived.

Can any one prove my ideas to be right?

Thank you

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]

P.J. Plauger

unread,
Jan 3, 2002, 12:35:18 PM1/3/02
to
"Kiril Avdeiv" <kav...@mail.ru> wrote in message news:873f7ae8.02010...@posting.google.com...

> I have the following question -- Is it really possible to implement
> the keyword export with all its semantics as specified in the
> standard?

The answer seems to be, ``barely.''

> It's been nearly 5 years since the feature appeared in the draft C++
> standard. The only team, as far as I know, that made an attempt to
> implement it was Comeau with their 'Countdown to "export" expected
> December 1, 2001'. Apparently the attempt didn't work out, as the
> countdown is still ticking.

The team behind Comeau is Edison Design Group, which supplies their
top-of-the-line C/C++ front end to many compiler vendors, including
Comeau Computing. I know they've been wrestling with export for some
time, that they have it pretty much working, but that they didn't meet
their hoped-for deadline that would have permitted Comeau to ship by
last month. I don't speak officially for EDG, however, so I won't
venture any predictions. (From years of personal experience, I CAN
predict that the final result will be of excellent quality.)

> Seeing the high quality of their compiler I presume they have come up
> against something not foreseen when the keyword was conceived.

I think that EDG foresaw the difficulty. In fact, one of the EDG team
made a yeoman effort to get separate compilation of templates removed
from the C++ Standard. This is one of the problems with inventing in
the guise of writing standards, and doing so literally up to the final
moments before approval. It stretches out the time between approval of
the standard and the appearance of fully conforming implementations.

Still, the end of the beginning appears to be nigh.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

Gabriel Dos Reis

unread,
Jan 4, 2002, 10:47:45 AM1/4/02
to
"P.J. Plauger" <p...@dinkumware.com> writes:

[...]

| > Seeing the high quality of their compiler I presume they have come up
| > against something not foreseen when the keyword was conceived.
|
| I think that EDG foresaw the difficulty. In fact, one of the EDG team
| made a yeoman effort to get separate compilation of templates removed
| from the C++ Standard. This is one of the problems with inventing in
| the guise of writing standards, and doing so literally up to the final
| moments before approval.

The concept of separate compilation of templates wasn't the committee's
invention. CFront already made a proof of the concept.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan,fr

P.J. Plauger

unread,
Jan 4, 2002, 12:51:22 PM1/4/02
to
"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message news:flr8p6l...@riz.cmla.ens-cachan.fr...

> The concept of separate compilation of templates wasn't the committee's
> invention. CFront already made a proof of the concept.

Yeah, fine. But the committee didn't standardize on ANY of the prior art.
Rather, it invented a whole new notation. Please note that NONE of the
compilers that support separate compilation of templates has been quickly
retooled for the standardized notation. I can only guess that the
differences run deeper than how you spell a keyword. From what I've seen
and heard to date, Edison Design Group is well ahead of the pack. And
they've been implementing export templates de novo.

If you don't codify existing practice in a standard, you pay the price
in several dimensions. Delayed implementation is just one of them.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---

Greg Comeau

unread,
Jan 4, 2002, 4:48:31 PM1/4/02
to
In article <873f7ae8.02010...@posting.google.com>,

Kiril Avdeiv <kav...@mail.ru> wrote:
>I have the following question -- Is it really possible to implement
>the keyword export with all its semantics as specified in the
>standard?

To the best of my understanding: yes.

>It's been nearly 5 years since the feature appeared in the draft C++
>standard.

It's been many years since many features appeared.
I know this is frustrating, but somehow it becomes the
nature of the beast (it's not just the features that
need to be considered).

>The only team, as far as I know, that made an attempt to
>implement it was Comeau with their 'Countdown to "export" expected
>December 1, 2001'. Apparently the attempt didn't work out, as the
>countdown is still ticking.

Well, that doesn't mean the attempt didn't work.
It is after all, only 3 days since that estimation,
so no need to tout any demise! :) In actuality, EDG,
who we license from, is doing the intial work. And it is
coming along fine. Being off a month or so, instead of
releasing constantly broken or 1/2 implemented stuff,
is how we (and they) do stuff. And as you will see,
it will be well worth it.

>Seeing the high quality of their compiler I presume they have come up
>against something not foreseen when the keyword was conceived.

As in even trivial tasks, there are setbacks. But nothing really
unantipated per se, since after all, the commitee was aware,
in fact quite well aware, of various things which would need to be
considered in an implementation of export.

>Can any one prove my ideas to be right?

Don't throw out your New Year's horns and confetti just yet.

As soon as I can, I'll get a beta version up on the online compiler.
--
Greg Comeau What's next: additional Windows backends and 'export'!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

Kiril Avdeiv

unread,
Jan 4, 2002, 4:49:04 PM1/4/02
to
"P.J. Plauger" <p...@dinkumware.com> wrote in message news:<3c3495e5$0$4510$724e...@reader2.ash.ops.us.uu.net>...

Peter, a big thankyou for the explanation! Turns out I was somewhat
right in my hunch about the keyword.

Seeing that you are rather close to the latest developments in regard
to the implementation of the keyword and its semantics, I want to ask
whether you, as a library writer, consider export to be a useful
feature. In other words and in terms of the terminology of the C++
standard -- will Dinkumware C++ library ever comprise translated
translation units as opposed to the current state of affairs when the
library is made up of instantiation units only?

Thank you
Kiril

Gabriel Dos Reis

unread,
Jan 4, 2002, 4:50:16 PM1/4/02
to
j...@edg.com (John H. Spicer) writes:

[...]

| The primary objective of separate compilation of templates is to permit
| the template writer to control the environment in which the template
| is compiled to make sure that names mean what the template writer
| intended. The cfront model does nothing to ensure this.

Presumably because the name lookup machinery wasn't that complicated as
we have now?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

P.J. Plauger

unread,
Jan 4, 2002, 5:22:09 PM1/4/02
to
"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message news:fl666hd...@riz.cmla.ens-cachan.fr...

> j...@edg.com (John H. Spicer) writes:
>
> [...]
>
> | The primary objective of separate compilation of templates is to permit
> | the template writer to control the environment in which the template
> | is compiled to make sure that names mean what the template writer
> | intended. The cfront model does nothing to ensure this.
>
> Presumably because the name lookup machinery wasn't that complicated as
> we have now?

Or wasn't as well understood. From what little I know of this esoteric
subject, there have ALWAYS been serious issues about what names percolate
in from the global scope when a template gets instantiated. So it matters
very much just where that instantiation can, might, and/or must take place.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---

P.J. Plauger

unread,
Jan 4, 2002, 5:26:19 PM1/4/02
to
"Kiril Avdeiv" <kav...@mail.ru> wrote in message news:873f7ae8.02010...@posting.google.com...

> Seeing that you are rather close to the latest developments in regard


> to the implementation of the keyword and its semantics, I want to ask
> whether you, as a library writer, consider export to be a useful
> feature. In other words and in terms of the terminology of the C++
> standard -- will Dinkumware C++ library ever comprise translated
> translation units as opposed to the current state of affairs when the
> library is made up of instantiation units only?

Only when our customers demand it. One use for separate compilation of
templates is to hide source code, as you can do when precompiling
modules for a binary library. Dinkumware has always relied on copyright
protection, rather than proprietary restrictions, to protect our code,
so we have no incentive to further burder our customers, or their
customers in turn, with additional impediments. Another use MAY be to
speed compilation, but I haven't heard any promises that separate
compilation will lead to faster builds. If there are other good reasons
for separate compilation, I haven't heard them yet.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---

Sergey P. Derevyago

unread,
Jan 5, 2002, 10:59:23 AM1/5/02
to
"P.J. Plauger" wrote:
> Only when our customers demand it. One use for separate compilation of
> templates is to hide source code, as you can do when precompiling
> modules for a binary library. Dinkumware has always relied on copyright
> protection, rather than proprietary restrictions, to protect our code,
> so we have no incentive to further burder our customers, or their
> customers in turn, with additional impediments. Another use MAY be to
> speed compilation, but I haven't heard any promises that separate
> compilation will lead to faster builds. If there are other good reasons
> for separate compilation, I haven't heard them yet.
Are you kidding? :) The point is "context dependence".

In particular, C.13.8 of TC++PL 3rd begins with: "It is important to define
template functions so that they have as few dependencies as possible on
nonlocal information. The reason is that a template will be used to generate
functions and classes based on unknown types and in unknown context."
And 14.6.2 [temp.dep] tells about too tricky issues to ignore the export
utility.
--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

Pete Becker

unread,
Jan 5, 2002, 11:54:54 AM1/5/02
to
"Sergey P. Derevyago" wrote:
>
> "P.J. Plauger" wrote:
> > Only when our customers demand it. One use for separate compilation of
> > templates is to hide source code, as you can do when precompiling
> > modules for a binary library. Dinkumware has always relied on copyright
> > protection, rather than proprietary restrictions, to protect our code,
> > so we have no incentive to further burder our customers, or their
> > customers in turn, with additional impediments. Another use MAY be to
> > speed compilation, but I haven't heard any promises that separate
> > compilation will lead to faster builds. If there are other good reasons
> > for separate compilation, I haven't heard them yet.
> Are you kidding? :) The point is "context dependence".
>
> In particular, C.13.8 of TC++PL 3rd begins with: "It is important to define
> template functions so that they have as few dependencies as possible on
> nonlocal information. The reason is that a template will be used to generate
> functions and classes based on unknown types and in unknown context."
> And 14.6.2 [temp.dep] tells about too tricky issues to ignore the export
> utility.

In other words, separate compilation of templates is necessary because
it makes it easier to write code that's incomprehensible. <g>

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

P.J. Plauger

unread,
Jan 5, 2002, 11:56:25 AM1/5/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:3C36E11F...@iobox.com...

> If there are other good reasons
> > for separate compilation, I haven't heard them yet.

> Are you kidding? :) The point is "context dependence".
>
> In particular, C.13.8 of TC++PL 3rd begins with: "It is important to define
> template functions so that they have as few dependencies as possible on
> nonlocal information. The reason is that a template will be used to generate
> functions and classes based on unknown types and in unknown context."
> And 14.6.2 [temp.dep] tells about too tricky issues to ignore the export
> utility.

I'm vaguely aware of these issues --certainly we have to worry about
hijacking and other lookup problems with our current (conventional)
implementation of template definitions all in the library header files.
If anyone can demonstrate a conforming program that can only be
translated properly with the use of exported templates, then I'll
listen harder. But my first reaction will be to submit a Defect Report.
And my second will be to wait for a significant customer to report it
as a problem that needs fixing for their marketplace.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---

Edward Diener

unread,
Jan 7, 2002, 4:36:15 PM1/7/02
to
P.J. Plauger wrote:

> "Kiril Avdeiv" <kav...@mail.ru> wrote in message news:873f7ae8.02010...@posting.google.com...
>
>
>>Seeing that you are rather close to the latest developments in regard
>>to the implementation of the keyword and its semantics, I want to ask
>>whether you, as a library writer, consider export to be a useful
>>feature. In other words and in terms of the terminology of the C++
>>standard -- will Dinkumware C++ library ever comprise translated
>>translation units as opposed to the current state of affairs when the
>>library is made up of instantiation units only?
>>
>
> Only when our customers demand it. One use for separate compilation of
> templates is to hide source code, as you can do when precompiling
> modules for a binary library. Dinkumware has always relied on copyright
> protection, rather than proprietary restrictions, to protect our code,
> so we have no incentive to further burder our customers, or their
> customers in turn, with additional impediments.


Not everyone wants to deal with copyright issues in regarding to code
distribution, or has the legal and financial means to do so. The small
developer may want to distribute the header files and final modules of
his implementation without having to distribute any source code and, if
part of the implementation is templated classes and templated function,
being able to use the export feature in order to distribute templated
code, without distributing templated implementations, would be a great
boon to him.

Gabriel Dos Reis

unread,
Jan 7, 2002, 4:36:50 PM1/7/02
to
j...@edg.com (John H. Spicer) writes:

| In article <fl666hd...@riz.cmla.ens-cachan.fr> Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> writes:
| >j...@edg.com (John H. Spicer) writes:
| >
| >[...]
| >
| >| The primary objective of separate compilation of templates is to permit
| >| the template writer to control the environment in which the template
| >| is compiled to make sure that names mean what the template writer
| >| intended. The cfront model does nothing to ensure this.
| >
| >Presumably because the name lookup machinery wasn't that complicated as
| >we have now?
| >
|

| No. The issue is the set of declarations that are present when the
| template definition is compiled.

But then, that is where the name lookup machinery plays an important
role and I think if the notion of dependent name lookup were dropped,
then the CFront model is pretty much what is specified.

Oscar Fuentes

unread,
Jan 7, 2002, 4:38:39 PM1/7/02
to
Pete Becker <peteb...@acm.org> writes:

> > Are you kidding? :) The point is "context dependence".
> >
> > In particular, C.13.8 of TC++PL 3rd begins with: "It is
> > important to define template functions so that they have as few
> > dependencies as possible on nonlocal information. The reason is
> > that a template will be used to generate functions and classes
> > based on unknown types and in unknown context." And 14.6.2
> > [temp.dep] tells about too tricky issues to ignore the export
> > utility.
>
> In other words, separate compilation of templates is necessary
> because it makes it easier to write code that's
> incomprehensible. <g>

I'm not sure I understand your comment, but cluttering header files
with function definitions does not helps to read code. #including a
special file with template definitions is not a good thing
either. Whenever I read a template class method or function I wonder
if the definition is on a special file whose existence I need to check
or somewhere else on the header file. "C with classes"
interface/implementation separation model is bad enough; C++'s
template implementation as available today stablishes new records on
code obfuscation.

IMHO, template definitions should be where all other non-inline
definitions are: on the .cpp file.

--
Oscar

Matthew Austern

unread,
Jan 7, 2002, 5:32:48 PM1/7/02
to
Edward Diener <eldi...@earthlink.net> writes:

> Not everyone wants to deal with copyright issues in regarding to code
> distribution, or has the legal and financial means to do so. The small
> developer may want to distribute the header files and final modules of
> his implementation without having to distribute any source code and,
> if part of the implementation is templated classes and templated
> function, being able to use the export feature in order to distribute
> templated code, without distributing templated implementations, would
> be a great boon to him.

It's a reasonable goal, but nothing in the C++ standard says that
'export' will help you achieve it. A compiler that supports export
may still require that you ship source, and such a compiler would be
conforming.

Gabriel Dos_Reis

unread,
Jan 8, 2002, 2:00:41 AM1/8/02
to
j...@edg.com (John H. Spicer) writes:

| In article <flell5b...@riz.cmla.ens-cachan.fr> Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> writes:
| >j...@edg.com (John H. Spicer) writes:
| >
| >| In article <fl666hd...@riz.cmla.ens-cachan.fr> Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> writes:
| >| >j...@edg.com (John H. Spicer) writes:
| >| >
| >| >[...]
| >| >
| >| >| The primary objective of separate compilation of templates is to permit
| >| >| the template writer to control the environment in which the template
| >| >| is compiled to make sure that names mean what the template writer
| >| >| intended. The cfront model does nothing to ensure this.
| >| >
| >| >Presumably because the name lookup machinery wasn't that complicated as
| >| >we have now?
| >| >
| >|
| >| No. The issue is the set of declarations that are present when the
| >| template definition is compiled.
| >
| >But then, that is where the name lookup machinery plays an important
| >role and I think if the notion of dependent name lookup were dropped,
| >then the CFront model is pretty much what is specified.
| >
|

| There is no way to discuss "export" in the absence of the dependent lookup
| rules that unless an alternate set of dependent lookup rules is proposed.

Well, at this point, maybe it is appropriate to recall the context of
my claims.

"P.J. Plauger" <p...@dinkumware.com> wrote:

[...]

| > Seeing the high quality of their compiler I presume they have come up
| > against something not foreseen when the keyword was conceived.
|
| I think that EDG foresaw the difficulty. In fact, one of the EDG team
| made a yeoman effort to get separate compilation of templates removed
| from the C++ Standard. This is one of the problems with inventing in
| the guise of writing standards, and doing so literally up to the final
| moments before approval.

Then I replied:

The *concept of separate compilation of templates* wasn't the committee's


invention. CFront already made a proof of the concept.

(Emphasis is added)

| With non-exported templates you can simply say "lets defer all lookup to
| the point of instantiation", but you can't do that with exported templates
| because names from the definition context are not necessarily present
| at the point of instantiation.

Yes, I do know that current rules require two-phase name lookup, but
then I don't think that two-phase name lookup is a sine qua non
condition for the "concept of separate compilation of templates".
Other rules are quite possible and one-phase lookup, that is,
deferring name lookup until instantiation time, is quite another model
ans is close to what CFront did. I don't think it is fair or accurate
to say that just because CFront didn't two-phase name-lookup means it
didn't a made a proof of the concept of separate compilation of
templates.

That the committee, later, changed the rules don't necessary means it
invented the "concept of separate compilation of templates".

| The whole point of export is to let the template writer control the names
| visible to the template. Cfront gives the template writer no such ability.
|
| The other important aspect of "export" is the source model. With export,
| templates are placed in separately compiled files. In the cfront model,
| they are not.

In a model where names in template declarations or definitions are
looked up at instantiation time, it is quite possible to place
templates in separately compiled files: The translation unit -- say
CT.tu -- resulting from a .C file where the templates are defined can
be encoded (in one or another form) and consitutes the separate
compiled file. At instantiation time, names are lookup up first in
CT.tu, then in the translation unit requesting the instantiation.

P.J. Plauger

unread,
Jan 8, 2002, 10:23:26 AM1/8/02
to

"Gabriel Dos_Reis" <gdos...@sophia.inria.fr> wrote in message news:xaj3d1h...@perceval.inria.fr...

> Yes, I do know that current rules require two-phase name lookup, but
> then I don't think that two-phase name lookup is a sine qua non
> condition for the "concept of separate compilation of templates".
> Other rules are quite possible and one-phase lookup, that is,
> deferring name lookup until instantiation time, is quite another model
> ans is close to what CFront did. I don't think it is fair or accurate
> to say that just because CFront didn't two-phase name-lookup means it
> didn't a made a proof of the concept of separate compilation of
> templates.

It isn't fair or accurate. And I don't think anyone said so. Proof of
concept is one thing, however, and what gets standardized can be quite
another thing.

> That the committee, later, changed the rules don't necessary means it
> invented the "concept of separate compilation of templates".

I don't recall anyone claiming that the committee invented separate
compilation either. I recall observing that several compilers, including
cfront, have had some form of separate compilation for years. Apparently,
NONE of these is close enough to the actual mechanism called for by the
standard to be of any advantage. John Spicer, who knows way more about
this topic than I ever want to, has elaborated on the different
mechanisms. He has made clearer, to me at least, why we have yet to see
a conforming implementation of export templates over four years after
the C++ Standard froze -- and why the EDG de novo implementation can be
quicker to market than ``existing practice.''

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---

James Kanze

unread,
Jan 8, 2002, 12:03:29 PM1/8/02
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
news:<fl666hd...@riz.cmla.ens-cachan.fr>...
> j...@edg.com (John H. Spicer) writes:

> [...]

> | The primary objective of separate compilation of templates is to
> | permit the template writer to control the environment in which the
> | template is compiled to make sure that names mean what the
> | template writer intended. The cfront model does nothing to ensure
> | this.

I didn't see John Spicer's posting, so I'll answer it here. As a
user, I never had any problems with the CFront model. I know what the
theoretical problems are, but they just don't occur in practice. (In
the same way, I can easily write a program which will silently change
semantics between older compilers and the new semantics. In practice,
however, I'd be very surprised if this "silent change" is a problem.)

The reason for separate compilation is managing dependancies. On a
large project, it is important that the authors of template client
code not have to wait for a complete implementation of the template
before they start to compile. The CFront model solved this trivially,
since instantiation didn't occur until link time. I think that most
current implementations, at least on Unix, manage to solve this as
well; if the template implementation isn't visible at compile time,
they will defer instantiation until link time. In practice, they have
to, because not doing so would break existing code.

> Presumably because the name lookup machinery wasn't that complicated
> as we have now?

I don't think that's the problem. The name lookup (complex or simple)
takes place in a specific context. The problem is to provide that
context. In C++, the *only* context we have is the result of
physically having copied a number of files into one (#include); at any
given point in a C++ program, you see literally everything that was
copied in before. The CFront heuristic works well in practice, up to
a point, but I just can't imagine the standard defining the context as
a function of the include files in which the various things happened
to be defined.

In an ideal world, there would be no real difference between templates
and non templates. I would put my class definitions in a .hh file. I
would put my function definitions in a .cc file. I would compile the
.cc file, and put it into a library. Client code would include the
.hh file, and link against the library. Intuitively, I think that
such an implementation should be possible, but I've not actually tried
to do it. And the people I know who do work on such things have
expressed significant doubts as to whether it can be done.

In an ideal world, I'm not really certain what the rules for name
binding should be. I don't like the current rules; I find them too
complex, and too confusing. I understand John Spicer's concern for
name hijacking, but I'm sceptical as to whether it is a real problem.
In the end, there is nothing to stop the template author from fully
qualifying everything if he is worried.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

Dave Harris

unread,
Jan 8, 2002, 7:33:29 PM1/8/02
to
ka...@gabi-soft.de (James Kanze) wrote (abridged):

> The reason for separate compilation is managing dependancies. On a
> large project, it is important that the authors of template client
> code not have to wait for a complete implementation of the template
> before they start to compile. The CFront model solved this trivially,
> since instantiation didn't occur until link time. I think that most
> current implementations, at least on Unix, manage to solve this as
> well; if the template implementation isn't visible at compile time,
> they will defer instantiation until link time. In practice, they have
> to, because not doing so would break existing code.

According to some readings of the standard, this behaviour is mandated as
part of support for explicit instantiation. Explicit instantiation often
provides a practical alternative to "export".

For example, code like:

template <typename T>
const T &max( const T &lhs, const T &rhs );

int a = max( 10, 20 );

should compile. It will even link and run if the template is defined and
explicitly instantiated with int, and that doesn't have to be done by the
compilation unit that uses the template.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

Gabriel Dos Reis

unread,
Jan 9, 2002, 10:40:50 AM1/9/02
to
"P.J. Plauger" <p...@dinkumware.com> writes:

| "Gabriel Dos_Reis" <gdos...@sophia.inria.fr> wrote in message news:xaj3d1h...@perceval.inria.fr...
|
| > Yes, I do know that current rules require two-phase name lookup, but
| > then I don't think that two-phase name lookup is a sine qua non
| > condition for the "concept of separate compilation of templates".
| > Other rules are quite possible and one-phase lookup, that is,
| > deferring name lookup until instantiation time, is quite another model
| > ans is close to what CFront did. I don't think it is fair or accurate
| > to say that just because CFront didn't two-phase name-lookup means it
| > didn't a made a proof of the concept of separate compilation of
| > templates.
|
| It isn't fair or accurate. And I don't think anyone said so.

Please, do (re)consider John Spicer's claims.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Pete Becker

unread,
Jan 10, 2002, 12:00:23 PM1/10/02
to
"John H. Spicer" wrote:
>
> It is not a proof of concept because it in no way did anything that
> resembles separate compilation. I posted a detailed description of
> exactly what cfront does that should permit readers to draw their own
> conclusions.
>

Just to bring this home: what cfront did was to compile each distinct
template instantiation directly from the template's source code.
Separate compilation means compiling the template once, to some
intermediate form, and generating instantiations from that intermediate
form.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

---

Daveed Vandevoorde

unread,
Jan 10, 2002, 1:50:38 PM1/10/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote:
> "P.J. Plauger" wrote:
> > [...] One use for separate compilation of
> > templates is to hide source code, [...] If there are other good reasons

> > for separate compilation, I haven't heard them yet.
> Are you kidding? :) The point is "context dependence".
>
> In particular, C.13.8 of TC++PL 3rd begins with: "It is important to define
> template functions so that they have as few dependencies as possible on
> nonlocal information. The reason is that a template will be used to generate
> functions and classes based on unknown types and in unknown context."
> And 14.6.2 [temp.dep] tells about too tricky issues to ignore the export
> utility.

However, I don't think "export" solves this issue. In fact, you might
argue it makes it worse: with "export" we now have the ability to
introduce dependencies that are not visible within a single translation
unit. With the inclusion model at least, all the interacting declarations
were present in one translation unit.

Here is a little example (an excerpt from "C++ Templates", which I'm
writing with Nico Josuttis):

// File a.c:
export template<typename T> void f(T);

struct A {};
struct B {};

struct X {
operator A() { return A(); }
operator B() { return B(); }
};

void g(A) {}

int main() {
f<X>(X());
}

// File b.c:
struct B {};

void g(B) {}

export template<typename T>
void f(T x) {
g(x);
}

The call "g(x)" ends up being ambiguous even though there is
no hint of that in translation unit b.c (where is appears).

This is a simple (and contrived) case involving just two translation
units. While developing support for "export", we have had to handle
weird interactions among dozens of translation units: "tricky issues"
takes on a whole new meaning :-/

Daveed

James Kanze

unread,
Jan 10, 2002, 1:52:57 PM1/10/02
to
bran...@cix.co.uk (Dave Harris) wrote in message news:<memo.2002010...@brangdon.madasafish.com>...

> ka...@gabi-soft.de (James Kanze) wrote (abridged):
> > The reason for separate compilation is managing dependancies. On
> > a large project, it is important that the authors of template
> > client code not have to wait for a complete implementation of the
> > template before they start to compile. The CFront model solved
> > this trivially, since instantiation didn't occur until link time.
> > I think that most current implementations, at least on Unix,
> > manage to solve this as well; if the template implementation isn't
> > visible at compile time, they will defer instantiation until link
> > time. In practice, they have to, because not doing so would break
> > existing code.

> According to some readings of the standard, this behaviour is
> mandated as part of support for explicit instantiation.

Then there are a number of compilers which aren't conform. G++ will
not complain if it cannot instantiate a template at compile time, but
it won't instantiate it later if you don't provide an explicit
instantiation. And how could it; where would it find the context?

> Explicit instantiation often provides a practical alternative to
> "export".

> For example, code like:

> template <typename T>
> const T &max( const T &lhs, const T &rhs );

> int a = max( 10, 20 );

> should compile. It will even link and run if the template is defined
> and explicitly instantiated with int, and that doesn't have to be
> done by the compilation unit that uses the template.

Right. But with CFront, it would compile and link without explicit
instantiation, provided you put the source code in conventionally
named files.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

Sergey P. Derevyago

unread,
Jan 10, 2002, 1:57:34 PM1/10/02
to
Pete Becker wrote:
> > In particular, C.13.8 of TC++PL 3rd begins with: "It is important to define
> > template functions so that they have as few dependencies as possible on
> > nonlocal information. The reason is that a template will be used to generate
> > functions and classes based on unknown types and in unknown context."
> > And 14.6.2 [temp.dep] tells about too tricky issues to ignore the export
> > utility.
> In other words, separate compilation of templates is necessary because
> it makes it easier to write code that's incomprehensible. <g>
Not, really. Separate compilation of templates is necessary because we don't
want to know about f<>()'s guts.
In particular, you can open your favorite std::map header and explore how
many map<> guts we have to include in order to use it.
I don't very like to include 500 000 LOC in every file which needs <string>,
<list>, <map> and <vector> simultaneously :((

--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

---

Sergey P. Derevyago

unread,
Jan 10, 2002, 1:57:15 PM1/10/02
to
Dave Harris wrote:
> According to some readings of the standard, this behaviour is mandated as
> part of support for explicit instantiation. Explicit instantiation often
> provides a practical alternative to "export".
>
> For example, code like:
>
> template <typename T>
> const T &max( const T &lhs, const T &rhs );
>
> int a = max( 10, 20 );
>
> should compile. It will even link and run if the template is defined and
> explicitly instantiated with int, and that doesn't have to be done by the
> compilation unit that uses the template.
Unfortunately, explicit instantiation often provides an impractical
alternative to "export". In principle, such toy templates as max() don't
involve too much troubles to worry about. I.e. we can easily include them as
any ordinary inline functions.
The troubles appear with "complex templates" which instantiate other
templates. Consider the following code:

// some.hpp
template <class T> void f(T);

// some.cpp
template <class T> void f_guts(vector<list<T> >& vec)
{
// ...
}

template <class T> void f(T t)
{
// ...
f_guts(some_vec);
// ...
}

I.e. f<>() needs f_guts<>(). You can explicitly instantiate f<>() but,
generally speaking, you don't know about its guts.


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

---

Sergey P. Derevyago

unread,
Jan 10, 2002, 2:15:50 PM1/10/02
to
"P.J. Plauger" wrote:
> I'm vaguely aware of these issues --certainly we have to worry about
> hijacking and other lookup problems with our current (conventional)
> implementation of template definitions all in the library header files.
> If anyone can demonstrate a conforming program that can only be
> translated properly with the use of exported templates, then I'll
> listen harder.
Hmm. AFAIK there is some subtle difference between std:: and ::std::
prefixes. So if the following code is "conforming"

namespace My {

namespace std {

}

}

then certain templates in My scope...

> But my first reaction will be to submit a Defect Report.

Well, try to aks them what namespace do they consider as the standard: ::std
or std one?

> And my second will be to wait for a significant customer to report it
> as a problem that needs fixing for their marketplace.

Unfortunately, "significant customers" tend to avoid advanced template
features...


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

---

Sergey P. Derevyago

unread,
Jan 10, 2002, 2:27:00 PM1/10/02
to
Daveed Vandevoorde wrote:
> However, I don't think "export" solves this issue. In fact, you might
> argue it makes it worse: with "export" we now have the ability to
> introduce dependencies that are not visible within a single translation
> unit.
Yes, but I want to use export to place my template definitions in my own
certain context. Now I have to put it in headers and hope that user don't
break them with macros, using directives and so on.
Using export, the size of headers (which really affects the compilation time
of our projects) can dramatically be reduced. In particular, STL headers are
awfully big :((

--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

---

Pete Becker

unread,
Jan 10, 2002, 4:09:56 PM1/10/02
to
"Sergey P. Derevyago" wrote:

>
> Pete Becker wrote:
> > In other words, separate compilation of templates is necessary because
> > it makes it easier to write code that's incomprehensible. <g>
> Not, really. Separate compilation of templates is necessary because we don't
> want to know about f<>()'s guts.

Sheesh, doesn't anybody know waht "<g>" means?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

---

Dave Harris

unread,
Jan 10, 2002, 5:36:03 PM1/10/02
to
ka...@gabi-soft.de (James Kanze) wrote (abridged):
> > According to some readings of the standard, this behaviour is
> > mandated as part of support for explicit instantiation.
>
> Then there are a number of compilers which aren't conform. G++ will
> not complain if it cannot instantiate a template at compile time, but
> it won't instantiate it later if you don't provide an explicit
> instantiation.

It's not expected to. Either the template must use "export", or it must be
instantiated explicitly somewhere, or the definition must be available
when the template is used. It sounds as though G++ does conform.

My point is, the middle option allows authors of template client code to
do what you were asking for.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

---

Dave Harris

unread,
Jan 10, 2002, 6:27:11 PM1/10/02
to
non-ex...@iobox.com (Sergey P. Derevyago) wrote (abridged):

> The troubles appear with "complex templates" which instantiate
> other templates. [...]

> I.e. f<>() needs f_guts<>(). You can explicitly instantiate f<>() but,
> generally speaking, you don't know about its guts.

Surely an explicit instantiation of f<>() will force an (implicit)
instantiation of f_guts<>(). This means the source file which contains
the instantiations must be dependent on whatever f_guts<>() needs, but we
have at least avoided that dependency for clients of f<>(). There only
needs to be one file with the explicit instantiation.

I am not saying that we don't need "export", by the way. Having to
instantiate stuff explicitly is, at best, a chore, and at worst
error-prone and liable to undefined behaviour. I mentioned it here
because, in James Kanze situation as I understood it, he didn't need to
instantiate at all because he didn't need to link or execute his code. He
just wanted to compile parts of it.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

---

Edward Diener

unread,
Jan 11, 2002, 11:23:25 AM1/11/02
to
John H. Spicer wrote:

> In article <3C36421F...@earthlink.net> eldi...@earthlink.net writes:
>
>>P.J. Plauger wrote:
>>
>>
>>>"Kiril Avdeiv" <kav...@mail.ru> wrote in message news:873f7ae8.02010...@posting.google.com...
>>>
>>>
>>>
>>>>Seeing that you are rather close to the latest developments in regard
>>>>to the implementation of the keyword and its semantics, I want to ask
>>>>whether you, as a library writer, consider export to be a useful
>>>>feature. In other words and in terms of the terminology of the C++
>>>>standard -- will Dinkumware C++ library ever comprise translated
>>>>translation units as opposed to the current state of affairs when the
>>>>library is made up of instantiation units only?
>>>>
>>>>
>>>Only when our customers demand it. One use for separate compilation of
>>>templates is to hide source code, as you can do when precompiling
>>>modules for a binary library. Dinkumware has always relied on copyright
>>>protection, rather than proprietary restrictions, to protect our code,
>>>so we have no incentive to further burder our customers, or their
>>>customers in turn, with additional impediments.
>>>
>>
>>Not everyone wants to deal with copyright issues in regarding to code
>>distribution, or has the legal and financial means to do so. The small
>>developer may want to distribute the header files and final modules of
>>his implementation without having to distribute any source code and, if
>>part of the implementation is templated classes and templated function,
>>being able to use the export feature in order to distribute templated
>>code, without distributing templated implementations, would be a great
>>boon to him.
>>
>>
>

> The export feature does not provide this facility. An implementation can
> require that the source be available when instantiations are generated.
>


Yes, I understand that. But as I understand it, export could be written
to provide the facility I mention above. In which case, if it was, I
think it would be a boon to the distribution of template code in much
the same way as the distribution of header files might be seen as a boon
to the distribution of class code. In general I think the distinction
between the declaration of types and the definition of types is a
valuable idea since it fairly cleanly separates types between what the
user of types sees and the creator of types sees.

I am amused at the programmers who think it is a great advance of
language that declarations of types be eliminated in favor of their
complete definitions in the same file ( ala Java ). To me it is much
cleaner that the user of a type sees only as much as need be to use that
type in code and isn't distracted by implementation code. Too often
having implementation code in view is just an excuse for not documenting
functionality. In all of these senses I would love to see an
implementation of export which is able to provide this separation even
if doing so is not mandated in any way by the C++ standard.

Eugene Karpachov

unread,
Jan 11, 2002, 1:00:20 PM1/11/02
to
Thu, 10 Jan 2002 18:57:34 GMT Sergey P. Derevyago wrote:
> I don't very like to include 500 000 LOC in every file which needs <string>,
><list>, <map> and <vector> simultaneously :((

I think it is QOI issue. That is, precompiled (by vendor) headers could
at least partially solve that problem - nothing in the standard requires
textual-only standard headers AFAIK.

--
jk

Pavel Kuznetsov

unread,
Jan 11, 2002, 1:16:44 PM1/11/02
to
Greg Comeau <com...@panix.com> wrote...
| Kiril Avdeiv <kav...@mail.ru> wrote...
| >I have the following question -- Is it really possible to implement
| >the keyword export with all its semantics as specified in the
| >standard?
|
| To the best of my understanding: yes.


Well, I do hope that compilers implementing export keyword should
compile `exported' templates much faster than `traditional' ones.
While for me `exported' templates are a kind of beasts from another
world, those are quite acquainted to you. So, could you encourage
me with the results of your acquaintance?

--
Pavel Kuznetsov

Daveed Vandevoorde

unread,
Jan 11, 2002, 1:53:09 PM1/11/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C3DEB90...@iobox.com>...

> Daveed Vandevoorde wrote:
> > However, I don't think "export" solves this issue. In fact, you might
> > argue it makes it worse: with "export" we now have the ability to
> > introduce dependencies that are not visible within a single translation
> > unit.
> Yes, but I want to use export to place my template definitions in my own
> certain context. Now I have to put it in headers and hope that user don't
> break them with macros, using directives and so on.

I think my example showed that "export" does not achieve that.
(It does with respect to macros, but not with respect to many
other things.) Users will break your exported templates just
as easily as (and more mysteriously than) included templates.

> Using export, the size of headers (which really affects the compilation time
> of our projects) can dramatically be reduced. In particular, STL headers are
> awfully big :((

The export model doesn't save you here either: it makes it worse.
When instantiating a template, you no longer just carry the
context included in one translation unit, but that of several.
In other words, compiling a single translation unit may require
the processing of all the #include'd declarations of several
other translation units.

I understand your desires with regard to a template separation
model: they're mine too. However, they're not fulfilled by C++'s
export model. That is not because there was no willingness to do
so, but because no agreeable specifications were found that could
meet those desiderata.

Daveed

Daveed Vandevoorde

unread,
Jan 11, 2002, 5:18:30 PM1/11/02
to
ka...@gabi-soft.de (James Kanze) wrote:
[...]

> I didn't see John Spicer's posting, so I'll answer it here. As a
> user, I never had any problems with the CFront model.

However, I distinctly remember you explaining that you didn't
use templates much (because they weren't portable at the time).

> I know what the
> theoretical problems are, but they just don't occur in practice.

I assure you that they do. I used to work for a company that
provided a cfront-based compiler for a long time and several
customers were quite unhappy with cfront's template model.
It was the main issue that made that company switch to alternative
technology (though other less critical limitations of cfront
played as well).

[...]


> The reason for separate compilation is managing dependancies.

I agree that could be expected from a separate compilation model,
but I don't think that that's provided by the C++ export model.
(It's a tough problem to solve, especially in the existing C++
source model.)

> On a
> large project, it is important that the authors of template client
> code not have to wait for a complete implementation of the template
> before they start to compile.

Note that that is not a limitation of the inclusion model.
It is perfectly possible to compile code without the definitions being
available.

> The CFront model solved this trivially,
> since instantiation didn't occur until link time.

However, even the 10-100 MLOC projects I worked with created
environments where you could link and execute the product at
intermediate stages of development. In such environments,
the cfront model was simply unusable (we regularly heard of
cfront ports that took several _days_ to link whereas other
C++ systems did the job under an hour).

> I think that most
> current implementations, at least on Unix, manage to solve this as
> well; if the template implementation isn't visible at compile time,
> they will defer instantiation until link time. In practice, they have
> to, because not doing so would break existing code.

Actually, I think those systems are now a minority, even on Unix.
Other than cfront, which systems work that way?
(I suspect I'm misunderstanding what you're saying here.)

> > Presumably because the name lookup machinery wasn't that complicated
> > as we have now?
>
> I don't think that's the problem. The name lookup (complex or simple)
> takes place in a specific context. The problem is to provide that
> context. In C++, the *only* context we have is the result of
> physically having copied a number of files into one (#include); at any
> given point in a C++ program, you see literally everything that was
> copied in before.

Well, we now also have the export model tied with argument-dependent
lookup (which transcends the translation unit barrier).

[...]


> In an ideal world, I'm not really certain what the rules for name
> binding should be. I don't like the current rules; I find them too
> complex, and too confusing. I understand John Spicer's concern for
> name hijacking, but I'm sceptical as to whether it is a real problem.
> In the end, there is nothing to stop the template author from fully
> qualifying everything if he is worried.

You cannot in general always reasonably qualify dependent functions
and operators. For example:

export template<typename T> f(T) {
g(T); // Which g? ::g may not be appropriate.
}

Daveed

Greg Comeau

unread,
Jan 11, 2002, 5:30:25 PM1/11/02
to
In article <a1ms25$tof$1...@gw.meridian.com.ua>,

Pavel Kuznetsov <su41vo...@sneakemail.com> wrote:
>Greg Comeau <com...@panix.com> wrote...
>| Kiril Avdeiv <kav...@mail.ru> wrote...
>| >I have the following question -- Is it really possible to implement
>| >the keyword export with all its semantics as specified in the
>| >standard?
>|
>| To the best of my understanding: yes.
>
>Well, I do hope that compilers implementing export keyword should
>compile `exported' templates much faster than `traditional' ones.

I think it's going to take incremental implementation "tweaks",
just like every other feature has. And only then can we see
where we are.

>While for me `exported' templates are a kind of beasts from another
>world, those are quite acquainted to you. So, could you encourage
>me with the results of your acquaintance?

I also think it's going to take a learning curve, for everybody.
Info will come forth as things materialize.
--
Greg Comeau What's next: additional Windows backends and 'export'!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

Sergey P. Derevyago

unread,
Jan 13, 2002, 10:20:05 AM1/13/02
to
Daveed Vandevoorde wrote:
> > In an ideal world, I'm not really certain what the rules for name
> > binding should be. I don't like the current rules; I find them too
> > complex, and too confusing. I understand John Spicer's concern for
> > name hijacking, but I'm sceptical as to whether it is a real problem.
> > In the end, there is nothing to stop the template author from fully
> > qualifying everything if he is worried.
>
> You cannot in general always reasonably qualify dependent functions
> and operators. For example:
>
> export template<typename T> f(T) {
> g(T); // Which g? ::g may not be appropriate.
> }
Well, consider the following non-template code:

void f(A a) {
g(a);
}

Which g? IMHO the answer is well-known: there should be some g() in the scope.

Currently, I we can write:

// file.hpp
void f(A);

// file.cpp
void f(A a) { /* */ }

But I long for:

// file.hpp


template <class T> void f(T);

// file.cpp
export template <class T> void f(T t) { /* */ }


--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

---

James Kanze

unread,
Jan 14, 2002, 10:39:26 AM1/14/02
to
Pete Becker <peteb...@acm.org> writes:

|> "John H. Spicer" wrote:

|> > It is not a proof of concept because it in no way did anything
|> > that resembles separate compilation. I posted a detailed
|> > description of exactly what cfront does that should permit readers
|> > to draw their own conclusions.

|> Just to bring this home: what cfront did was to compile each
|> distinct template instantiation directly from the template's source
|> code. Separate compilation means compiling the template once, to
|> some intermediate form, and generating instantiations from that
|> intermediate form.

Separate compilation apparently means different things to different
people. For John, for example, the control of name binding is
important, for you, the fact that the compiler only scans the actual
sources once. For me, the key point is being able to compile client
code before the implementation of the template code is available.

One thing that might make a difference in viewpoint is that John writes
compilers (where name binding is one of the most critical things to get
right) for a living, you write libraries (where being able to deliver
already compiled code can only be seen as an advantage), and I develop
applications -- some of which are very large, and being to compile
client code before the template implementation is a critical point in
reducing human dependancies.

--
James Kanze mailto:ka...@gabi-soft.de

Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

James Kanze

unread,
Jan 14, 2002, 10:40:11 AM1/14/02
to
j...@edg.com (John H. Spicer) writes:

|> And again, what cfront did was in no way seperate compilation. The
|> templates are not in separately compiled files and the semantics are
|> not at all like export.

I think part of the hang up here is the AND in your sentence. I think
that we all agree that the semantics of export are considerably
different than the semantics implemented by CFront. And although I very
much like CFront, and found it an extremely useful tool.

But semantics and separate compilation are, in the minds of many of us,
orthogonal issues. (Not from the implementation point of view, of
course. I'm sure some semantics make implementation far more difficult
than others. But from the user point of view.) And that separate
compilation seems to mean different things to different people. As
someone who has worked on very large applications, and who is concerned
about dependancies between people working on the project, the critical
issue is that I can compile my client sources before the implementation
of the template code is available. Having read your other postings, I'm
not sure if this is really what should be meant be separate compilation,
but it is what I have meant by it (rightly or wrongly) for many years.

[...]
|> Please explain how what cfront does can in any way be considered
|> separate compilation of templates. Please refer to my earlier
|> messages for why I believe it is not separate compilation.

As I say above, it depends on your definition of separate compilation.
Forgetting about the exact words, I think it safe to say that we all
recognize that CFront isn't really useful as a model to implement
export. This doesn't take anything away from the importance of the
pioneering role of CFront in template implementations, and it shouldn't
be taken to imply that there was anything intrinsically inferior in what
CFront did. It served my needs (at least in the large projects) better
than any compiler since.

I think it is also important to point out, however, that whatever its
qualities, the CFront specification simply didn't lend itself to
standardization. Although the heuristic worked very well in practice,
at least in well organized shops, it played havoc with the phases of
compilation.

|> > In a model where names in template declarations or definitions are
|> > looked up at instantiation time, it is quite possible to place
|> > templates in separately compiled files: The translation unit --
|> > say CT.tu -- resulting from a .C file where the templates are
|> > defined can be encoded (in one or another form) and consitutes the
|> > separate compiled file. At instantiation time, names are lookup up
|> > first in CT.tu, then in the translation unit requesting the
|> > instantiation.

|> But then you are not separately compiling the templates in any
|> meaningful way. This is indistinguishable from just including the
|> template definition.

With regards to semantics. It *does* mean that I can compile client
code without the implementation of the template being available. For my
purposes, that's the key -- it's what I need.

Other people's needs may differ.

|> This is like saying that include files are a form of separate
|> compilation. I would argue that a process that does neither name
|> lookup or any kind of semantic analysis does not qualify as a form
|> of compilation.

That's one definition of compilation:-).

As I say, I don't think it's important, and I think we're wasting time
arguing about what exactly constitutes separate compilation. The
questions are: how do I use it, and what are it's semantics? For the
first question, CFront was acceptable, as a proof of concept, and it was
significantly superior to anything that has followed to date. For the
second, CFront's semantics, to put it mildly, stretched the phases of
compilation well beyond the breaking point. Could there have been
semantics which allowed an acceptable answer to the first question, and
been easier to implement than export? Probably -- the standard is the
work of human beings, after all. Were any such semantics proposed? I
don't know of them. I'm not fully happy about export, but since I don't
have anything better to propose, I'll hold my peace.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

James Kanze

unread,
Jan 14, 2002, 10:40:43 AM1/14/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

|> ka...@gabi-soft.de (James Kanze) wrote:
|> [...]
|> > I didn't see John Spicer's posting, so I'll answer it here. As a
|> > user, I never had any problems with the CFront model.

|> However, I distinctly remember you explaining that you didn't use
|> templates much (because they weren't portable at the time).

Some companies stayed with CFront a very long time:-). After templates
did become portable. (Also, some of my customers didn't realize the
importance of portability until they had to port:-).)

|> > I know what the theoretical problems are, but they just don't
|> > occur in practice.

|> I assure you that they do. I used to work for a company that
|> provided a cfront-based compiler for a long time and several
|> customers were quite unhappy with cfront's template model. It was
|> the main issue that made that company switch to alternative
|> technology (though other less critical limitations of cfront played
|> as well).

Knowing which company that was:-)... My customer at the time was eager
to switch because of bugs in the CFront multiple inheritance
implementation. And couldn't, because he had used templates, and
counted on CFront's separate compilation:-).

I've also heard a lot of complaints concerning the speed of CFront, or
problems with inconsistencies in the repository; anytime you got a
strange error, the first thing to do was clear out the repository, and
rebuild, which took forever. These are what I would consider
implementation problems (bugs, if you prefer), but not a problem with
the model itself. Unless, of course, you pretend that the model cannot
be made to work better: at least two people far more qualified than
myself have expressed serious doubts about making the model work, so
there may be something in this. (The qualifications of the people in
question are such that if they express doubts, I will only dare
contradict them if I have actually implemented it myself.)

|> [...]
|> > The reason for separate compilation is managing dependancies.

|> I agree that could be expected from a separate compilation model,
|> but I don't think that that's provided by the C++ export model.
|> (It's a tough problem to solve, especially in the existing C++
|> source model.)

The standard certainly doesn't require it. But then, it doesn't require
it from non-template code either -- a conforming implementation could
simply use the preprocessed sources as its "object file" format.

A quality implementation would solve that problem, and at least one
compiler writer expressed to me in private email that one of the reasons
their implementation wasn't available yet is that they would not release
something that wasn't really usable.

|> > On a large project, it is important that the authors of template
|> > client code not have to wait for a complete implementation of the
|> > template before they start to compile.

|> Note that that is not a limitation of the inclusion model. It is
|> perfectly possible to compile code without the definitions being
|> available.

I know that there are several technical solutions possible. I really
don't care which one is used, as long as it works:-). (Of course, I'm
talking about high quality solutions. The problem is trivial with the
theoretical implementation above, using the preprocessed sources as the
object file format.)

|> > The CFront model solved this trivially, since instantiation didn't
|> > occur until link time.

|> However, even the 10-100 MLOC projects I worked with created
|> environments where you could link and execute the product at
|> intermediate stages of development.

True. And the template implementations had to be available then.

|> In such environments, the cfront model was simply unusable (we
|> regularly heard of cfront ports that took several _days_ to link
|> whereas other C++ systems did the job under an hour).

This is a real problem. Not that the more modern compilers are better;
Sun CC 5.0 is significantly slower than the CFront based 3.1. (This
could be largely due to the fact that the code uses more templates. In
5.0, cin is a template; in 3.1, it wasn't.)

|> > I think that most current implementations, at least on Unix,
|> > manage to solve this as well; if the template implementation isn't
|> > visible at compile time, they will defer instantiation until link
|> > time. In practice, they have to, because not doing so would break
|> > existing code.

|> Actually, I think those systems are now a minority, even on Unix.
|> Other than cfront, which systems work that way? (I suspect I'm
|> misunderstanding what you're saying here.)

What I'm saying is that most Unix compilers have a backwards
compatibility mode which permits code developed under CFront to continue
to compile, without modifications. I know Sun CC does (Sun CC, at least
4.2, does give a warning), and I've been told that EDG based compilers
do.

|> > > Presumably because the name lookup machinery wasn't that
|> > > complicated as we have now?

|> > I don't think that's the problem. The name lookup (complex or
|> > simple) takes place in a specific context. The problem is to
|> > provide that context. In C++, the *only* context we have is the
|> > result of physically having copied a number of files into one
|> > (#include); at any given point in a C++ program, you see literally
|> > everything that was copied in before.

|> Well, we now also have the export model tied with argument-dependent
|> lookup (which transcends the translation unit barrier).

|> [...]
|> > In an ideal world, I'm not really certain what the rules for name
|> > binding should be. I don't like the current rules; I find them
|> > too complex, and too confusing. I understand John Spicer's
|> > concern for name hijacking, but I'm sceptical as to whether it is
|> > a real problem. In the end, there is nothing to stop the template
|> > author from fully qualifying everything if he is worried.

|> You cannot in general always reasonably qualify dependent functions
|> and operators. For example:
|>
|> export template<typename T> f(T) {
|> g(T); // Which g? ::g may not be appropriate.
|> }

If ::g isn't appropriate, which g is? I won't say it's impossible, but
I can't come up with an example off hand where there is no acceptable
qualification of g. In a template function, it is either global (::g),
or in a namespace (name::g), or perhaps a static member of something
(which must be qualified in any case). In a function of a template
class, you can add base class members, but there too, qualification is
possible. What am I missing?

--
James Kanze mailto:ka...@gabi-soft.de

Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

James Kanze

unread,
Jan 14, 2002, 12:06:01 PM1/14/02
to
bran...@cix.co.uk (Dave Harris) writes:

|> ka...@gabi-soft.de (James Kanze) wrote (abridged):
|> > > According to some readings of the standard, this behaviour is
|> > > mandated as part of support for explicit instantiation.

|> > Then there are a number of compilers which aren't conform. G++
|> > will not complain if it cannot instantiate a template at compile
|> > time, but it won't instantiate it later if you don't provide an
|> > explicit instantiation.

|> It's not expected to. Either the template must use "export", or it
|> must be instantiated explicitly somewhere, or the definition must be
|> available when the template is used. It sounds as though G++ does
|> conform.

|> My point is, the middle option allows authors of template client
|> code to do what you were asking for.

I've lost track of what is being said. What middle option? Looking
back, all I can see is that I said that compilers were not required to
instantiate a template at link time if they hadn't done so earlier. To
which you responded that some interpretations of the standard imply that
they must. To which I answered that if this were the case, many
compilers where not conform. I cited g++, but I could have just as
easily cited almost any Windows compiler.

--
James Kanze mailto:ka...@gabi-soft.de

Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

James Kanze

unread,
Jan 14, 2002, 12:06:27 PM1/14/02
to
j...@edg.com (John H. Spicer) writes:

|> Inline functions already suffer from the alleged dependency problems
|> that export is supposed to address yet I have not seen any evidence
|> that this is a cause of problems.

That's because you don't have to use them. In every large scale project
I've worked on, in fact, inline functions have been banned because of
the dependancies they create.

Anthony Williams

unread,
Jan 14, 2002, 12:07:30 PM1/14/02
to
"James Kanze" <ka...@gabi-soft.de> wrote in message
news:86bsfxo...@alex.gabi-soft.de...

The template might expect to find g by argument-dependent lookup. If g is an
operator, you cannot avoid this.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer

Daveed Vandevoorde

unread,
Jan 14, 2002, 2:51:44 PM1/14/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote:
> Daveed Vandevoorde wrote:
[...]

> > You cannot in general always reasonably qualify dependent functions
> > and operators. For example:
> >
> > export template<typename T> f(T) {
> > g(T); // Which g? ::g may not be appropriate.
> > }
> Well, consider the following non-template code:
>
> void f(A a) {
> g(a);
> }
>
> Which g? IMHO the answer is well-known: there should be some
> g() in the scope.

IThat is my point though: in the nondependent case, it "well-known"
(though g might not be in scope with ADL). However, in the dependent
case it is _not_ known (in general); it might not be a "g" from the
translation unit in which the definition appears.


> Currently, I we can write:
>
> // file.hpp
> void f(A);
>
> // file.cpp
> void f(A a) { /* */ }
>
> But I long for:
>
> // file.hpp
> template <class T> void f(T);
>
> // file.cpp
> export template <class T> void f(T t) { /* */ }

(The declaration in file.hpp should also be tagged "export".)

I understand (and our in-house compiler supports that).
However, it may not be the blue skies you hope for: dependencies
between the client and the implementation remain (as I illustrated
before), mysterious interactions appear, etc.

Daveed

Pete Becker

unread,
Jan 15, 2002, 10:06:05 AM1/15/02
to
James Kanze wrote:
>
> Pete Becker <peteb...@acm.org> writes:
>
> |> "John H. Spicer" wrote:
>
> |> > It is not a proof of concept because it in no way did anything
> |> > that resembles separate compilation. I posted a detailed
> |> > description of exactly what cfront does that should permit readers
> |> > to draw their own conclusions.
>
> |> Just to bring this home: what cfront did was to compile each
> |> distinct template instantiation directly from the template's source
> |> code. Separate compilation means compiling the template once, to
> |> some intermediate form, and generating instantiations from that
> |> intermediate form.
>
> Separate compilation apparently means different things to different
> people. For John, for example, the control of name binding is
> important, for you, the fact that the compiler only scans the actual
> sources once. For me, the key point is being able to compile client
> code before the implementation of the template code is available.
>
> One thing that might make a difference in viewpoint is that John writes
> compilers (where name binding is one of the most critical things to get
> right) for a living, you write libraries (where being able to deliver
> already compiled code can only be seen as an advantage), and I develop
> applications -- some of which are very large, and being to compile
> client code before the template implementation is a critical point in
> reducing human dependancies.
>

The main difference, however, is that cfront did not do what the C++
standard requires. Arguing that cfront is a proof of concept is,
therefore, wrong.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

---

Richard Smith

unread,
Jan 15, 2002, 10:15:44 AM1/15/02
to

"James Kanze" <ka...@gabi-soft.de> wrote in message
news:86k7umn...@alex.gabi-soft.de...

> Pete Becker <peteb...@acm.org> writes:
>
> |> "John H. Spicer" wrote:
>
> |> > It is not a proof of concept because it in no way did anything
> |> > that resembles separate compilation. I posted a detailed
> |> > description of exactly what cfront does that should permit readers
> |> > to draw their own conclusions.
>
> |> Just to bring this home: what cfront did was to compile each
> |> distinct template instantiation directly from the template's source
> |> code. Separate compilation means compiling the template once, to
> |> some intermediate form, and generating instantiations from that
> |> intermediate form.
>
> Separate compilation apparently means different things to different
> people. For John, for example, the control of name binding is
> important, for you, the fact that the compiler only scans the actual
> sources once. For me, the key point is being able to compile client
> code before the implementation of the template code is available.

But the standard does not require that client code can be compiled before
the implementation of the template code is avaliable: 14/9 says "[Note: an
implementation may require that a translation unit containing the definition
of an exported template be compiled before any translation unit containing
an instantiation of that template.]". It will interesting to see whether
Comeau requires this or not.

--
Richard Smith

Richard Smith

unread,
Jan 15, 2002, 10:46:04 AM1/15/02
to

"James Kanze" <ka...@gabi-soft.de> wrote in message
news:86elkun...@alex.gabi-soft.de...

> bran...@cix.co.uk (Dave Harris) writes:
>
> |> ka...@gabi-soft.de (James Kanze) wrote (abridged):
> |> > > According to some readings of the standard, this behaviour is
> |> > > mandated as part of support for explicit instantiation.
>
> |> > Then there are a number of compilers which aren't conform. G++
> |> > will not complain if it cannot instantiate a template at compile
> |> > time, but it won't instantiate it later if you don't provide an
> |> > explicit instantiation.
>
> |> It's not expected to. Either the template must use "export", or it
> |> must be instantiated explicitly somewhere, or the definition must be
> |> available when the template is used. It sounds as though G++ does
> |> conform.
>
> |> My point is, the middle option allows authors of template client
> |> code to do what you were asking for.
>
> I've lost track of what is being said. What middle option?

I think Dave Harris meant,

1. The export mechanism must be used, or
2. there must be an explicit instantiation somewhere, or
3. the template must have been successfully implicitly instantiated
elsewhere.


I've always been of the opinion that the language should support some
standard way of forward declaring explicit instantiations of classes. (Many
compilers do this as an extension with the syntax "extern template class
foo<bar>;".) If this were the allowed, then it would be reasonable for the
standard to require that when a templated function is used it should have
either

i) been declared exported, or
ii) been explicitly instantiated, or
iii) been forward declared for explicit instantiation, or
iv) been successfully implicitly instantiated,

or failing these a error is reported.

This would stop the example from earlier in this thread,

template <typename T>
const T &max( const T &lhs, const T &rhs );

int a = max( 10, 20 );

from compiling because none of the four conditions are met. In my
experience, most of the time that someone writes code like this, it is
because they have forgotten to include some header, and frequently this
results in a link error, if not immediately, then at a later point when
another unrelated piece of code is changed.


--
Richard Smith

James Kanze

unread,
Jan 15, 2002, 10:59:26 AM1/15/02
to
"Anthony Williams"<ant...@nortelnetworks.com> wrote in message
news:<a1v0m7$293$1...@bcarh8ab.ca.nortel.com>...

Good point. I hadn't thought of operators. If I can imagine
requiring template authors to write ::std::sin(x), instead of just
sin(x), requiring ::???::operator+(x,y) instead of x+y is beyond the
bounds of reasonable (although Java requires it, but that's another
story). It also doesn't work if x and y are built-in types: to write
templates this way, I'd have to specialize on all of the built-in
types, in order to use the operator notation rather than the
functional notation. (I've never encountered any problems because of
this, but my work doesn't normally involve much numerical processing,
and overloaded operators are pretty rare.)

Which leads me back to the original point. David Vandervoorde stated
that at an earlier employer, a number of customers complained about
CFront templates. It would be interesting to know if it were because
of this problem, or because of the well known problems of build time
and dependancy management. I'm curious because my impression is that
the double name lookup solves a non-existant problem. (But I could be
wrong.)

--
James Kanze mailto:ka...@gabi-soft.de

Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

Daveed Vandevoorde

unread,
Jan 15, 2002, 2:32:26 PM1/15/02
to
James Kanze <ka...@gabi-soft.de> wrote :

> goo...@vandevoorde.com (Daveed Vandevoorde) writes:
>
> |> ka...@gabi-soft.de (James Kanze) wrote:
[...]
> |> > I know what the theoretical problems are, but they just don't
> |> > occur in practice.
>
> |> I assure you that they do. I used to work for a company that
> |> provided a cfront-based compiler for a long time and several
> |> customers were quite unhappy with cfront's template model. It was
> |> the main issue that made that company switch to alternative
> |> technology (though other less critical limitations of cfront played
> |> as well).
>
> Knowing which company that was:-)... My customer at the time was eager
> to switch because of bugs in the CFront multiple inheritance
> implementation. And couldn't, because he had used templates, and
> counted on CFront's separate compilation:-).

They could have used the compatibility option you mention below.



> I've also heard a lot of complaints concerning the speed of CFront, or
> problems with inconsistencies in the repository; anytime you got a
> strange error, the first thing to do was clear out the repository, and
> rebuild, which took forever. These are what I would consider
> implementation problems (bugs, if you prefer), but not a problem with
> the model itself. Unless, of course, you pretend that the model cannot
> be made to work better: at least two people far more qualified than
> myself have expressed serious doubts about making the model work, so
> there may be something in this. (The qualifications of the people in
> question are such that if they express doubts, I will only dare
> contradict them if I have actually implemented it myself.)

I suppose it all depends on what you call "the model". However, I
don't think that "when you compile all the translation units by
themselves and then you link their output it works" is a viable model
specification.

Later cfront version worked correctly according to their model in many
(or all) of the cases where users were cleaning out the repository.
The problem was that they didn't not "model the cfront model" in their
dependency analysis. That is no surprise because cfront's model is an
inclusion model with quasi-implicit includes (they're explicit in the
synthesized source but it is a pain to model those in Makefiles and the
like).

> |> [...]
> |> > The reason for separate compilation is managing dependancies.
>
> |> I agree that could be expected from a separate compilation model,
> |> but I don't think that that's provided by the C++ export model.
> |> (It's a tough problem to solve, especially in the existing C++
> |> source model.)
>
> The standard certainly doesn't require it.

I believe that for practical purposes it requires the opposite: a client
of an exported template is dependent not only on the interface of that
template, but also on its implementation. This is the same sort of
dependency that you get with the inclusion model, except there is no
source-visible indication of that dependency.

> But then, it doesn't require
> it from non-template code either -- a conforming implementation could
> simply use the preprocessed sources as its "object file" format.
>
> A quality implementation would solve that problem, and at least one
> compiler writer expressed to me in private email that one of the reasons
> their implementation wasn't available yet is that they would not release
> something that wasn't really usable.

I guess we disagree: I claim that you cannot remove the dependency
because the model mandates it. You can try to embed the implementation
in the "object file", but that doesn't address the dependency management
issue.

[...]


> |> > I think that most current implementations, at least on Unix,
> |> > manage to solve this as well; if the template implementation isn't
> |> > visible at compile time, they will defer instantiation until link
> |> > time. In practice, they have to, because not doing so would break
> |> > existing code.
>
> |> Actually, I think those systems are now a minority, even on Unix.
> |> Other than cfront, which systems work that way? (I suspect I'm
> |> misunderstanding what you're saying here.)
>
> What I'm saying is that most Unix compilers have a backwards
> compatibility mode which permits code developed under CFront to continue
> to compile, without modifications. I know Sun CC does (Sun CC, at least
> 4.2, does give a warning), and I've been told that EDG based compilers
> do.

I don't think the compatibility mode defers the instantiation to link-time.
Instead, the regular inclusion model is used with a twist: the template
source is implicitly included at the end of the translation unit (with the
cfront convention to determine which file contains that source).

> |> > > Presumably because the name lookup machinery wasn't that
> |> > > complicated as we have now?
>
> |> > I don't think that's the problem. The name lookup (complex or
> |> > simple) takes place in a specific context. The problem is to
> |> > provide that context. In C++, the *only* context we have is the
> |> > result of physically having copied a number of files into one
> |> > (#include); at any given point in a C++ program, you see literally
> |> > everything that was copied in before.
>
> |> Well, we now also have the export model tied with argument-dependent
> |> lookup (which transcends the translation unit barrier).
>
> |> [...]
> |> > In an ideal world, I'm not really certain what the rules for name
> |> > binding should be. I don't like the current rules; I find them
> |> > too complex, and too confusing. I understand John Spicer's
> |> > concern for name hijacking, but I'm sceptical as to whether it is
> |> > a real problem. In the end, there is nothing to stop the template
> |> > author from fully qualifying everything if he is worried.
>
> |> You cannot in general always reasonably qualify dependent functions
> |> and operators. For example:
> |>
> |> export template<typename T> f(T) {
> |> g(T); // Which g? ::g may not be appropriate.
> |> }
>
> If ::g isn't appropriate, which g is? I won't say it's impossible, but
> I can't come up with an example off hand where there is no acceptable
> qualification of g.

The qualification will in general depend on the type T.
With the unqualified form you can hope that ADL will find the appropriate
function. However, you cannot emulate ADL with a qualifier.

> In a template function, it is either global (::g),
> or in a namespace (name::g), or perhaps a static member of something
> (which must be qualified in any case). In a function of a template
> class, you can add base class members, but there too, qualification is
> possible. What am I missing?

You don't know which namespace (presumably whatever namespace T
comes from, but we don't know that).

Daveed

Dave Harris

unread,
Jan 15, 2002, 4:21:46 PM1/15/02
to
ric...@ex-parrot.com (Richard Smith) wrote (abridged):

> I think Dave Harris meant,

You were right.


> I've always been of the opinion that the language should support some
> standard way of forward declaring explicit instantiations of classes.

That sounds like a good idea to me.


> In my experience, most of the time that someone writes code like
> this, it is because they have forgotten to include some header,
> and frequently this results in a link error, if not immediately,
> then at a later point when another unrelated piece of code is
> changed.

Actually I use forward declarations of templates even when the definition
of the template appears later in the same header. It is just a way of
reducing clutter in the header.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

---

Dave Harris

unread,
Jan 15, 2002, 4:22:14 PM1/15/02
to
ka...@gabi-soft.de (James Kanze) wrote (abridged):
> I've lost track of what is being said. What middle option?

See Richard Smith's answer.


> Looking back, all I can see is that I said that compilers were
> not required to instantiate a template at link time if they hadn't
> done so earlier.

You said:
On a large project, it is important that the authors of template
client code not have to wait for a complete implementation of
the template before they start to compile.

and mentioned some compilers which allowed this. I pointed out that
because of explicit instantiation, they *must* allow it.

I didn't mean to imply the compiler would instantiate implicitly at link
time. Indeed, I thought I made it clear that the template would need to be
instantiated explicitly before linking.


> I cited g++, but I could have just as easily cited almost any
> Windows compiler.

Microsoft VC++ 6 supports explicit instantiation in different compilation
units, so can be used to separate clients of a template from its
implementation as I described.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

---

Daveed Vandevoorde

unread,
Jan 16, 2002, 10:51:57 AM1/16/02
to
James Kanze <ka...@gabi-soft.de> wrote:
[...]

> But semantics and separate compilation are, in the minds of many of us,
> orthogonal issues. (Not from the implementation point of view, of
> course. I'm sure some semantics make implementation far more difficult
> than others. But from the user point of view.) And that separate
> compilation seems to mean different things to different people. As
> someone who has worked on very large applications, and who is concerned
> about dependancies between people working on the project, the critical
> issue is that I can compile my client sources before the implementation
> of the template code is available. Having read your other postings, I'm
> not sure if this is really what should be meant be separate compilation,
> but it is what I have meant by it (rightly or wrongly) for many years.

Every popular template instantiation model satisfies that requirement
however. The currently standard "inclusion model" can be considered
"separate compilation" with that criterion (which seems odd to me).

[...]


> As I say, I don't think it's important, and I think we're wasting time
> arguing about what exactly constitutes separate compilation. The
> questions are: how do I use it, and what are it's semantics? For the
> first question, CFront was acceptable, as a proof of concept, and it was
> significantly superior to anything that has followed to date.

You have to admit that that is a pretty unusual opinion. Most
developers have not exactly been clamoring for the cfront model
(on the contrary).

Daveed

Daveed Vandevoorde

unread,
Jan 16, 2002, 10:52:34 AM1/16/02
to
ka...@gabi-soft.de (James Kanze) wrote:
> "Anthony Williams"<ant...@nortelnetworks.com> wrote in message
> news:<a1v0m7$293$1...@bcarh8ab.ca.nortel.com>...
> > "James Kanze" <ka...@gabi-soft.de> wrote in message
> > news:86bsfxo...@alex.gabi-soft.de...
> > > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
>
> > > |> ka...@gabi-soft.de (James Kanze) wrote:
> > > |> > In an ideal world, I'm not really certain what the rules for
> > > |> > name binding should be. I don't like the current rules; I
> > > |> > find them too complex, and too confusing. I understand John
> > > |> > Spicer's concern for name hijacking, but I'm sceptical as to
> > > |> > whether it is a real problem. In the end, there is nothing
> > > |> > to stop the template author from fully qualifying everything
> > > |> > if he is worried.
>
> > > |> You cannot in general always reasonably qualify dependent
> > > |> functions and operators. For example:
>
> > > |> export template<typename T> f(T) {
> > > |> g(T); // Which g? ::g may not be appropriate.
> > > |> }
[...]

> Which leads me back to the original point. David Vandervoorde stated
> that at an earlier employer, a number of customers complained about
> CFront templates. It would be interesting to know if it were because
> of this problem, or because of the well known problems of build time
> and dependancy management.

The latter: build times and implicit dependencies were the problem.

Cfront uses an inclusion model (i.e., the template implementation is
#included into a synthesized client environment to generate the
instantiations). In such a model you don't need multiple lookups
because there is only one translation unit to deal with. Ordinary
lookup works with that. Two-phase lookup also works in such a context
but which is better is a matter of taste. The two-phase lookup as
mandated by the standard possibly reduces the risk of picking unwanted
declarations (from the client context).

> I'm curious because my impression is that
> the double name lookup solves a non-existant problem. (But I could be
> wrong.)

If you have a true "separation model" for template instantiation
(i.e., a model where the client and the implementation remain in
separate translation units and are compiled separately), you need
a mechanism to "cross over" that translation unit boundary to
handle nontrivial dependent expressions. The two-phase lookup
(where the second phase is argument-dependent lookup (ADL))is one
way to address the problem.

Daveed

Gabriel Dos_Reis

unread,
Jan 16, 2002, 10:56:48 AM1/16/02
to
j...@edg.com (John H. Spicer) writes:

[...]

| > Well, at this point, maybe it is appropriate to recall the context of
| > my claims.
| >
| > "P.J. Plauger" <p...@dinkumware.com> wrote:
| >
| > [...]
| >
| > | > Seeing the high quality of their compiler I presume they have come up
| > | > against something not foreseen when the keyword was conceived.
| > |
| > | I think that EDG foresaw the difficulty. In fact, one of the EDG team
| > | made a yeoman effort to get separate compilation of templates removed
| > | from the C++ Standard. This is one of the problems with inventing in
| > | the guise of writing standards, and doing so literally up to the final
| > | moments before approval.
| >
| > Then I replied:
| >
| > The *concept of separate compilation of templates* wasn't the committee's
| > invention. CFront already made a proof of the concept.
| >
| > (Emphasis is added)


|
| And again, what cfront did was in no way seperate compilation. The templates
| are not in separately compiled files and the semantics are not at all
| like export.

Obviously, we have, each one, different notions of the concept of separate
compilation of templates.

For me, there exists different models of the concept of separate
compilation of templates, and the semantics mandated by the standard
is just *one* instance of separate compilation of templates. I've
described quite another model.

The impression I gain from your different messages is that, a separate
compilation of templates must have the export-semantics described in
ths standard. I find that to be a very restrictive definition of
separate compilation of templates.

| > | With non-exported templates you can simply say "lets defer all lookup to
| > | the point of instantiation", but you can't do that with exported templates
| > | because names from the definition context are not necessarily present
| > | at the point of instantiation.
| >
| > Yes, I do know that current rules require two-phase name lookup, but
| > then I don't think that two-phase name lookup is a sine qua non
| > condition for the "concept of separate compilation of templates".
| > Other rules are quite possible and one-phase lookup, that is,
| > deferring name lookup until instantiation time, is quite another model
| > ans is close to what CFront did. I don't think it is fair or accurate
| > to say that just because CFront didn't two-phase name-lookup means it
| > didn't a made a proof of the concept of separate compilation of
| > templates.
|
| I didn't say that. I said that some kind of two-phase lookup is required
| for export.

Precisely *why* you think two-phase name lookup would be required in a
separate compilation of templates is the key-question you might want
to answer before we can dig up this issue further.

[...]

| > In a model where names in template declarations or definitions are
| > looked up at instantiation time, it is quite possible to place
| > templates in separately compiled files: The translation unit -- say
| > CT.tu -- resulting from a .C file where the templates are defined can
| > be encoded (in one or another form) and consitutes the separate
| > compiled file. At instantiation time, names are lookup up first in

| > CT.tu, then in the translation unit requesting the instantiation.


| >
|
| But then you are not separately compiling the templates in any meaningful
| way. This is indistinguishable from just including the template definition.

Oh certainly, there IS a difference; at least from the user point of
view: he would no longer be required to include the templates in
*every* translation unit that uses them.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

Gabriel Dos_Reis

unread,
Jan 16, 2002, 10:57:15 AM1/16/02
to
"Richard Smith" <ric...@ex-parrot.com> writes:

[...]

| But the standard does not require that client code can be compiled before
| the implementation of the template code is avaliable:

nor does the standard mandate useful implementations.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 16, 2002, 10:58:49 AM1/16/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

[...]

| export template<typename T> f(T) {
| g(T); // Which g? ::g may not be appropriate.
| }

I don't think your example is particular to "export".
The same question arises with the inclusion-model.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 16, 2002, 10:58:41 AM1/16/02
to
ka...@gabi-soft.de (James Kanze) writes:

[...]

| Which leads me back to the original point.

Note, however, that if you defer name lookup until instantiation time,
then you suppress the dependent-name lookup problem -- that doesn't
mean you solve all problems though :-)

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 16, 2002, 10:58:05 AM1/16/02
to
"Richard Smith" <ric...@ex-parrot.com> writes:

[...]

| I've always been of the opinion that the language should support some


| standard way of forward declaring explicit instantiations of classes. (Many
| compilers do this as an extension with the syntax "extern template class
| foo<bar>;".)

And I would be glad to see any rationale of why the standard
explicitly forbids that construct.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr
>

If this were the allowed, then it would be reasonable for the


| standard to require that when a templated function is used it should have
| either
|
| i) been declared exported, or
| ii) been explicitly instantiated, or
| iii) been forward declared for explicit instantiation, or
| iv) been successfully implicitly instantiated,
|
| or failing these a error is reported.
|
| This would stop the example from earlier in this thread,
|
| template <typename T>
| const T &max( const T &lhs, const T &rhs );
|
| int a = max( 10, 20 );
|
| from compiling because none of the four conditions are met. In my
| experience, most of the time that someone writes code like this, it is
| because they have forgotten to include some header, and frequently this
| results in a link error, if not immediately, then at a later point when
| another unrelated piece of code is changed.
|
|
| --
| Richard Smith
|
|
| ---
| [ comp.std.c++ is moderated. To submit articles, try just posting with ]
| [ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
| [ --- Please see the FAQ before posting. --- ]
| [ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
|

--
Gabriel Dos Reis | Centre de Mathématiques et de
dos...@cmla.ens-cachan.fr | Leurs Applications
Fax : (33) 01 47 40 21 69 | ENS de Cachan -- CNRS (URA 1611)
61, Avenue du Pdt Wilson, 94235 Cachan - Cedex

Gabriel Dos_Reis

unread,
Jan 16, 2002, 1:21:55 PM1/16/02
to
Pete Becker <peteb...@acm.org> writes:

[...]

| The main difference, however, is that cfront did not do what the C++
| standard requires.

That, nobody disagrees with.

| Arguing that cfront is a proof of concept is,
| therefore, wrong.

Only if you assume that what the standard currently requires is the
sole and only possible model of the concept of separate compilation of
templates.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 16, 2002, 1:21:43 PM1/16/02
to
j...@edg.com (John H. Spicer) writes:

[...]

| It is not a proof of concept because it in no way did anything that
| resembles separate compilation.

That simply means you have a very stringent view of what separate
compilation of template should means. However, if you accept that
there can exist other models of separate compilation of templates,
then you'll that the export-model isn't just the only one possible
model.

Gabriel Dos_Reis

unread,
Jan 16, 2002, 1:22:04 PM1/16/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

| IThat is my point though: in the nondependent case, it "well-known"
| (though g might not be in scope with ADL). However, in the dependent
| case it is _not_ known (in general); it might not be a "g" from the
| translation unit in which the definition appears.

But the issue has to be deakt with in the inclusion-model.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

James Kanze

unread,
Jan 16, 2002, 1:25:41 PM1/16/02
to
bran...@cix.co.uk (Dave Harris) wrote in message news:<memo.20020115...@brangdon.madasafish.com>...

> You said:
> On a large project, it is important that the authors of template
> client code not have to wait for a complete implementation of the
> template before they start to compile.

> and mentioned some compilers which allowed this. I pointed out that
> because of explicit instantiation, they *must* allow it.

> I didn't mean to imply the compiler would instantiate implicitly at
> link time. Indeed, I thought I made it clear that the template would
> need to be instantiated explicitly before linking.

Yes. I think I was getting confused. Just been spoiled by CFront, I
guess:-). (John Spicer actually pointed this out to me in private
email over a year ago, so I have no excuse.)

> > I cited g++, but I could have just as easily cited almost any
> > Windows compiler.

> Microsoft VC++ 6 supports explicit instantiation in different
> compilation units, so can be used to separate clients of a template
> from its implementation as I described.

It works exactly like g++ (at least if you don't use any of the g++
pragmas). Sun CC gives a warning. If you eventually get to link time
without an instantiation, it will try to imitate CFront. Or at least,
version 4.2 did. (I haven't tried is since.)

--
James Kanze mailto:ka...@gabi-soft.de

Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

James Kanze

unread,
Jan 16, 2002, 1:31:51 PM1/16/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) wrote in message
news:<52f2f9cd.02011...@posting.google.com>...

> James Kanze <ka...@gabi-soft.de> wrote :
> > goo...@vandevoorde.com (Daveed Vandevoorde) writes:

> > |> ka...@gabi-soft.de (James Kanze) wrote:
> [...]
> > |> > I know what the theoretical problems are, but they just don't
> > |> > occur in practice.

> > |> I assure you that they do. I used to work for a company that
> > |> provided a cfront-based compiler for a long time and several
> > |> customers were quite unhappy with cfront's template model. It
> > |> was the main issue that made that company switch to
> > |> alternative technology (though other less critical limitations
> > |> of cfront played as well).

> > Knowing which company that was:-)... My customer at the time was
> > eager to switch because of bugs in the CFront multiple inheritance
> > implementation. And couldn't, because he had used templates, and
> > counted on CFront's separate compilation:-).

> They could have used the compatibility option you mention below.

They may have done so in the end. They only got their first version
of the new compiler shortly before I left, and I know that the change
in the template model was high on the list of upgrade problems.

> > I've also heard a lot of complaints concerning the speed of
> > CFront, or problems with inconsistencies in the repository;
> > anytime you got a strange error, the first thing to do was clear
> > out the repository, and rebuild, which took forever. These are
> > what I would consider implementation problems (bugs, if you
> > prefer), but not a problem with the model itself. Unless, of
> > course, you pretend that the model cannot be made to work better:
> > at least two people far more qualified than myself have expressed
> > serious doubts about making the model work, so there may be
> > something in this. (The qualifications of the people in question
> > are such that if they express doubts, I will only dare contradict
> > them if I have actually implemented it myself.)

> I suppose it all depends on what you call "the model". However, I
> don't think that "when you compile all the translation units by
> themselves and then you link their output it works" is a viable
> model specification.

Agreed. As I've mentioned earlier, CFront was a very good proof of
concept, but it made use of a number of ad hoc heuristics, which while
they worked well in practice, didn't lend themselves very well to
standardization.

> Later cfront version worked correctly according to their model in
> many (or all) of the cases where users were cleaning out the
> repository. The problem was that they didn't not "model the cfront
> model" in their dependency analysis. That is no surprise because
> cfront's model is an inclusion model with quasi-implicit includes
> (they're explicit in the synthesized source but it is a pain to
> model those in Makefiles and the like).

This is what I meant by the bugs in the implementation. It was, or
should have been, up to the implementation to manage dependancies in
the files it generates. CFront tried to, but didn't always succeed.

> > |> [...]
> > |> > The reason for separate compilation is managing dependancies.

> > |> I agree that could be expected from a separate compilation
> > |> model, but I don't think that that's provided by the C++
> > |> export model. (It's a tough problem to solve, especially in
> > |> the existing C++ source model.)

> > The standard certainly doesn't require it.

> I believe that for practical purposes it requires the opposite: a
> client of an exported template is dependent not only on the
> interface of that template, but also on its implementation. This is
> the same sort of dependency that you get with the inclusion model,
> except there is no source-visible indication of that dependency.

In practice, this isn't as much of a problem as I expected, since most
compilers will let you compile programs without instantiating the
templates if they cannot find the template implementation. The theory
is that if the compiler cannot find the implementation, there will be
an explicit instantiation later.

I'm still not overjoyed. From the beginning, what I wanted is that
templates be treated exactly like any other code: I provide a header
with the class definition, and one or more source files with the
implementation. I compile the source files into a library, and I
deliver the library and the headers. The client code includes the
headers, and links against the library.

Apparently, no implementor has ever supported this, either because
they don't want to, or they don't know how to, or both.

> > But then, it doesn't require it from non-template code either --
> > a conforming implementation could simply use the preprocessed
> > sources as its "object file" format.

> > A quality implementation would solve that problem, and at least
> > one compiler writer expressed to me in private email that one of
> > the reasons their implementation wasn't available yet is that they
> > would not release something that wasn't really usable.

> I guess we disagree: I claim that you cannot remove the dependency
> because the model mandates it. You can try to embed the
> implementation in the "object file", but that doesn't address the
> dependency management issue.

It would if the "object file" were not exploited until link time. But
as you say, the model forbids this. Or at least, makes it very
expensive.

> [...]
> > |> > I think that most current implementations, at least on Unix,
> > |> > manage to solve this as well; if the template implementation
> > |> > isn't visible at compile time, they will defer instantiation
> > |> > until link time. In practice, they have to, because not
> > |> > doing so would break existing code.

> > |> Actually, I think those systems are now a minority, even on
> > |> Unix. Other than cfront, which systems work that way? (I
> > |> suspect I'm misunderstanding what you're saying here.)

> > What I'm saying is that most Unix compilers have a backwards
> > compatibility mode which permits code developed under CFront to
> > continue to compile, without modifications. I know Sun CC does
> > (Sun CC, at least 4.2, does give a warning), and I've been told
> > that EDG based compilers do.

> I don't think the compatibility mode defers the instantiation to
> link-time. Instead, the regular inclusion model is used with a
> twist: the template source is implicitly included at the end of the
> translation unit (with the cfront convention to determine which file
> contains that source).

That's the default behavior. At least with Sun CC 4.2 (the last
compiler with which I really tried), if it couldn't find the files to
implicitly include, it issued a warning, but generated the object file
anyway. And at least from what I understand from private email with
the author (I never tried it), if there were still unresolved
dependancies due to uninstantiated templates at link time, it would
try to instantiate them then.

--
James Kanze mailto:ka...@gabi-soft.de

Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

James Kanze

unread,
Jan 16, 2002, 1:32:09 PM1/16/02
to
"Richard Smith" <ric...@ex-parrot.com> wrote in message
news:<1011106547.6975.0...@news.demon.co.uk>...

> > |> "John H. Spicer" wrote:

That's a non-normative note, and it doesn't tell us anything we don't
already know. An implementation is not required to support any useful
form of separate compilation, even if templates are not involved.

The standard has never made any requirements concerning the quality of
implementations.

> It will interesting to see whether Comeau requires this or not.

I will be very unhappy if it does, but whether it does or not, it
looks like it will be the best available implementation of export, at
least for a certain time.

I'm becoming more and more convinced that templates are a thing to
avoid.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

Pete Becker

unread,
Jan 17, 2002, 10:41:12 AM1/17/02
to
Gabriel Dos_Reis wrote:
>
> Pete Becker <peteb...@acm.org> writes:
>
> [...]
>
> | The main difference, however, is that cfront did not do what the C++
> | standard requires.
>
> That, nobody disagrees with.
>
> | Arguing that cfront is a proof of concept is,
> | therefore, wrong.
>
> Only if you assume that what the standard currently requires is the
> sole and only possible model of the concept of separate compilation of
> templates.
>

Or if you assume that the context of a discussion determines what its
terms mean. Of course, if you're willing to ignore context it's very
hard to have a meaningful discussion.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

---

Nicola Musatti

unread,
Jan 17, 2002, 11:01:50 AM1/17/02
to

"John H. Spicer" wrote:
[...]
> x.h:


> template <class T> void f(T);
>

> x.c:
> template <class T> void f(T){}
>
> a.h:
> struct A {};
>
> t.c:
>
> #include "a.h"
> #include "x.h"
>
> int main()
> {
> A a;
> f(a);
> }
>
> When you link this program, cfront creates this file in its ptrepository
> directory:
>
> #include "x.h"
> #include "x.c"
> #include "a.h"
>
> static void _dummy_(A a1)
> {
> f(a1);
> }
>
> The only thing special about the compilation is that it suppresses the
> output of any external entities found in the header files.
>
> There is no black magic going on here. The template definitions are
> just textually included, they are just included in a compiler-generated
> file instead of a user-written one. This in no way resembles what
> happens with exported templates, nor is there any way that I can see
> why anyone would consider this some form of separately compiled templates.

Probably because from a user's point of view x.c and t.c appear as
separate translation units and t.c is successfully compiled without
including function template definitions.

For a user like me, who only has a vague notion of what an
implementation actually does, separate compilation means: do not compile
the definitions of (member) function templates I use when you compile
*my* code. If I can run a command such as

cc x.c t.c

and obtain a working executable, it's okay by me provided the compiler
doesn't take to long to do what it has to do in order to correctly
compile templates.

To you separate compilation appears to mean: do not compile user code
(i.e. definitions of templates' actual arguments found in user code)
when you compile templates.

Cheers,
Nicola Musatti

Sergey P. Derevyago

unread,
Jan 17, 2002, 12:29:53 PM1/17/02
to
Daveed Vandevoorde wrote:
> > Well, consider the following non-template code:
> >
> > void f(A a) {
> > g(a);
> > }
> >
> > Which g? IMHO the answer is well-known: there should be some
> > g() in the scope.
> IThat is my point though: in the nondependent case, it "well-known"
> (though g might not be in scope with ADL). However, in the dependent
> case it is _not_ known (in general); it might not be a "g" from the
> translation unit in which the definition appears.
Yes, I've got it.
Not so long ago, the "quite separate" compilation of templates was possible.
But now any template can reach any other types (and not only) by means of its
template parameters:

template <class T> void f(T t)
{

typename T::other_type surprise;
surprise+surprise;
// ...
}

IMHO, in general, we have two variants of the export implementation:

1. Do not requre the definition of exported template and save all the context


at the point of instantiation.

2. Preliminary parse the definition and save only the needed elements of the
context.

Both variants have their own drawbacks and the current absence of export
seems to be quite reasonable. I.e. the current #include technique is
unsatisfactory but reasonable :(


> > Currently, I we can write:
> >
> > // file.hpp
> > void f(A);
> >
> > // file.cpp
> > void f(A a) { /* */ }
> >
> > But I long for:
> >
> > // file.hpp
> > template <class T> void f(T);
> >
> > // file.cpp
> > export template <class T> void f(T t) { /* */ }
>
> (The declaration in file.hpp should also be tagged "export".)
>

Yes, thanks. But your

> > > export template<typename T> f(T) {
> > > g(T); // Which g? ::g may not be appropriate.
> > > }

is much more worse :))

> I understand (and our in-house compiler supports that).

BTW did you completelly implemented export? And if you did, which variant did
you choose?
--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

Daveed Vandevoorde

unread,
Jan 17, 2002, 1:06:34 PM1/17/02
to
Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote:
> ka...@gabi-soft.de (James Kanze) writes:
>
> [...]
>
> | Which leads me back to the original point.
>
> Note, however, that if you defer name lookup until instantiation time,
> then you suppress the dependent-name lookup problem -- that doesn't
> mean you solve all problems though :-)

Can you elaborate on how that solves the problem?

Daveed

Daveed Vandevoorde

unread,
Jan 17, 2002, 1:27:13 PM1/17/02
to
Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote in message news:<xaj1ygq...@perceval.inria.fr>...

> goo...@vandevoorde.com (Daveed Vandevoorde) writes:
>
> | That is my point though: in the nondependent case, it "well-known"
> | (though g might not be in scope with ADL). However, in the dependent
> | case it is _not_ known (in general); it might not be a "g" from the
> | translation unit in which the definition appears.
>
> But the issue has to be [dealt] with in the inclusion-model.

I'm not entirely sure what your comment is aiming at (in general,
it would help if you were supporting your statements with a bit
of your line of thinking).

In the standard inclusion model the "g" will be from the same
translation unit; in the standard separation model it might not.

Having worked with both models, I can assure you that the
latter adds a whole new level of pain to tracking problems in
even relatively small projects.

Daveed

Daveed Vandevoorde

unread,
Jan 19, 2002, 11:52:21 AM1/19/02
to
Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote:
> j...@edg.com (John H. Spicer) writes:
> [...]
[...]

> | > The *concept of separate compilation of templates* wasn't the committee's
> | > invention. CFront already made a proof of the concept.
> | >
> | > (Emphasis is added)
> |
> | And again, what cfront did was in no way seperate compilation. The templates
> | are not in separately compiled files and the semantics are not at all
> | like export.
>
> Obviously, we have, each one, different notions of the concept of separate
> compilation of templates.
>
> For me, there exists different models of the concept of separate
> compilation of templates, and the semantics mandated by the standard
> is just *one* instance of separate compilation of templates. I've
> described quite another model.

Can you remind me what your description is?



> The impression I gain from your different messages is that, a separate
> compilation of templates must have the export-semantics described in
> ths standard.

I have not seen a message where John said or implied such a thing.

However, "separate compilation of templates" is an English phrase,
which involves:
(a) compilation: (in this context) translation by a compiler; not by
a preprocessor or linker (though such things could
participate by directing or driving the compiler).
(b) templates: we're specifying how templates are compiled; not how
their instantiations are produced (though there is
presumably a connection).
(c) separate: the templates are compiled separately from the client
code.

Cfront on the other hand does not compile templates separately from
client code (John's example amply proves that). In fact, it barely
"compiles" templates at all; I seem to remember it only parses them
after the parameter tokens have been substituted (which is why many
errors aren't caught unless you actually instiate the template).

Note that this is in sharp contradiction with your claim:
> But then, that is where the name lookup machinery plays an important
> role and I think if the notion of dependent name lookup were dropped,
> then the CFront model is pretty much what is specified.

I suspect you are confused by the fact that Cfront relies on a
convention where the definitions are placed in separate source
files (and their inclusion is implicit). However, if you take
a look at the semantics and mechanisms of Cfront, there is no
basis to call it a "proof of concept of separate compilation of
templates" or "pretty much was the standard specifies except
for dependent name lookup".

Daveed

James Kanze

unread,
Jan 21, 2002, 3:21:07 AM1/21/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

|> [...]
|> > As I say, I don't think it's important, and I think we're wasting
|> > time arguing about what exactly constitutes separate compilation.
|> > The questions are: how do I use it, and what are it's semantics?
|> > For the first question, CFront was acceptable, as a proof of
|> > concept, and it was significantly superior to anything that has
|> > followed to date.

|> You have to admit that that is a pretty unusual opinion. Most
|> developers have not exactly been clamoring for the cfront model (on
|> the contrary).

I don't really know what most developers have been clamoring for. What
I know is that the criticism of CFront that I have heard from developers
has always concerned implementation problems, principally build times
and problems with dependancy management. I've heard complaints about
every implementation around, however, and for the Borland model, most of
the complaints did concern the model, or at least, the way it was
perceived. As you reminded me, most compilers *do* allow differing
template instantiation to a final build. Never the less, most people
seem to be unaware of it; I was unaware of it myself until John Spicer
pointed it out to me in private email about a year ago. And the
developers I know DO complain about having to put the implementation in
the header files.

--
James Kanze mailto:ka...@gabi-soft.de

Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

James Kanze

unread,
Jan 21, 2002, 3:24:59 AM1/21/02
to
j...@edg.com (John H. Spicer) writes:

|> Yes, you are right I do have a stringent view of what separate
|> compilation means. It must mean that the templates are defined in a
|> file that is compiled once separately from any user code. I really
|> didn't think the concept of separate compilation was something that
|> required debate.

And I think this is where the difference of opinion lies. It never
occurred to me that "separate" implied "once".

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

Daveed Vandevoorde

unread,
Jan 21, 2002, 3:28:29 AM1/21/02
to
ka...@gabi-soft.de (James Kanze) wrote:

> goo...@vandevoorde.com (Daveed Vandevoorde) wrote:
> > James Kanze <ka...@gabi-soft.de> wrote :
> > > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
[...]

> As I've mentioned earlier, CFront was a very good proof of
> concept, but it made use of a number of ad hoc heuristics, which while
> they worked well in practice, didn't lend themselves very well to
> standardization.
>
> > Later cfront version worked correctly according to their model in
> > many (or all) of the cases where users were cleaning out the
> > repository. The problem was that they didn't not "model the cfront
> > model" in their dependency analysis. That is no surprise because
> > cfront's model is an inclusion model with quasi-implicit includes
> > (they're explicit in the synthesized source but it is a pain to
> > model those in Makefiles and the like).
>
> This is what I meant by the bugs in the implementation. It was, or
> should have been, up to the implementation to manage dependancies in
> the files it generates. CFront tried to, but didn't always succeed.

Suppose Cfront were enhanced to deal with dependencies of its
generated files to your liking. What would its benefits be over
the standard inclusion model (which fits in your standard dependency
tools such as "make" and friends)? I claim there is no material
advantage:

(a) The standard inclusion model results in compiling code like:

#include "mystuff.h"
#include "templ_defs.c"

// whatever

(b) the Cfront model would end up compiling your source:

#include "mystuff.h"
#include "templ_decls.h"

// whatever.c

and then synthesizing and compiling source like:

#include "mystuff.h"
#include "templ_decls.h"
#include "templ_defs.c"
#include "whatever.c"

// a bit of synthesized stuff

The details of the lookup and code-generation process are a bit
different, but I don't think that affects the discussion
materially.

I think there is a bit more work in the Cfront case (depending on
what the headers contain) and you "gain" the fact that you didn't
have to write a #include line in the Cfront case (it's implicitly
added in the synthesized file). However, I don't think the latter
is an advantage.

Note that delaying some of this work to link time is not intrinsic to
the cfront template source model, but a requirement of its instantiation
mechanism working with standard linkers (i.e., it could not afford
the luxury of duplicate template instantiations). Some compilers
(like EDG's) offer modes that implement the standard inclusion model
in the same wait-until-link-time manner. The only advantage that I
see there is that it does indeed avoid duplicate instantiations: the
duplicates could be expensive to produce in theory, but the compilers
that don't delay instantiation until link time (and eliminate
duplicates in their linker) have competitive build-times in practice.

In light of the above comments, I'm asking again: why prefer Cfront
over an implementation of the standard inclusion model?

[...]


> I'm still not overjoyed. From the beginning, what I wanted is that
> templates be treated exactly like any other code: I provide a header
> with the class definition, and one or more source files with the
> implementation. I compile the source files into a library, and I
> deliver the library and the headers. The client code includes the
> headers, and links against the library.

I understand the feeling, and to some extent, the "export" model could
provide this. But in truth, template definitions (of function templates
and dependent static data member definitions) are _not_ "exactly like
any other code". They have that "macro-reminescent" character which
causes any such library technology to have to incorporate a chunk of
compiler-like technology, with all the consequences in terms of
dependency management and diagnostic timeliness/quality.

Maybe the answer lies in so-called "module systems", by which I mean
a source model that imposes a single definition of any kind of entity.
C/C++ allows multiple definitions of various kinds of entities (types
in particular). So you end up with two kinds of packaging bounds that
don't match: library (module) and translation unit. The export model
has to cope with that (e.g.) when it finds a same type in two different
translation units: they should match, but they might not (no diagnostic
required <grin>). If libraries and translation units are defined by
the same bounds (modules), you basically end up with a match between
the compiler and the linker granularity and it becomes easier to float
roles between the two tools (e.g., a "linker" can more naturally
incorporate a substantial code-generation role).

But I digress :-P



> Apparently, no implementor has ever supported this, either because
> they don't want to, or they don't know how to, or both.

I'm quite sure they're aware of the alternatives available to implement
such things. Ultimately, I suspect the market decides.

Daveed

James Kanze

unread,
Jan 21, 2002, 3:29:20 AM1/21/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

|> However, "separate compilation of templates" is an English phrase,
|> which involves:
|> (a) compilation: (in this context) translation by a compiler; not by
|> a preprocessor or linker (though such things could
|> participate by directing or driving the compiler).
|> (b) templates: we're specifying how templates are compiled; not how
|> their instantiations are produced (though there is
|> presumably a connection).
|> (c) separate: the templates are compiled separately from the client
|> code.

|> Cfront on the other hand does not compile templates separately from
|> client code (John's example amply proves that). In fact, it barely
|> "compiles" templates at all; I seem to remember it only parses them
|> after the parameter tokens have been substituted (which is why many
|> errors aren't caught unless you actually instiate the template).

I think it does. At some point, it translates templates -- otherwise,
there could be no executable using them. And when it translates them is
separate from the moment that it translates client code.

What one could object to -- in fact, what many people did object to
indirectly, when they complained about build times -- is that it
actually translates the templates many times, once for each
instantiation. And that, although the translation is separate from that
of the client code per se, it does "retranslate" parts of the client
code sources as well.

|> Note that this is in sharp contradiction with your claim:
|> > But then, that is where the name lookup machinery plays an important
|> > role and I think if the notion of dependent name lookup were dropped,
|> > then the CFront model is pretty much what is specified.

|> I suspect you are confused by the fact that Cfront relies on a
|> convention where the definitions are placed in separate source files
|> (and their inclusion is implicit). However, if you take a look at
|> the semantics and mechanisms of Cfront, there is no basis to call it
|> a "proof of concept of separate compilation of templates" or "pretty
|> much was the standard specifies except for dependent name lookup".

If you remove dependant name lookup from the standard, without replacing
it with something else, you don't have a viable specification for
templates. Whether CFront is a proof of concept of what you have
really depends on what you replace the dependant lookup with -- surely
you'd admit that it is a proof of concept of some unspecified (and
perhaps unspecifiable) name binding rules.

More important than whether CFront was a proof of concept of anything,
however, is a clearer analysis of what the alternatives are. What were
the name binding rules in CFront? How could they have been adapted to a
standard, and whether such an adaptation would be an improvement?

All I can really say is that CFront's name binding heuristic (I won't
use the word rules for it) worked well in practice.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

Nicola Musatti

unread,
Jan 21, 2002, 11:12:27 AM1/21/02
to

Daveed Vandevoorde wrote:
[...]


> Maybe the answer lies in so-called "module systems", by which I mean
> a source model that imposes a single definition of any kind of entity.
> C/C++ allows multiple definitions of various kinds of entities (types
> in particular). So you end up with two kinds of packaging bounds that
> don't match: library (module) and translation unit. The export model
> has to cope with that (e.g.) when it finds a same type in two different
> translation units: they should match, but they might not (no diagnostic
> required <grin>). If libraries and translation units are defined by
> the same bounds (modules), you basically end up with a match between
> the compiler and the linker granularity and it becomes easier to float
> roles between the two tools (e.g., a "linker" can more naturally
> incorporate a substantial code-generation role).
>
> But I digress :-P

I wish this hadn't to be a "digression". Don't you ever get the feeling
that we're stretching a compile/link model which dates from the 70's
well beyond its point of rupture, just so that we don't have to adopt a
model that relies on technology from the 80's?

Cheers,
Nicola Musatti

James Kanze

unread,
Jan 21, 2002, 12:45:13 PM1/21/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

Agreed. I don't doubt it has advantages in this respect. My question
is more along the lines, "is is worth the price", the price being, in
this case, incompatibility with existing implementations, and an
additional complexity to learn (as if name lookup wasn't already
complicated enough). With regards to the first, my impression is that
most programs won't notice. For the same reasons that I suspect that it
is solving an inexistant problem; most users tend to be wary by nature,
and take external steps to avoid name conflicts.

|> > I'm curious because my impression is that the double name lookup
|> > solves a non-existant problem. (But I could be wrong.)

|> If you have a true "separation model" for template instantiation
|> (i.e., a model where the client and the implementation remain in
|> separate translation units and are compiled separately), you need a
|> mechanism to "cross over" that translation unit boundary to handle
|> nontrivial dependent expressions. The two-phase lookup (where the
|> second phase is argument-dependent lookup (ADL))is one way to
|> address the problem.

I understand. I think it is basically that I hadn't really thought too
deeply about the meaning of "separate compilation". I'm not sure it
really merits the name, but I was concerned about the problem of
compiling the client code and the template instantiation separately.
Even in this case, of course, you have the cross over problem; at least
some of the context of the client code must be made available when the
template instantiation is compiled. CFront used a particularly awkward,
but surprisingly effective, heuristic for this. Most (or all?) modern
compilers have no problem, because the instantiation takes place during
compilation of the client code. The alternative is, of course, to
cleanly define what context is necessary, and make it available at a
later date. The definite advantage of the two phase lookup is that it
allows at least a minimum of error checking on the template before
instantiation. How important this is will depend on the development
methodologies; in most of the shops I've worked in, unit tests would be
required on the template before making the implementation available.
Whether the error messages are generated when the template is seen, or
during instantiation, is unimportant.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

---

John H. Spicer

unread,
Jan 21, 2002, 1:18:42 PM1/21/02
to
James Kanze <ka...@gabi-soft.de> wrote in message news:<86vgdwb...@alex.gabi-soft.de>...

> j...@edg.com (John H. Spicer) writes:
>
> |> Yes, you are right I do have a stringent view of what separate
> |> compilation means. It must mean that the templates are defined in a
> |> file that is compiled once separately from any user code. I really
> |> didn't think the concept of separate compilation was something that
> |> required debate.
>
> And I think this is where the difference of opinion lies. It never
> occurred to me that "separate" implied "once".
>

I should clarify that by "once" I meant that the user compiles the code
once. The compiler may so so more than once behind the scenes.

I didn't think "separate compilation" was such a controversial concept.
You compile files separately and link them together to form a complete
program (again, from a user perspective).

John Spicer
Edison Design Group

Daveed Vandevoorde

unread,
Jan 21, 2002, 4:44:59 PM1/21/02
to
James Kanze <ka...@gabi-soft.de> wrote:
> goo...@vandevoorde.com (Daveed Vandevoorde) writes:
[...]
> |> Cfront on the other hand does not compile templates separately from
> |> client code (John's example amply proves that). In fact, it barely
> |> "compiles" templates at all; I seem to remember it only parses them
> |> after the parameter tokens have been substituted (which is why many
> |> errors aren't caught unless you actually instiate the template).
>
> I think it does. At some point, it translates templates -- otherwise,
> there could be no executable using them. And when it translates them is
> separate from the moment that it translates client code.
>
> What one could object to -- in fact, what many people did object to
> indirectly, when they complained about build times -- is that it
> actually translates the templates many times, once for each
> instantiation.

Not really. In Cfront (and many other implementations) templates are
much closer to macros. Instead of compiling the template, it is just
stored away in a tokenized form. When an instantiation is needed, the
parameter tokens are bound to the template arguments and the resulting
instantiation is parsed. The template itself (i.e., the parameterized
definition) is never parsed.

To the best of my knowledge, the first compiler to really compile
templates was Taligent's (now HP's aC++ compiler). I believe newer GNU
compiler versions also compile templates and our own (EDG) can do it
either way. I'm sure other modern compilers do so too.

> And that, although the translation is separate from that
> of the client code per se, it does "retranslate" parts of the client
> code sources as well.
>
> |> Note that this is in sharp contradiction with your claim:
> |> > But then, that is where the name lookup machinery plays an important
> |> > role and I think if the notion of dependent name lookup were dropped,
> |> > then the CFront model is pretty much what is specified.
>
> |> I suspect you are confused by the fact that Cfront relies on a
> |> convention where the definitions are placed in separate source files
> |> (and their inclusion is implicit). However, if you take a look at
> |> the semantics and mechanisms of Cfront, there is no basis to call it
> |> a "proof of concept of separate compilation of templates" or "pretty
> |> much was the standard specifies except for dependent name lookup".
>
> If you remove dependant name lookup from the standard, without replacing
> it with something else, you don't have a viable specification for
> templates.

It is arguably viable for the inclusion model (many compilers worked
exactly that way for a while).

> Whether CFront is a proof of concept of what you have
> really depends on what you replace the dependant lookup with -- surely
> you'd admit that it is a proof of concept of some unspecified (and
> perhaps unspecifiable) name binding rules.

No, it uses the ordinary name binding rules that Cfront uses for any
other code. It's a proof of concept of an implicit inclusion policy.
It's also a good proof of concept of the general principle of templates:
it showed that they could be implemented relatively efficiently with
a relatively simple (macro-inspired) technique.

> More important than whether CFront was a proof of concept of anything,
> however, is a clearer analysis of what the alternatives are. What were
> the name binding rules in CFront?

Pretty much the ordinary lookup of today. (I'm sure there were some small
changes, but I don't think they're material in this context.)

> How could they have been adapted to a
> standard, and whether such an adaptation would be an improvement?
>
> All I can really say is that CFront's name binding heuristic (I won't
> use the word rules for it) worked well in practice.

See above; I don't believe Cfront's template implementation did anything
new with name lookup or name binding (other than the template parameter
concept, of course).

Daveed

Daveed Vandevoorde

unread,
Jan 22, 2002, 12:25:53 PM1/22/02
to
Nicola Musatti <obje...@divalsim.it> wrote:
[...]

> Don't you ever get the feeling
> that we're stretching a compile/link model which dates from the 70's
> well beyond its point of rupture, just so that we don't have to adopt a
> model that relies on technology from the 80's?

Well, sort of. I think the root cause of the "problem" lies more
in the source model of the programming language than in technology.

Compare Modula and C, for example. Both are languages from the 70's.
The former has a module system, the latter doesn't (wrt. types).
I suspect the designers of C knew about technology that enabled Modula
(even though Modula came a little later) but for some reason they chose
to handle public type definitions through the preprocessor (in practice).
(Perhaps because the dominating programming styles of the time introduced
relatively few type definitions. In many of the paradigms supported by
C++, that is no longer the case.)

Daveed

James Kanze

unread,
Jan 22, 2002, 12:28:56 PM1/22/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) wrote in message
news:<52f2f9cd.02012...@posting.google.com>...

> James Kanze <ka...@gabi-soft.de> wrote:
> > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
> [...]
> > |> Cfront on the other hand does not compile templates separately
> > |> from client code (John's example amply proves that). In fact,
> > |> it barely "compiles" templates at all; I seem to remember it
> > |> only parses them after the parameter tokens have been
> > |> substituted (which is why many errors aren't caught unless you
> > |> actually instiate the template).

> > I think it does. At some point, it translates templates --
> > otherwise, there could be no executable using them. And when it
> > translates them is separate from the moment that it translates
> > client code.

> > What one could object to -- in fact, what many people did object
> > to indirectly, when they complained about build times -- is that
> > it actually translates the templates many times, once for each
> > instantiation.

> Not really. In Cfront (and many other implementations) templates
> are much closer to macros.

There are certain similarities. Having used <generic.h>, however, I
can assure you that even in CFront, templates were several orders of
magnitude easier to use than macros.

> Instead of compiling the template, it is just stored away in a
> tokenized form.

I thought it worked directly from the source each time. Or do you
mean within the compiler, when the compiler was invoked for
instantiation.

> When an instantiation is needed, the parameter tokens are bound to
> the template arguments and the resulting instantiation is parsed.
> The template itself (i.e., the parameterized definition) is never
> parsed.

OK. I think I understand what John meant by no separate compile,
too. The fact that the compiler never processed the templates (other
than perhaps just tokenizing) except in an instantiation.

> To the best of my knowledge, the first compiler to really compile
> templates was Taligent's (now HP's aC++ compiler). I believe newer
> GNU compiler versions also compile templates and our own (EDG) can
> do it either way. I'm sure other modern compilers do so too.

Just curious, but does anyone remember what Lucid did? They *were*
the second compiler with templates, I think. Was it like CFront, or
did they require the same include everything policy of Borland?

[...]


> > If you remove dependant name lookup from the standard, without
> > replacing it with something else, you don't have a viable
> > specification for templates.

> It is arguably viable for the inclusion model (many compilers worked
> exactly that way for a while).

Perhaps I'm not using the correct technical term. When a compiler
instantiates a template, it must define an instantiation context in
which the name lookup takes place. For a non template, that it
trivial; each name is looked up where it occurs. But where does the
"name" occur when a template is instantiated? It can't be where the
name textually occurs, in the template definition, because you
couldn't resolve dependant names there. And it can't reasonably just
be at the statement which triggered the instantiation -- this is
likely to be in a function, and you certainly don't want to resolve to
any function local names.

The CFront solution, of course, threw the phases of compilation out
the window to create a perfectly arbitrary artificial context. It
worked well in practice, but I'll be the first to admit that it wasn't
appropriate for standardization.

I don't know how other early compilers did it. I vaguely remember
hearing once something about "just before the outermost enclosing
declaration" -- this was before namespaces, of course.

Dependant name lookup has the particularity that names are looked up
in two different contexts, according to whether they are dependant or
not. If you remove dependant name lookup, you still have the problem:
what is the context.

> > Whether CFront is a proof of concept of what you have really
> > depends on what you replace the dependant lookup with -- surely
> > you'd admit that it is a proof of concept of some unspecified (and
> > perhaps unspecifiable) name binding rules.

> No, it uses the ordinary name binding rules that Cfront uses for any
> other code.

But in a somewhat special context. Dependant name lookup also uses
the same name binding rules as any other code. What makes it
particular is that according to whether the name is dependant or not,
the binding takes place at a different time, and thus in a different
context.

Just curious, again, but could dependant name lookup find a static
function in a file. Say:

t.h:
template< typename T >
T f(T a, T b) { return a + b ; }

c.cc:
#include "t.h"
struct C {} ;
static C operator+( C a, C b ) { return C() ; }

void
g()
{
C x, y ;
C z = f( x, y ) ;
}

> It's a proof of concept of an implicit inclusion policy. It's also
> a good proof of concept of the general principle of templates: it
> showed that they could be implemented relatively efficiently with a
> relatively simple (macro-inspired) technique.

Perhaps most importantly, it showed just how useful they could be, so
that people would be inspired to invest the effort to make them
better.

> > More important than whether CFront was a proof of concept of
> > anything, however, is a clearer analysis of what the alternatives
> > are. What were the name binding rules in CFront?

> Pretty much the ordinary lookup of today. (I'm sure there were some
> small changes, but I don't think they're material in this context.)

Don't forget, when you're talking about templates, name binding must
say something about the context in which it takes place. You can't
just say "just like anything else." CFront uses a synthesized context
which I don't think can be described without reconsidering the
fundamental way compiling is described in the standard.

> > How could they have been adapted to a standard, and whether such
> > an adaptation would be an improvement?

> > All I can really say is that CFront's name binding heuristic (I
> > won't use the word rules for it) worked well in practice.

> See above; I don't believe Cfront's template implementation did
> anything new with name lookup or name binding (other than the
> template parameter concept, of course).

It defined a synthesized context in which the name binding took
place. As I said, the way it synthesized the context was a real
hack. But it worked well in practice, at least for me (and my
customers, none of whom ever complained about this aspect of CFront).

--
James Kanze mailto:ka...@gabi-soft.de

Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

Daveed Vandevoorde

unread,
Jan 23, 2002, 9:00:50 PM1/23/02
to
ka...@gabi-soft.de (James Kanze) wrote:
> goo...@vandevoorde.com (Daveed Vandevoorde) wrote:
> > James Kanze <ka...@gabi-soft.de> wrote:
> > > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
> [...]
[...]

> > Not really. In Cfront (and many other implementations) templates
> > are much closer to macros.
>
> There are certain similarities. Having used <generic.h>, however, I
> can assure you that even in CFront, templates were several orders of
> magnitude easier to use than macros.

You're right of course that the total template experience is much more
than preprocessor expansion. However, the instantiation process itself
is a macro-expansion operation in Cfront (and some other compilers).

> > Instead of compiling the template, it is just stored away in a
> > tokenized form.
>
> I thought it worked directly from the source each time. Or do you
> mean within the compiler, when the compiler was invoked for
> instantiation.

Yes, what you say is what I mean ;-)

> > When an instantiation is needed, the parameter tokens are bound to
> > the template arguments and the resulting instantiation is parsed.
> > The template itself (i.e., the parameterized definition) is never
> > parsed.
>
> OK. I think I understand what John meant by no separate compile,
> too. The fact that the compiler never processed the templates (other
> than perhaps just tokenizing) except in an instantiation.

And then it's not a template anymore.

> > To the best of my knowledge, the first compiler to really compile
> > templates was Taligent's (now HP's aC++ compiler). I believe newer
> > GNU compiler versions also compile templates and our own (EDG) can
> > do it either way. I'm sure other modern compilers do so too.
>
> Just curious, but does anyone remember what Lucid did? They *were*
> the second compiler with templates, I think. Was it like CFront, or
> did they require the same include everything policy of Borland?

I don't. Did they ever do templates at all?

> [...]
> > > If you remove dependant name lookup from the standard, without
> > > replacing it with something else, you don't have a viable
> > > specification for templates.
>
> > It is arguably viable for the inclusion model (many compilers worked
> > exactly that way for a while).
>
> Perhaps I'm not using the correct technical term. When a compiler
> instantiates a template, it must define an instantiation context in
> which the name lookup takes place. For a non template, that it
> trivial; each name is looked up where it occurs. But where does the
> "name" occur when a template is instantiated? It can't be where the
> name textually occurs, in the template definition, because you
> couldn't resolve dependant names there. And it can't reasonably just
> be at the statement which triggered the instantiation -- this is
> likely to be in a function, and you certainly don't want to resolve to
> any function local names.

For class templates you instantiate it at the closest namespace scope
point before the POU (point of use). For functions, you delay the
instantiation (of the definition) until the closest namespace
scope point after the POU (or until the end of the translation unit).
(For the function declarator part you follow the same rules as for the
class template. The standard doesn't really describe that though. ;-)

> The CFront solution, of course, threw the phases of compilation out
> the window to create a perfectly arbitrary artificial context. It
> worked well in practice, but I'll be the first to admit that it wasn't
> appropriate for standardization.
>
> I don't know how other early compilers did it. I vaguely remember
> hearing once something about "just before the outermost enclosing
> declaration" -- this was before namespaces, of course.

Well it's really the standard POI (point of instantiation) (see above).
Cfront essentially does the same thing.



> Dependant name lookup has the particularity that names are looked up
> in two different contexts, according to whether they are dependant or
> not. If you remove dependant name lookup, you still have the problem:
> what is the context.

"Dependent name lookup" isn't the best terminology I think. Pre-export
all names were considered dependent and ordinary lookup was done at the
POI. I don't see the problem you mention.

Post-export we now have 2-phase lookup: names are looked up at the
point of definition, at the POI or both. At the point of definition
ordinary lookup applies; at the POI only ADL is performed for
unqualified function calls.

> > > Whether CFront is a proof of concept of what you have really
> > > depends on what you replace the dependant lookup with -- surely
> > > you'd admit that it is a proof of concept of some unspecified (and
> > > perhaps unspecifiable) name binding rules.
>
> > No, it uses the ordinary name binding rules that Cfront uses for any
> > other code.
>
> But in a somewhat special context. Dependant name lookup also uses
> the same name binding rules as any other code.

Not quite: depedent unqualified function calls are bound using two
different lookups (ordinary vs. argument-dependent) at two different
points.

> What makes it
> particular is that according to whether the name is dependant or not,
> the binding takes place at a different time, and thus in a different
> context.

See above.

> Just curious, again, but could dependant name lookup find a static
> function in a file. Say:
>
> t.h:
> template< typename T >
> T f(T a, T b) { return a + b ; }
>
> c.cc:
> #include "t.h"
> struct C {} ;
> static C operator+( C a, C b ) { return C() ; }
>
> void
> g()
> {
> C x, y ;
> C z = f( x, y ) ;
> }

Not in this case because only functions with external linkage are
valid candidates (14.6.4.2/1).

> > It's a proof of concept of an implicit inclusion policy. It's also
> > a good proof of concept of the general principle of templates: it
> > showed that they could be implemented relatively efficiently with a
> > relatively simple (macro-inspired) technique.
>
> Perhaps most importantly, it showed just how useful they could be, so
> that people would be inspired to invest the effort to make them
> better.

Yep.

> > > More important than whether CFront was a proof of concept of
> > > anything, however, is a clearer analysis of what the alternatives
> > > are. What were the name binding rules in CFront?
>
> > Pretty much the ordinary lookup of today. (I'm sure there were some
> > small changes, but I don't think they're material in this context.)
>
> Don't forget, when you're talking about templates, name binding must
> say something about the context in which it takes place. You can't
> just say "just like anything else." CFront uses a synthesized context
> which I don't think can be described without reconsidering the
> fundamental way compiling is described in the standard.

I guess we just disagree on this. For me, it's just ordinary lookup
in a translation unit created with #includes. The only material
difference from the standard inclusion model is that the #includes
are implicit.

Daveed

James Kanze

unread,
Jan 24, 2002, 10:53:55 AM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) wrote in message
news:<52f2f9cd.02012...@posting.google.com>...
> ka...@gabi-soft.de (James Kanze) wrote:
> > goo...@vandevoorde.com (Daveed Vandevoorde) wrote:
> > > James Kanze <ka...@gabi-soft.de> wrote:
> > > > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
> > [...]
> [...]
> > > Not really. In Cfront (and many other implementations)
> > > templates are much closer to macros.

> > There are certain similarities. Having used <generic.h>, however,
> > I can assure you that even in CFront, templates were several
> > orders of magnitude easier to use than macros.

> You're right of course that the total template experience is much
> more than preprocessor expansion. However, the instantiation process
> itself is a macro-expansion operation in Cfront (and some other
> compilers).

With scoping rules applied to the macro names, etc.

It is a sort of macro-expansion, but certainly more evolved and more
integrated into the language that the preprocessor macros.

[...]


> > Just curious, but does anyone remember what Lucid did? They
> > *were* the second compiler with templates, I think. Was it like
> > CFront, or did they require the same include everything policy of
> > Borland?

> I don't. Did they ever do templates at all?

Apparently. Now that Google has put the old news CD's in there data
base, you can go way back, and I find articles from 1993 comparing
template instantiation times of Lucid and CFront. Which, I'm pretty
sure, makes Lucid the second compiler to implement templates, before
Borland or any of the others.

> > [...]
> > > > If you remove dependant name lookup from the standard, without
> > > > replacing it with something else, you don't have a viable
> > > > specification for templates.

> > > It is arguably viable for the inclusion model (many compilers
> > > worked exactly that way for a while).

> > Perhaps I'm not using the correct technical term. When a compiler
> > instantiates a template, it must define an instantiation context
> > in which the name lookup takes place. For a non template, that it
> > trivial; each name is looked up where it occurs. But where does
> > the "name" occur when a template is instantiated? It can't be
> > where the name textually occurs, in the template definition,
> > because you couldn't resolve dependant names there. And it can't
> > reasonably just be at the statement which triggered the
> > instantiation -- this is likely to be in a function, and you
> > certainly don't want to resolve to any function local names.

> For class templates you instantiate it at the closest namespace
> scope point before the POU (point of use). For functions, you delay
> the instantiation (of the definition) until the closest namespace
> scope point after the POU (or until the end of the translation
> unit). (For the function declarator part you follow the same rules
> as for the class template. The standard doesn't really describe
> that though. ;-)

That's what the standard finally adopted.

> > The CFront solution, of course, threw the phases of compilation
> > out the window to create a perfectly arbitrary artificial context.
> > It worked well in practice, but I'll be the first to admit that it
> > wasn't appropriate for standardization.

> > I don't know how other early compilers did it. I vaguely remember
> > hearing once something about "just before the outermost enclosing
> > declaration" -- this was before namespaces, of course.

> Well it's really the standard POI (point of instantiation) (see
> above). Cfront essentially does the same thing.

Not with regards to the POI. CFront generated a synthetic context
based on the (include) files where the template and its instantiation
arguments where defined. This is very different from what the
standard requires.

> > Dependant name lookup has the particularity that names are looked
> > up in two different contexts, according to whether they are
> > dependant or not. If you remove dependant name lookup, you still
> > have the problem: what is the context.

> "Dependent name lookup" isn't the best terminology I think.
> Pre-export all names were considered dependent and ordinary lookup
> was done at the POI. I don't see the problem you mention.

> Post-export we now have 2-phase lookup: names are looked up at the
> point of definition, at the POI or both. At the point of definition
> ordinary lookup applies; at the POI only ADL is performed for
> unqualified function calls.

I don't think I'm making myself clear. Basically, when a compiler
looks up a name, what it finally binds can be thought of as being
defined by three aspects: what is visible (the context), what name
lookup finds (in what is visible, using various rules of scope, etc.),
and what it binds (chosen from what it finds).

CFront definitely used no special rules for the latter two aspects.
It did, however, create a very special synthetic context to define
what was visible.

With regards to the standard, I could easily be wrong, but from what I
gather, there are also no special rules for the latter two aspects.
What is special is that there are two distinct visibility contexts,
according to whether the name is dependant or not.

> > > > Whether CFront is a proof of concept of what you have really
> > > > depends on what you replace the dependant lookup with --
> > > > surely you'd admit that it is a proof of concept of some
> > > > unspecified (and perhaps unspecifiable) name binding rules.

> > > No, it uses the ordinary name binding rules that Cfront uses for
> > > any other code.

> > But in a somewhat special context. Dependant name lookup also
> > uses the same name binding rules as any other code.

> Not quite: depedent unqualified function calls are bound using two
> different lookups (ordinary vs. argument-dependent) at two different
> points.

I'm not sure I understand here. I thought that if the function call
were deemed dependant, name lookup and binding would occur at the
point of instantiation -- otherwise, at the point of definition, but
that in both cases, name lookup and binding followed the usual rules
that would be applied to a non template function at that point. In
other words, the compiler applies two different rules for visibility,
according to whether the call is dependant or not.

Are you trying to say that the compiler does name lookup in both
contexts? (In my words, what is visible is the union of what is
visible at the point of the call and at the point of instantiation?)
Or that it does both separately, and somehow resolves disagreements in
the results?

> > What makes it particular is that according to whether the name is
> > dependant or not, the binding takes place at a different time, and
> > thus in a different context.

> See above.

> > Just curious, again, but could dependant name lookup find a static
> > function in a file. Say:

> > t.h:
> > template< typename T >
> > T f(T a, T b) { return a + b ; }

> > c.cc:
> > #include "t.h"
> > struct C {} ;
> > static C operator+( C a, C b ) { return C() ; }

> > void
> > g()
> > {
> > C x, y ;
> > C z = f( x, y ) ;
> > }

> Not in this case because only functions with external linkage are
> valid candidates (14.6.4.2/1).

And if the operator+ wasn't static, but had external linkage? If I
understand correctly, this should be dependant name lookup. With the
point of instantiation immediately following the definition of g().
If this is correct, it should find the local operator+.

What if the operator+ were in an anonymous namespace, instead of being
static? Would the name lookup still find it?

And the restriction to functions with external linkage is a difference
from non-template (and non-dependant?) lookup. So they aren't totally
identical (unlike CFront).

I'll reserve final judgement until I've had the opportunity to
actually do some significant coding with a conformant compiler, of
course. But off hand, the CFront model seems a lot easier to explain
and to understand.

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 11:01:35 AM1/24/02
to
James Kanze <ka...@gabi-soft.de> writes:

[...]

| And the
| developers I know DO complain about having to put the implementation in
| the header files.

That also matches my personnal experience.

Apparently there seem to be a divorce between users and suppliers.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 11:03:28 AM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

| Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote:
| > j...@edg.com (John H. Spicer) writes:
| > [...]
| [...]
| > | > The *concept of separate compilation of templates* wasn't the committee's
| > | > invention. CFront already made a proof of the concept.
| > | >
| > | > (Emphasis is added)
| > |
| > | And again, what cfront did was in no way seperate compilation. The templates
| > | are not in separately compiled files and the semantics are not at all
| > | like export.
| >
| > Obviously, we have, each one, different notions of the concept of separate
| > compilation of templates.
| >
| > For me, there exists different models of the concept of separate
| > compilation of templates, and the semantics mandated by the standard
| > is just *one* instance of separate compilation of templates. I've
| > described quite another model.
|
| Can you remind me what your description is?

Deferring name lookup to instantiation time.

| > The impression I gain from your different messages is that, a separate
| > compilation of templates must have the export-semantics described in
| > ths standard.
|
| I have not seen a message where John said or implied such a thing.
|
| However, "separate compilation of templates" is an English phrase,
| which involves:
| (a) compilation: (in this context) translation by a compiler; not by
| a preprocessor or linker (though such things could
| participate by directing or driving the compiler).
| (b) templates: we're specifying how templates are compiled; not how
| their instantiations are produced (though there is
| presumably a connection).
| (c) separate: the templates are compiled separately from the client
| code.

No kidding.

Using the same logics, you should conclude that a "null pointer
constant" in C++ has a pointer-type. Won't you? ;-)

| Cfront on the other hand does not compile templates separately from
| client code (John's example amply proves that). In fact, it barely
| "compiles" templates at all; I seem to remember it only parses them
| after the parameter tokens have been substituted (which is why many
| errors aren't caught unless you actually instiate the template).

Even in the export-model, not all error's are caugth at parsing time,
so why bother at all with what happens at parsing time if we're going
to do some form of parsing at instantiation time along with semantic
analysis?

When discussing the concept of separate compilation of templates, we
should keep in mind what users perceives, not what implementors with
their compilers internals.

| Note that this is in sharp contradiction with your claim:
| > But then, that is where the name lookup machinery plays an important
| > role and I think if the notion of dependent name lookup were dropped,
| > then the CFront model is pretty much what is specified.

If the notion of depenent-name is dropped, the name-lookup will happen
at instantiation-time i.e. when the compiler effectively does parsing
and semantic analysis. I don't see where the contradiction lies.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 11:03:44 AM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

| James Kanze <ka...@gabi-soft.de> wrote:
| > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
| [...]
| > |> Cfront on the other hand does not compile templates separately from
| > |> client code (John's example amply proves that). In fact, it barely
| > |> "compiles" templates at all; I seem to remember it only parses them
| > |> after the parameter tokens have been substituted (which is why many
| > |> errors aren't caught unless you actually instiate the template).
| >
| > I think it does. At some point, it translates templates -- otherwise,
| > there could be no executable using them. And when it translates them is
| > separate from the moment that it translates client code.
| >
| > What one could object to -- in fact, what many people did object to
| > indirectly, when they complained about build times -- is that it
| > actually translates the templates many times, once for each
| > instantiation.
|
| Not really. In Cfront (and many other implementations) templates are
| much closer to macros. Instead of compiling the template, it is just
| stored away in a tokenized form. When an instantiation is needed, the
| parameter tokens are bound to the template arguments and the resulting
| instantiation is parsed.

The export-model by itself does not suppress that machinery for a code
like this:

// t.H
export template<typename T>
struct X {
void f();
};

// t.C
template<typename T>
void X<T>::f()
{
typename T::A a;
g(a);
a.h();
}

[...]

| > More important than whether CFront was a proof of concept of anything,
| > however, is a clearer analysis of what the alternatives are. What were
| > the name binding rules in CFront?
|
| Pretty much the ordinary lookup of today. (I'm sure there were some small
| changes, but I don't think they're material in this context.)

Dependent-name lookup changes semantics.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Pete Becker

unread,
Jan 24, 2002, 12:02:03 PM1/24/02
to
Gabriel Dos_Reis wrote:
>
> James Kanze <ka...@gabi-soft.de> writes:
>
> [...]
>
> | And the
> | developers I know DO complain about having to put the implementation in
> | the header files.
>
> That also matches my personnal experience.
>
> Apparently there seem to be a divorce between users and suppliers.
>

Not at all. There's a divorce between requirements and implementability.
Every compiler vendor that I know of is trying to impelement export
templates, but it's not easy to do.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:43:57 PM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

| Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote:
| > ka...@gabi-soft.de (James Kanze) writes:
| >
| > [...]
| >
| > | Which leads me back to the original point.
| >
| > Note, however, that if you defer name lookup until instantiation time,
| > then you suppress the dependent-name lookup problem -- that doesn't
| > mean you solve all problems though :-)
|
| Can you elaborate on how that solves the problem?

James's original "problem" (cf its posting I was replying to) was
about the implications of depend-names and two-phase name-lookup which
introduce semantics changes with respect to pre-standard templates.

If you defer name lookup to instantation time then, that problem is
removed.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:49:11 PM1/24/02
to
j...@edg.com (John H. Spicer) writes:

| In article <xajita2...@perceval.inria.fr> Gabriel Dos_Reis <gdos...@sophia.inria.fr> writes:
| >j...@edg.com (John H. Spicer) writes:
| >
| >| >

| >| > Yes, I do know that current rules require two-phase name lookup, but
| >| > then I don't think that two-phase name lookup is a sine qua non
| >| > condition for the "concept of separate compilation of templates".
| >| > Other rules are quite possible and one-phase lookup, that is,
| >| > deferring name lookup until instantiation time, is quite another model
| >| > ans is close to what CFront did. I don't think it is fair or accurate
| >| > to say that just because CFront didn't two-phase name-lookup means it
| >| > didn't a made a proof of the concept of separate compilation of
| >| > templates.
| >|
| >| I didn't say that. I said that some kind of two-phase lookup is required
| >| for export.
| >
| >Precisely *why* you think two-phase name lookup would be required in a
| >separate compilation of templates is the key-question you might want
| >to answer before we can dig up this issue further.
| >
|
| This is quite simple. When you are compiling the file that contains
| the template definitions you must be able to do name lookup and semantic
| analysis.

This is precily why we disagree: *why* must I be able to do name lookup?
That is, from the outset, I disagree with your sentiment that template
compilation as defined by the C++ standard is the only possibvle model
of separate compilation of template. There are other models of
template compilation.

| If you are not doing these things then you are not really
| compiling the file.

Oh well, even in the export-model not all names are looked-up and not
all semantics restrictions are checked, to the point that you're
not doing any of those things, if we were to adopt a very narrow view
of what compilation should mean.

| If you consider processing that does neither lookup
| or semantic analysis to be compilation then the "cat" and "cp" commands
| would also have to be considered compilation.

Yes, *theorically* they would be considered compilation. So what?

| But when compiling template definitions, you can't lookup all of the names
| because some of them are dependent and must be looked up at instantiation time.

Which according to your view of compilation, means thatexport-model
isn't implementing compilation of templates. I'd take that as a
pedantic joke ;-)

| As a result, you have some names that *must* be looked up at compile time
| and some names that *must* be looked up at instantiation time, this
| is why I say some kind of two-phase lookup is required. Note that I did
| not say that the precise definition of two-phase lookup in the standard
| is required.

I noted that. But as said earlier, I do not agree that a two-phase
name lookup is *necessary* in every model of compilation of templates.

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:49:16 PM1/24/02
to
Pete Becker <peteb...@acm.org> writes:

| Gabriel Dos_Reis wrote:
| >
| > Pete Becker <peteb...@acm.org> writes:
| >
| > [...]
| >
| > | The main difference, however, is that cfront did not do what the C++
| > | standard requires.
| >
| > That, nobody disagrees with.
| >
| > | Arguing that cfront is a proof of concept is,
| > | therefore, wrong.
| >
| > Only if you assume that what the standard currently requires is the
| > sole and only possible model of the concept of separate compilation of
| > templates.
| >
|
| Or if you assume that the context of a discussion determines what its
| terms mean.

Certainly, I do not assume that since the context is indicating
"concept of separate compilation of templates". There can be several
models for a given concept.

| Of course, if you're willing to ignore context it's very
| hard to have a meaningful discussion.

Did you miss "concept" in the context?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:49:24 PM1/24/02
to
j...@edg.com (John H. Spicer) writes:

| In article <xajd70a...@perceval.inria.fr> Gabriel Dos_Reis <gdos...@sophia.inria.fr> writes:
| >Pete Becker <peteb...@acm.org> writes:
| >
| >[...]
| >
| >| The main difference, however, is that cfront did not do what the C++
| >| standard requires.
| >
| >That, nobody disagrees with.
| >
| >| Arguing that cfront is a proof of concept is,
| >| therefore, wrong.
| >
| >Only if you assume that what the standard currently requires is the
| >sole and only possible model of the concept of separate compilation of
| >templates.
| >
|

| This is simply false.

Certainly, not.

| In order for something to be a proof of concept
| of separate compilation, it must in some form permit the template definitions
| to be separately compiled.

The issue wasn't "concept of separate compilation", but "concept of
separate compilation of templates". That makes a big difference.

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:49:42 PM1/24/02
to
j...@edg.com (John H. Spicer) writes:

| In article <xajg056...@perceval.inria.fr> Gabriel Dos_Reis <gdos...@sophia.inria.fr> writes:
| >j...@edg.com (John H. Spicer) writes:
| >

| >[...]
| >
| >| It is not a proof of concept because it in no way did anything that
| >| resembles separate compilation.
| >
| >That simply means you have a very stringent view of what separate
| >compilation of template should means. However, if you accept that
| >there can exist other models of separate compilation of templates,
| >then you'll that the export-model isn't just the only one possible
| >model.

| >
|
| Yes, you are right I do have a stringent view of what separate compilation
| means. It must mean that the templates are defined in a file that is

| compiled once separately from any user code. I really didn't think the


| concept of separate compilation was something that required debate.

The issue under debate isn't the "concept of separate compilation" but
"concept of separate compilation of templates". Like it or not but,
it is a debatable notion. Especially when there are different views of
what can constitutes a model of separate compilation of templates.

[...]

| You still haven't responded to my earlier question about why you consider
| the cfront implementation to actually be an example of separate compilation.

Oh, I didn't forget it. But, as said earlier in another message, we
first have to agree on the meaning of "concept of separate compilation
of templates"; and for the moment we're failing on that issue. I
can't see how we could have further productive discussions on what
did CFront if we can't, from the outset, agree on what is a "concept


of separate compilation of templates".

--

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:50:06 PM1/24/02
to
Nicola Musatti <obje...@divalsim.it> writes:

[...]

| Probably because from a user's point of view x.c and t.c appear as
| separate translation units and t.c is successfully compiled without
| including function template definitions.

For many users -- and judging from questions regularly raised --
separately compiling templates means, given t.H and t.C, the user
invokes

<favorite-compiler> <favorite-switches> t.C

and the compiler takes appropriate action to convert the translation
unit obtained from t.C into some file (in any format it likes) which
can later be linked against other translated translation units to
produce a final excutable.

For me, a model of separate compilation of templates that exposes
compiler internals into user codes, through pedantic notions like
"typename" or two-phase name lookup, isn't scalable and puts
unnecessary burden on users. It violates abstraction barriers.

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:50:32 PM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

[...]

| > I'm still not overjoyed. From the beginning, what I wanted is that


| > templates be treated exactly like any other code: I provide a header
| > with the class definition, and one or more source files with the
| > implementation. I compile the source files into a library, and I
| > deliver the library and the headers. The client code includes the
| > headers, and links against the library.
|
| I understand the feeling, and to some extent, the "export" model could
| provide this.

Then, why did we end up with the inclusion model?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:50:56 PM1/24/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) writes:

| Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote in message news:<xaj1ygq...@perceval.inria.fr>...
| > goo...@vandevoorde.com (Daveed Vandevoorde) writes:
| >
| > | That is my point though: in the nondependent case, it "well-known"
| > | (though g might not be in scope with ADL). However, in the dependent
| > | case it is _not_ known (in general); it might not be a "g" from the
| > | translation unit in which the definition appears.
| >
| > But the issue has to be [dealt] with in the inclusion-model.
|
| I'm not entirely sure what your comment is aiming at (in general,
| it would help if you were supporting your statements with a bit
| of your line of thinking).
|
| In the standard inclusion model the "g" will be from the same
| translation unit; in the standard separation model it might not.

But when the program is composed of several translation units, in the
inclusion model we may have different "g"s, each being captured by its
translation unit. In the export-model we'll have just as many
provenances.

| Having worked with both models, I can assure you that the
| latter adds a whole new level of pain to tracking problems in
| even relatively small projects.

I don't doubt that the export-model poses is own set of problems.
But, I'm totally unconvinced that the example you gave was a
representative and uniquely "featured" by the export-model.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:51:13 PM1/24/02
to
James Kanze <ka...@gabi-soft.de> writes:

[...]

| What one could object to -- in fact, what many people did object to


| indirectly, when they complained about build times -- is that it
| actually translates the templates many times, once for each
| instantiation. And that, although the translation is separate from that
| of the client code per se, it does "retranslate" parts of the client
| code sources as well.

I don't see why the export-model suppresses reparsing for each
instantiation.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Gabriel Dos_Reis

unread,
Jan 24, 2002, 12:52:52 PM1/24/02
to
ka...@gabi-soft.de (James Kanze) writes:

[...]

| Dependant name lookup has the particularity that names are looked up


| in two different contexts, according to whether they are dependant or
| not. If you remove dependant name lookup, you still have the problem:
| what is the context.

In one of my earlier postings, I said you could first look the name up
in the "template-definition translation unit" then, in the
translation units requesting the instantiation.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

---

Daveed Vandevoorde

unread,
Jan 24, 2002, 3:51:25 PM1/24/02
to
ka...@gabi-soft.de (James Kanze) wrote:
> goo...@vandevoorde.com (Daveed Vandevoorde) wrote:
> > ka...@gabi-soft.de (James Kanze) wrote:
[...]
> > > Just curious, but does anyone remember what Lucid did? They
> > > *were* the second compiler with templates, I think. Was it like
> > > CFront, or did they require the same include everything policy of
> > > Borland?
>
> > I don't. Did they ever do templates at all?
>
> Apparently. Now that Google has put the old news CD's in there data
> base, you can go way back, and I find articles from 1993 comparing
> template instantiation times of Lucid and CFront. Which, I'm pretty
> sure, makes Lucid the second compiler to implement templates, before
> Borland or any of the others.

It's entirely possible. Borland had templates in version 3.1 which
also dates back to 1993 or earlier, I think. (I used 4.0 to develop
expression templates in 1994 and STL was also developed on 4.0.)

[...]


> > For class templates you instantiate it at the closest namespace
> > scope point before the POU (point of use). For functions, you delay
> > the instantiation (of the definition) until the closest namespace
> > scope point after the POU (or until the end of the translation
> > unit). (For the function declarator part you follow the same rules
> > as for the class template. The standard doesn't really describe
> > that though. ;-)
>
> That's what the standard finally adopted.

Yes, and I think it just adopted common practice.

> > > The CFront solution, of course, threw the phases of compilation
> > > out the window to create a perfectly arbitrary artificial context.
> > > It worked well in practice, but I'll be the first to admit that it
> > > wasn't appropriate for standardization.
>
> > > I don't know how other early compilers did it. I vaguely remember
> > > hearing once something about "just before the outermost enclosing
> > > declaration" -- this was before namespaces, of course.
>
> > Well it's really the standard POI (point of instantiation) (see
> > above). Cfront essentially does the same thing.
>
> Not with regards to the POI. CFront generated a synthetic context
> based on the (include) files where the template and its instantiation
> arguments where defined. This is very different from what the
> standard requires.

It's not terribly different from the standard inclusion model.
I believe the only essential difference is that the inclusion of the
template definitions (the ".C" files) is implicit in Cfront. We could
call that "generating a synthetic context", but why obfuscating what the
mechanism really is?

After the implicit inclusions are done, however, the POI processing
is the same (modulo perhaps some minor corners) as the standard
inclusion model rules.

[...]


> I don't think I'm making myself clear. Basically, when a compiler
> looks up a name, what it finally binds can be thought of as being
> defined by three aspects: what is visible (the context), what name
> lookup finds (in what is visible, using various rules of scope, etc.),
> and what it binds (chosen from what it finds).
>
> CFront definitely used no special rules for the latter two aspects.
> It did, however, create a very special synthetic context to define
> what was visible.

(See above.) That "special context" is essentially what you obtain in
the standard inclusion model by making explicit the implicit inclusion
rules of Cfront. That is exactly why various compilers (HP's, ours
and maybe Sun's) get away with doing exactly that in their Cfront
compatibility mode.

> With regards to the standard, I could easily be wrong, but from what I
> gather, there are also no special rules for the latter two aspects.

There are because of 2-phase lookup (see below).

> What is special is that there are two distinct visibility contexts,
> according to whether the name is dependant or not.

It is true that there are two potential points of lookup which is what
you're saying, I think). One or both of those points may be used,
depending on the name being looked up and the lookups at those two
points may be different kinds of lookups (ordinary vs. ADL).

[...]


> > > But in a somewhat special context. Dependant name lookup also
> > > uses the same name binding rules as any other code.
>
> > Not quite: depedent unqualified function calls are bound using two
> > different lookups (ordinary vs. argument-dependent) at two different
> > points.
>
> I'm not sure I understand here. I thought that if the function call
> were deemed dependant, name lookup and binding would occur at the
> point of instantiation -- otherwise, at the point of definition, but
> that in both cases, name lookup and binding followed the usual rules
> that would be applied to a non template function at that point.

I'm afraid not.

> In
> other words, the compiler applies two different rules for visibility,
> according to whether the call is dependant or not.
>
> Are you trying to say that the compiler does name lookup in both
> contexts? (In my words, what is visible is the union of what is
> visible at the point of the call and at the point of instantiation?)
> Or that it does both separately, and somehow resolves disagreements in
> the results?

In the case of unqualified dependent calls, that is right.
Here is an "interesting" example:

template<typename T>
void f(T a) {
g(a); // Dependent. Ordinary lookup here is empty set
}

void g(int) {}

int main() {
f(3);
}
// Point of instantiation of f<int> is here.
// Causes ADL of g on int-type argument, but builtin types don't have
// associated namespaces: lookup is also empty set.

This example program is an error with the standard (2-phase) lookup
rules. The lookup of g in g(a) is spread across two points and
neither lookup sees g(int).

[...]


> > > t.h:
> > > template< typename T >
> > > T f(T a, T b) { return a + b ; }
>
> > > c.cc:
> > > #include "t.h"
> > > struct C {} ;
> > > static C operator+( C a, C b ) { return C() ; }
>
> > > void
> > > g()
> > > {
> > > C x, y ;
> > > C z = f( x, y ) ;
> > > }
>
> > Not in this case because only functions with external linkage are
> > valid candidates (14.6.4.2/1).
>
> And if the operator+ wasn't static, but had external linkage? If I
> understand correctly, this should be dependant name lookup.

As I mentioned earlier, "dependent name lookup" may be confusing
terminology here. Operator+ is looked up twice. Once at the definition
of the template (t.h) and then using ADL at the point of instantiation.
It finds ::operator+(C, C) because the global namespace is associated
with C and so things are OK (when that operator has external linkage).

> With the
> point of instantiation immediately following the definition of g().
> If this is correct, it should find the local operator+.

But through ADL only; ordinary lookup is not applied at that point.

> What if the operator+ were in an anonymous namespace, instead of being
> static? Would the name lookup still find it?

Only if that namespace was associated with the argument types,
or if it was in scope that the point of definition.

> And the restriction to functions with external linkage is a difference
> from non-template (and non-dependant?) lookup. So they aren't totally
> identical (unlike CFront).

I think it only applies to unqualified function names in function calls.

> I'll reserve final judgement until I've had the opportunity to
> actually do some significant coding with a conformant compiler, of
> course. But off hand, the CFront model seems a lot easier to explain
> and to understand.

I agree there.

To get back to the original points that started this: I claim the
Cfront model is an inclusion model (not too remote from the standard
inclusion model), and hence not a separation model at all.

Also, it is practical to define an inclusion model without 2-phase
lookup (most compilers still implement only that, afaik), but a
separation model will need some sort of 2-phase lookup so it can
pick up declaration from the different translation units that
participate in an instantiation.

Daveed

Daveed Vandevoorde

unread,
Jan 25, 2002, 5:26:35 PM1/25/02
to
Gabriel Dos_Reis <gdos...@sophia.inria.fr> wrote in message news:<xaj665r...@perceval.inria.fr>...

> James Kanze <ka...@gabi-soft.de> writes:
>
> [...]
>
> | What one could object to -- in fact, what many people did object to
> | indirectly, when they complained about build times -- is that it
> | actually translates the templates many times, once for each
> | instantiation. And that, although the translation is separate from that
> | of the client code per se, it does "retranslate" parts of the client
> | code sources as well.
>
> I don't see why the export-model suppresses reparsing for each
> instantiation.

If by "suppresses" you mean "prohibits", it doesn't. However, it
does in practice mandate that you parse the template _prior_ to
processing its instantiation because of the 2-phase name lookup
rules. (See another posting of today in reply to you.)

If an implementation wishes to reparse an instantiated token
sequence afterwards, that's fine. Alternatively, it can instantiate
from the results of the generic parse.

Daveed

James Kanze

unread,
Jan 29, 2002, 11:23:48 AM1/29/02
to
goo...@vandevoorde.com (Daveed Vandevoorde) wrote in message
news:<52f2f9cd.02012...@posting.google.com>...
> ka...@gabi-soft.de (James Kanze) wrote:

> > > > The CFront solution, of course, threw the phases of
> > > > compilation out the window to create a perfectly arbitrary
> > > > artificial context. It worked well in practice, but I'll be
> > > > the first to admit that it wasn't appropriate for
> > > > standardization.

> > > > I don't know how other early compilers did it. I vaguely
> > > > remember hearing once something about "just before the
> > > > outermost enclosing declaration" -- this was before
> > > > namespaces, of course.

> > > Well it's really the standard POI (point of instantiation) (see
> > > above). Cfront essentially does the same thing.

> > Not with regards to the POI. CFront generated a synthetic context
> > based on the (include) files where the template and its
> > instantiation arguments where defined. This is very different
> > from what the standard requires.

> It's not terribly different from the standard inclusion model. I
> believe the only essential difference is that the inclusion of the
> template definitions (the ".C" files) is implicit in Cfront. We
> could call that "generating a synthetic context", but why
> obfuscating what the mechanism really is?

If I remember correctly, if I define a template Container in
Container.h/Container.c, and a MyClass class in MyClass.h, the
instantiation context would be generated by including Container.h and
MyClass.h; anything else included in my source file which triggered
the instantiation would be ignored. The exact context defined by
these two includes is what I mean by a synthesized context; it may
actually occur no where else in my program.

> After the implicit inclusions are done, however, the POI processing
> is the same (modulo perhaps some minor corners) as the standard
> inclusion model rules.

Once the context is generated, no special rules are applied.

> [...]
> > I don't think I'm making myself clear. Basically, when a compiler
> > looks up a name, what it finally binds can be thought of as being
> > defined by three aspects: what is visible (the context), what name
> > lookup finds (in what is visible, using various rules of scope, etc.),
> > and what it binds (chosen from what it finds).

> > CFront definitely used no special rules for the latter two
> > aspects. It did, however, create a very special synthetic context
> > to define what was visible.

> (See above.) That "special context" is essentially what you obtain
> in the standard inclusion model by making explicit the implicit
> inclusion rules of Cfront. That is exactly why various compilers
> (HP's, ours and maybe Sun's) get away with doing exactly that in
> their Cfront compatibility mode.

Unless my memory is failing me, the special context is as described
above, depends on which include files define what, and does not
include anything from the source file which triggers the
instantiation.

[...]


> > I'm not sure I understand here. I thought that if the function
> > call were deemed dependant, name lookup and binding would occur at
> > the point of instantiation -- otherwise, at the point of
> > definition, but that in both cases, name lookup and binding
> > followed the usual rules that would be applied to a non template
> > function at that point.

> I'm afraid not.

Yes. It looks even more complicated than I feared.

> > In other words, the compiler applies two different rules for
> > visibility, according to whether the call is dependant or not.

> > Are you trying to say that the compiler does name lookup in both
> > contexts? (In my words, what is visible is the union of what is
> > visible at the point of the call and at the point of
> > instantiation?) Or that it does both separately, and somehow
> > resolves disagreements in the results?

> In the case of unqualified dependent calls, that is right. Here is
> an "interesting" example:

> template<typename T>
> void f(T a) {
> g(a); // Dependent. Ordinary lookup here is empty set
> }

> void g(int) {}

> int main() {
> f(3);
> }
> // Point of instantiation of f<int> is here.
> // Causes ADL of g on int-type argument, but builtin types don't have
> // associated namespaces: lookup is also empty set.

> This example program is an error with the standard (2-phase) lookup
> rules. The lookup of g in g(a) is spread across two points and
> neither lookup sees g(int).

Which I suspect will break a certain amount of existing code.

I'm just glad I don't have to teach this stuff. Using it to write
robust code is difficult enough.

[...]


> I think it only applies to unqualified function names in function
> calls.

> > I'll reserve final judgement until I've had the opportunity to
> > actually do some significant coding with a conformant compiler, of
> > course. But off hand, the CFront model seems a lot easier to
> > explain and to understand.

> I agree there.

> To get back to the original points that started this: I claim the
> Cfront model is an inclusion model (not too remote from the standard
> inclusion model), and hence not a separation model at all.

Well, I'm not interested in arguing about what it is called. I
generally thought of CFront as "separate compilation" because the
template instantiation was compiled separately (and in a different
context) from the code which triggered the instantiation. But I
understand the signification that you and John give it: that the
template code is compiled separately from any instantiation (which is
not the case for CFront).

--
James Kanze mailto:ka...@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientée objet
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany, Tél.: +49 (0)69 19 86 27

---

It is loading more messages.
0 new messages