|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Let's take a better example: Every time I want to use std::vector,
> > I have to #include <vector> in the source file where I want to do so.
> > Is there any advantage to this?
> For C++ and templates, yes. Altho (and I know you'll go apeshit over this
> comment) C# manages not to need the source code for generics like that.
It's not so much a question of making it work as much as a question of
optimization.
For example, if you create your own class or struct which has a few
member variables, and then you instantiate a vector of that type, it will
be quite space-optimal: Every element in the vector will only consume as
much memory as the size of the object. There is no ancillary data needed.
Of course the second efficiency advantage is that the compiler will be
able to inline code and to perform type-specific optimizations (for example,
sorting a vector of ints will be very efficient because the compiler will
be able to inline the element comparisons directly into the sorting routine
as a machine code register comparison opcode).
This still doesn't make it technically impossible to compile templates
into precompiled libraries. In fact, the current C++ standard defines such
a possibility (the so-called "export templates"). The only major problem
with export templates is that it's technically extremely difficult and
laborious to implement in compilers, which is why there's only one major
C++ compiler that supports it (and it's because of this that, faced with
the harsh realities of the marketplace, the standardization committee is
going to drop the feature from the next standard).
The problem is that templates need to be instantiated in the context
where they are used. Or in the case of export templates, the context needs
to be "brought" where the export template is being instantiated. This is
an extremely complicated thing to do.
For example, you could have this in one source file:
//--------------------------------------------------------
namespace
{
// 'Point' is a type local to this compilation unit
struct Point { int x, y; }
std::vector<Point> points;
}
//--------------------------------------------------------
And then you could have this in another source file:
//--------------------------------------------------------
namespace
{
// 'Point' is a type local to this compilation unit
struct Point { double x, y; }
std::vector<Point> points;
}
//--------------------------------------------------------
With regular templates this isn't any problem at all, and it's trivial
for compilers to handle. With export templates the problem is enormously
harder. (Basically, the 'vector' template class, if it was an export
template, would be instantiated at the linking stage in its own compilation
unit, with its own context, but it needs to also know the context in which
it was used, as above. The compiler needs to somehow carry all the context
information to the template instantiation process at the linking stage.)
And as far as I understand, the above example is just one of the *minor*
complexities in this whole thing.
On the other hand, it's not technically impossible, and it has been done,
so in principle it would be possible to have precompiled template libraries.
(They would only be slightly less efficient because functions which are not
implemented in the header file would not be inlined. OTOH this isn't different
from regular functions.)
As far as I understand "generics" do not handle things "inline" and
"by value", but instead simply handle references, and basically the only
thing they do is that they allow you to skip doing explicit upcasting.
Generics do not allow things like template metaprogramming, template
specialization, and such. (Well, this at least with Java generics. I have
no idea about C#. Also, at least in Java, you can't handle primitive types
with generics.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |