July 05, 2002
That could also suck alot of the ease-of-use out of them.  Would mean writing every declaration of a generic type in at least two places.  Ok, most of the time in C++ we do this anyway using a typedef, but when splicing together expressions etc it's convenient to not have to manually instantiate them.

Sean

"Walter" <walter@digitalmars.com> wrote in message news:afvs5u$2lce$1@digitaldaemon.com...
>
> "Burton Radons" <loth@users.sourceforge.net> wrote in message news:3D1AD1CD.3080308@users.sourceforge.net...
> > I _think_ the ambiguities that C++ was fighting against are nullified by D, which would be very good, as <> is not.
>
> That's some of the problem with C++ templates. The rest of the
complexities
> come about because of implicit instantiation. If, instead, things are explicitly instantiated, most of the complexity goes away. None of the
rules
> about partial ordering, etc., would be necessary.



July 05, 2002
"Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:ag40dh$mc2$1@digitaldaemon.com...
> That could also suck alot of the ease-of-use out of them.  Would mean writing every declaration of a generic type in at least two places.  Ok, most of the time in C++ we do this anyway using a typedef, but when
splicing
> together expressions etc it's convenient to not have to manually
instantiate
> them.

I know it's convenient when it works, but I don't believe it's worth it. When there are a bunch of partially specialized templates spread all over the header files, don't you find yourself wondering sometimes which is getting picked, and then trying to figure out an easy way to verify it? If your code is working, there's no problem, but if it isn't or it needs enhancement, I just don't think the obfuscation is saving any programming effort.

What I see for D is what you say, basically enshrining the typedef approach as the way to instantiate a template.


July 05, 2002
That will work.  And it'll be simple and elegant.

It just might be a teeny bit inconvenient as it will prevent expression-style programming without having to put typedefs beforehand.

in STL C++:

    #include <list>
    #include <algorithm>

    list<int> intlist;
    sort(intlist.begin(), intlist.end(), less<int>());

in D:  something like

    import list;
    import algorithm;

    typedef list{int} list_of_int;
    list_of_int intlist;

    typedef less{int} less_for_int;
    typedef sort{int, list_of_int.iterator_type, less_for_int} sort_routine;
    sort_routine(intlist.begin(), intlist.end(), less_for_int());

As you can see, it's not nearly as elegant when you have to typedef everything.  This is just one teensy example;  I've seen really cool stuff done this way:  Check out http://spirit.sourceforge.net for a cool example of the power of C++ templates when combined with operator overloading.

Maybe you could make it work so that if you fully spell out the type it can be instantiated in an expression.  I suppose this can be added later without much problem, so if it turns out to be impractical it can be fixed later. Something like:

    import list;
    import algorithm;

    list{int} intlist;
    sort{int, list{int}.iterator_type, less{int}}(intlist.begin(),
intlist.end());

But in reality I'd rather the standard templated containers be safer than STL iterator-based containers, perhaps something that functions more like a dynamic array?  It'll be tough to make a linked list behave like a dynamic array though.  The algorithmic performance characteristics and the preferred usage patterns are completely different.

Perhaps the dynamic array reallocation problem can be solved by making a dynamic array actually a container of pointers to subranges of the array. So if it needs expanded and the memory can't be resized in place, it just allocates a new block and doesn't copy the old one.  That would make dynamic array access have to go through one more level of indirection and you couldn't typecast it to a pointer to a flat array anymore (maybe a function to "flatten" a dynamic array would be good) but it would solve most of the "for (ever) myarray ~= asingleentry;" problem.

Sean

"Walter" <walter@digitalmars.com> wrote in message news:ag4kct$1bdq$3@digitaldaemon.com...
>
> "Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:ag40dh$mc2$1@digitaldaemon.com...
> > That could also suck alot of the ease-of-use out of them.  Would mean writing every declaration of a generic type in at least two places.  Ok, most of the time in C++ we do this anyway using a typedef, but when
> splicing
> > together expressions etc it's convenient to not have to manually
> instantiate
> > them.
>
> I know it's convenient when it works, but I don't believe it's worth it. When there are a bunch of partially specialized templates spread all over the header files, don't you find yourself wondering sometimes which is getting picked, and then trying to figure out an easy way to verify it? If your code is working, there's no problem, but if it isn't or it needs enhancement, I just don't think the obfuscation is saving any programming effort.
>
> What I see for D is what you say, basically enshrining the typedef
approach
> as the way to instantiate a template.



July 06, 2002
Yes I know it'll be more typing. Perhaps I can find a way to reduce that without doing the implicit instantiation two-step. There's another maddening example of the implict instantiation resulting in bizarre rules - the way dependent and non-dependent names are looked up. The non-dependent names are looked up in an earlier version of the global symbol table than the dependent names are. Perhaps this makes sense to someone, but to me it's just a way to torture compiler writers <g>.

"Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:ag4q05$1grg$1@digitaldaemon.com...
> That will work.  And it'll be simple and elegant.
>
> It just might be a teeny bit inconvenient as it will prevent expression-style programming without having to put typedefs beforehand.
>
> in STL C++:
>
>     #include <list>
>     #include <algorithm>
>
>     list<int> intlist;
>     sort(intlist.begin(), intlist.end(), less<int>());
>
> in D:  something like
>
>     import list;
>     import algorithm;
>
>     typedef list{int} list_of_int;
>     list_of_int intlist;
>
>     typedef less{int} less_for_int;
>     typedef sort{int, list_of_int.iterator_type, less_for_int}
sort_routine;
>     sort_routine(intlist.begin(), intlist.end(), less_for_int());
>
> As you can see, it's not nearly as elegant when you have to typedef everything.  This is just one teensy example;  I've seen really cool stuff done this way:  Check out http://spirit.sourceforge.net for a cool example of the power of C++ templates when combined with operator overloading.
>
> Maybe you could make it work so that if you fully spell out the type it
can
> be instantiated in an expression.  I suppose this can be added later
without
> much problem, so if it turns out to be impractical it can be fixed later. Something like:
>
>     import list;
>     import algorithm;
>
>     list{int} intlist;
>     sort{int, list{int}.iterator_type, less{int}}(intlist.begin(),
> intlist.end());
>
> But in reality I'd rather the standard templated containers be safer than STL iterator-based containers, perhaps something that functions more like
a
> dynamic array?  It'll be tough to make a linked list behave like a dynamic array though.  The algorithmic performance characteristics and the
preferred
> usage patterns are completely different.
>
> Perhaps the dynamic array reallocation problem can be solved by making a dynamic array actually a container of pointers to subranges of the array. So if it needs expanded and the memory can't be resized in place, it just allocates a new block and doesn't copy the old one.  That would make
dynamic
> array access have to go through one more level of indirection and you couldn't typecast it to a pointer to a flat array anymore (maybe a
function
> to "flatten" a dynamic array would be good) but it would solve most of the
> "for (ever) myarray ~= asingleentry;" problem.



July 06, 2002
"Walter" <walter@digitalmars.com> wrote in message news:ag5bvm$227j$1@digitaldaemon.com...

> > As you can see, it's not nearly as elegant when you have to typedef everything.
>
> Yes I know it'll be more typing. Perhaps I can find a way to reduce that without doing the implicit instantiation two-step. There's another
maddening
> example of the implict instantiation resulting in bizarre rules - the way dependent and non-dependent names are looked up. The non-dependent names
are
> looked up in an earlier version of the global symbol table than the dependent names are.

   Yes, the non-dependent names are looked up at the point where the
template is defined, and the dependent names are looked up at the point the
template is instantiated. But how could this be different? Unless you
enforce the explicit enumeration of all allowed instances at the point where
the template is defined, or somehow store a snapshot of the symbol tables at
the point the template was defined, you still need to match names at the
point of instantiation. And those alternatives do not sound reasonable to
me.

> Perhaps this makes sense to someone, but to me it's
> just a way to torture compiler writers <g>.

   What alternative could there be? Looking up _all_ names at the point of
instantiation? I'm really curious.

   Or am I missing something here?

Salutaciones,
                         JCAB



July 07, 2002
Yeah, it seems difficult.  I never implemented generics before.  You're like 15 steps ahead of me there.  ;)

Sean

"Walter" <walter@digitalmars.com> wrote in message news:ag5bvm$227j$1@digitaldaemon.com...
> Yes I know it'll be more typing. Perhaps I can find a way to reduce that without doing the implicit instantiation two-step. There's another
maddening
> example of the implict instantiation resulting in bizarre rules - the way dependent and non-dependent names are looked up. The non-dependent names
are
> looked up in an earlier version of the global symbol table than the dependent names are. Perhaps this makes sense to someone, but to me it's just a way to torture compiler writers <g>.



July 07, 2002
"Juan Carlos Arevalo Baeza" <jcab@roningames.com> wrote in message news:ag5j9q$29lv$1@digitaldaemon.com...
>    Yes, the non-dependent names are looked up at the point where the
> template is defined, and the dependent names are looked up at the point
the
> template is instantiated. But how could this be different? Unless you enforce the explicit enumeration of all allowed instances at the point
where
> the template is defined, or somehow store a snapshot of the symbol tables
at
> the point the template was defined, you still need to match names at the point of instantiation. And those alternatives do not sound reasonable to me.
> > Perhaps this makes sense to someone, but to me it's
> > just a way to torture compiler writers <g>.
>    What alternative could there be? Looking up _all_ names at the point of
> instantiation? I'm really curious.
>    Or am I missing something here?

The DMC++ compiler collects the template definition as a list of tokens, and then inserts it into the source at the point of instantiation. So, all symbol table lookups are done at the point of instantiation. I believe that is a much more understandable rule (easy to explain) than the confusing and subtle difference in behavior between dependent and non-dependent names.


July 08, 2002
I don't believe the scoping rules would work with that scheme, would it? Like treating an inline function as a pure macro expansion, it just doesn't have the right semantics.

Sean

"Walter" <walter@digitalmars.com> wrote in message news:agajj6$1h6g$1@digitaldaemon.com...
>
> "Juan Carlos Arevalo Baeza" <jcab@roningames.com> wrote in message news:ag5j9q$29lv$1@digitaldaemon.com...
> >    Yes, the non-dependent names are looked up at the point where the
> > template is defined, and the dependent names are looked up at the point
> the
> > template is instantiated. But how could this be different? Unless you enforce the explicit enumeration of all allowed instances at the point
> where
> > the template is defined, or somehow store a snapshot of the symbol
tables
> at
> > the point the template was defined, you still need to match names at the point of instantiation. And those alternatives do not sound reasonable
to
> > me.
> > > Perhaps this makes sense to someone, but to me it's
> > > just a way to torture compiler writers <g>.
> >    What alternative could there be? Looking up _all_ names at the point
of
> > instantiation? I'm really curious.
> >    Or am I missing something here?
>
> The DMC++ compiler collects the template definition as a list of tokens,
and
> then inserts it into the source at the point of instantiation. So, all symbol table lookups are done at the point of instantiation. I believe
that
> is a much more understandable rule (easy to explain) than the confusing
and
> subtle difference in behavior between dependent and non-dependent names.



July 08, 2002
"Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:agbegl$2bll$1@digitaldaemon.com...
> I don't believe the scoping rules would work with that scheme, would it? Like treating an inline function as a pure macro expansion, it just
doesn't
> have the right semantics.

I neglected to mention that only the global namespace and the current namespace(s) are included in the instantiation symbol lookups.


July 08, 2002
Seems like it should only have access to:

1) The symbols available at the point of template declaration 2) The symbols injected into the template as template parameters 3) Symbols local to the template

Sean

"Walter" <walter@digitalmars.com> wrote in message news:agcei2$aln$2@digitaldaemon.com...
>
> "Sean L. Palmer" <seanpalmer@earthlink.net> wrote in message news:agbegl$2bll$1@digitaldaemon.com...
> > I don't believe the scoping rules would work with that scheme, would it? Like treating an inline function as a pure macro expansion, it just
> doesn't
> > have the right semantics.
>
> I neglected to mention that only the global namespace and the current namespace(s) are included in the instantiation symbol lookups.