www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Deep flaw with D's template mechanism

reply "Matthew Wilson" <admin.hat stlsoft.dot.org> writes:
Ok, here's where I'm at with working on DTL. I'm pretty sure I've hit some
fundamental limitations of D, that probably need to be changed.

I have a template member function of a container called select(), which
returns a collection-set - (for the moment, don't worry about what one of
those is) - of all elements which match a certain predicate.

Container
{
    template select(F) { final MatchedNotionalRange!(range_type, F) select(F
f = new F())
    {
        return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
    }}


Note that the function is defaulted, so that one can write things such as
the following:

    printf("\nselect()-ing the numbers, with IsOdd\n");
    foreach(int i; cont.select!(IsOdd)())
    {
        printf("%d ", i);
    }
    printf("\n");

Since many functors are default constructed, it's advantageous to be able to
default the argument to select().

However, when we wish to use a functor that needs non-default construction,
we run into some snags. The " = new F()" requires that the functor be
default constructible.

Now, if we could overload template member functions, this would not be an
issue, since we could separate select() into two functions, as follows:


Container
{
    template select(F) { final MatchedNotionalRange!(range_type, F) select(F
f)
    {
        return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
    }}

    template select(F) { final MatchedNotionalRange!(range_type, F) select()
    {
        return new MatchedNotionalRange!(range_type, F)(opSlice(), new F());
    }}


Then all would be happy.

If we can't have this, then we will have to stipulate functors twice, as
follows:

        foreach(int i; cont.select!(IsOdd)(new IsOdd()))
        {
            . . .

This is tedious.

Walter, what do you think?
Jul 16 2004
next sibling parent "Matthew Wilson" <admin.hat stlsoft.dot.org> writes:
Hmm. The title of this sounds a bit portentous. I meant to include other,
related, problems, but am holding off to see if I can find acceptable
workarounds

So, think of it as "Serious flaw with ..."

And now to bed, I think. Too many hours thinking about D for me today.



"Matthew Wilson" <admin.hat stlsoft.dot.org> wrote in message
news:cd8kek$7kh$1 digitaldaemon.com...
 Ok, here's where I'm at with working on DTL. I'm pretty sure I've hit some
 fundamental limitations of D, that probably need to be changed.

 I have a template member function of a container called select(), which
 returns a collection-set - (for the moment, don't worry about what one of
 those is) - of all elements which match a certain predicate.

 Container
 {
     template select(F) { final MatchedNotionalRange!(range_type, F)

 f = new F())
     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
     }}


 Note that the function is defaulted, so that one can write things such as
 the following:

     printf("\nselect()-ing the numbers, with IsOdd\n");
     foreach(int i; cont.select!(IsOdd)())
     {
         printf("%d ", i);
     }
     printf("\n");

 Since many functors are default constructed, it's advantageous to be able

 default the argument to select().

 However, when we wish to use a functor that needs non-default

 we run into some snags. The " = new F()" requires that the functor be
 default constructible.

 Now, if we could overload template member functions, this would not be an
 issue, since we could separate select() into two functions, as follows:


 Container
 {
     template select(F) { final MatchedNotionalRange!(range_type, F)

 f)
     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
     }}

     template select(F) { final MatchedNotionalRange!(range_type, F)

     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), new

     }}


 Then all would be happy.

 If we can't have this, then we will have to stipulate functors twice, as
 follows:

         foreach(int i; cont.select!(IsOdd)(new IsOdd()))
         {
             . . .

 This is tedious.

 Walter, what do you think?

Jul 16 2004
prev sibling next sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
silly question: why is select a template? Why not just make the selection
function (or delegate) an input? I haven't delved into STL implementations
before so I don't know all the C++ template tricks needed to get it working
but from a users point of view one just passes the function and it works,
right? If the Container is parameterized by the type T doesn't the selection
function should type int delegate(T val)? Variations would include inout T
val or function instead of delegate but basically it's all there.

"Matthew Wilson" <admin.hat stlsoft.dot.org> wrote in message
news:cd8kek$7kh$1 digitaldaemon.com...
 Ok, here's where I'm at with working on DTL. I'm pretty sure I've hit some
 fundamental limitations of D, that probably need to be changed.

 I have a template member function of a container called select(), which
 returns a collection-set - (for the moment, don't worry about what one of
 those is) - of all elements which match a certain predicate.

 Container
 {
     template select(F) { final MatchedNotionalRange!(range_type, F)

 f = new F())
     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
     }}


 Note that the function is defaulted, so that one can write things such as
 the following:

     printf("\nselect()-ing the numbers, with IsOdd\n");
     foreach(int i; cont.select!(IsOdd)())
     {
         printf("%d ", i);
     }
     printf("\n");

 Since many functors are default constructed, it's advantageous to be able

 default the argument to select().

 However, when we wish to use a functor that needs non-default

 we run into some snags. The " = new F()" requires that the functor be
 default constructible.

 Now, if we could overload template member functions, this would not be an
 issue, since we could separate select() into two functions, as follows:


 Container
 {
     template select(F) { final MatchedNotionalRange!(range_type, F)

 f)
     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
     }}

     template select(F) { final MatchedNotionalRange!(range_type, F)

     {
         return new MatchedNotionalRange!(range_type, F)(opSlice(), new

     }}


 Then all would be happy.

 If we can't have this, then we will have to stipulate functors twice, as
 follows:

         foreach(int i; cont.select!(IsOdd)(new IsOdd()))
         {
             . . .

 This is tedious.

 Walter, what do you think?

Jul 16 2004
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
Maybe I'm missing something, but can't you do this?:

template select(F) {
final MatchedNotionalRange!(range_type, F) select(F f)
{
return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
}

final MatchedNotionalRange!(range_type, F) select()
{
return new MatchedNotionalRange!(range_type, F)(opSlice(), new F());
}
}


Sean
Jul 16 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
Alas no. Overloading member templates is not supported. I want that support

"Sean Kelly" <sean f4.ca> wrote in message
news:cd8s6f$b77$1 digitaldaemon.com...
 Maybe I'm missing something, but can't you do this?:

 template select(F) {
 final MatchedNotionalRange!(range_type, F) select(F f)
 {
 return new MatchedNotionalRange!(range_type, F)(opSlice(), f);
 }

 final MatchedNotionalRange!(range_type, F) select()
 {
 return new MatchedNotionalRange!(range_type, F)(opSlice(), new F());
 }
 }


 Sean

Jul 16 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
Instead of having two separate templates, have one template with both
functions inside it.
Jul 16 2004
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Walter" <newshound digitalmars.com> wrote in message
news:cd955a$faj$1 digitaldaemon.com...
 Instead of having two separate templates, have one template with both
 functions inside it.

Doesn't work. If a member template has anything at all - an alias, a function - before the one function, it gives an error like "function expected before (), not 'cont dotexp template instance select!(IsOdd)' and the file/line is the client code call site. If I knock up a small example to demonstrate this, can you effect a fix in the next few hrs, so I can proceed?
Jul 16 2004