www.digitalmars.com         C & C++   DMDScript  

D - Irritating template inconsistency

reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
D provides for the programmer to omit the type within a template
instantiation, if there is only one type in the template, and it has the
same name as the template. This is provided as a convenience (AFAIK).
Consider the following code:

  template Thing(T)
  {
    class Thing
    {}
  }

  template Thing2(T)
  {
    class Thing2
    {}

    class X
    {}
  }

  int main()
  {
    alias Thing!(int)     thing_int_t;
    alias Thing2!(int).Thing2 thing2_int_t;

    alias Thing!(int).Thing   thing_int_2_t;  // no property 'Thing' for
type 'Thing'

    return 0;
  }

The first instantiation does not require anything after the "!(int)" because
there is only one type - the class Thing - within the Thing template.

The second instantiation does require the full qualification, because there
are two types within the template.

The third instantiation is an error, and gives a misleading error message.
Is this intended behaviour? It seems unnecessarily inconsistent, and is very
irritating when one is developing template code and moving things around a
lot, as the client code has to be changed every time.
Apr 20 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c63vmm$ju5$1 digitaldaemon.com...
 D provides for the programmer to omit the type within a template
 instantiation, if there is only one type in the template, and it has the
 same name as the template. This is provided as a convenience (AFAIK).
 Consider the following code:

   template Thing(T)
   {
     class Thing
     {}
   }

   template Thing2(T)
   {
     class Thing2
     {}

     class X
     {}
   }

   int main()
   {
     alias Thing!(int)     thing_int_t;
     alias Thing2!(int).Thing2 thing2_int_t;

     alias Thing!(int).Thing   thing_int_2_t;  // no property 'Thing' for
 type 'Thing'

     return 0;
   }

 The first instantiation does not require anything after the "!(int)"

 there is only one type - the class Thing - within the Thing template.

 The second instantiation does require the full qualification, because

 are two types within the template.

 The third instantiation is an error, and gives a misleading error message.
 Is this intended behaviour? It seems unnecessarily inconsistent, and is

 irritating when one is developing template code and moving things around a
 lot, as the client code has to be changed every time.

Yes, it is intended. You can avoid the issue, though, by adding a dummy declaration in the template.
Apr 20 2004
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 20 Apr 2004 17:26:13 -0700, Walter wrote:

 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c63vmm$ju5$1 digitaldaemon.com...
 D provides for the programmer to omit the type within a template
 instantiation, if there is only one type in the template, and it has the
 same name as the template. This is provided as a convenience (AFAIK).
 Consider the following code:

   template Thing(T)
   {
     class Thing
     {}
   }

   template Thing2(T)
   {
     class Thing2
     {}

     class X
     {}
   }

   int main()
   {
     alias Thing!(int)     thing_int_t;
     alias Thing2!(int).Thing2 thing2_int_t;

     alias Thing!(int).Thing   thing_int_2_t;  // no property 'Thing' for
 type 'Thing'

     return 0;
   }

 The first instantiation does not require anything after the "!(int)"

 there is only one type - the class Thing - within the Thing template.

 The second instantiation does require the full qualification, because

 are two types within the template.

 The third instantiation is an error, and gives a misleading error message.
 Is this intended behaviour? It seems unnecessarily inconsistent, and is

 irritating when one is developing template code and moving things around a
 lot, as the client code has to be changed every time.

Yes, it is intended. You can avoid the issue, though, by adding a dummy declaration in the template.

Walter, what is your reason for this behaviour. Not that I'm suggesting anything is wrong or otherwise, just curious. I guess I'm hoping that it wasn't an arbitrary or "convenient" decision, but instead one based on sound reasoning. -- Derek 21/Apr/04 11:02:50 AM
Apr 20 2004
parent "Walter" <walter digitalmars.com> writes:
"Derek Parnell" <derek psych.ward> wrote in message
news:13z4hgc9kgxng$.1jahjei5gnd6s$.dlg 40tude.net...
 Yes, it is intended. You can avoid the issue, though, by adding a dummy
 declaration in the template.

Walter, what is your reason for this behaviour. Not that I'm suggesting anything

 wrong or otherwise, just curious. I guess I'm hoping that it wasn't an
 arbitrary or "convenient" decision, but instead one based on sound
 reasoning.

The symbol table lookups needed to be unambiguous. Therefore, a rule is required to say in what scope a symbol is in. Having it in both scopes and trying to guess what the programmer meant leads to trouble like the wretched tag name space in C++. I'd rather have a simple rule that is easilly explained that may lead to minor aggravation on occaision, than a complicated rule that is hard to explain that mostly works right until it doesn't and somebody starts up a "D Bug of the Month" column <g>.
Apr 21 2004
prev sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Walter" <walter digitalmars.com> wrote in message
news:c64ffb$1ehd$2 digitaldaemon.com...
 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c63vmm$ju5$1 digitaldaemon.com...
 D provides for the programmer to omit the type within a template
 instantiation, if there is only one type in the template, and it has the
 same name as the template. This is provided as a convenience (AFAIK).
 Consider the following code:

   template Thing(T)
   {
     class Thing
     {}
   }

   template Thing2(T)
   {
     class Thing2
     {}

     class X
     {}
   }

   int main()
   {
     alias Thing!(int)     thing_int_t;
     alias Thing2!(int).Thing2 thing2_int_t;

     alias Thing!(int).Thing   thing_int_2_t;  // no property 'Thing' for
 type 'Thing'

     return 0;
   }

 The first instantiation does not require anything after the "!(int)"

 there is only one type - the class Thing - within the Thing template.

 The second instantiation does require the full qualification, because

 are two types within the template.

 The third instantiation is an error, and gives a misleading error


 Is this intended behaviour? It seems unnecessarily inconsistent, and is

 irritating when one is developing template code and moving things around


 lot, as the client code has to be changed every time.

Yes, it is intended. You can avoid the issue, though, by adding a dummy declaration in the template.

What's the rationale? It doesn't make sense to me. And your solution smacks of a C++ hack. Isn't this a modern language designed from the off to avoid crappy hacks?
Apr 20 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c64i8l$1j2g$2 digitaldaemon.com...
 What's the rationale? It doesn't make sense to me. And your solution

 of a C++ hack. Isn't this a modern language designed from the off to avoid
 crappy hacks?

It's a worse hack to have the symbol appear in two scopes. Consider: template Foo(T) { class Foo { int Foo; } } Now we do: Foo!(int).Foo What are we referring to? class Foo or int Foo?
Apr 21 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Walter" <walter digitalmars.com> wrote in message
news:c65dof$314c$2 digitaldaemon.com...
 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c64i8l$1j2g$2 digitaldaemon.com...
 What's the rationale? It doesn't make sense to me. And your solution

 of a C++ hack. Isn't this a modern language designed from the off to avoid
 crappy hacks?

It's a worse hack to have the symbol appear in two scopes. Consider: template Foo(T) { class Foo { int Foo; } } Now we do: Foo!(int).Foo What are we referring to? class Foo or int Foo?

Well, this is where I could comment that we should be using the :: operator ... I take your point with the given example, but I would then suggest that the short-circuit version be dropped. Since there's still the "!(...)' gunk needed, why not just incline people to use aliases in all cases. I would prefer the consistency, as I'm finding this the most vexing part of my use of templates, and not in the least "minor aggravation on occasion".
Apr 21 2004
parent reply "Walter" <walter digitalmars.com> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c65enm$129$2 digitaldaemon.com...
 Well, this is where I could comment that we should be using the ::

 I take your point with the given example, but I would then suggest that

 short-circuit version be dropped. Since there's still the "!(...)' gunk

 why not just incline people to use aliases in all cases. I would prefer

 consistency, as I'm finding this the most vexing part of my use of

 not in the least "minor aggravation on occasion".

The short circuit version is there because people simply did not like the: Foo!(int).Foo construct for one member templates, and I didn't either.
Apr 21 2004
parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Walter" <walter digitalmars.com> wrote in message
news:c66f9s$1qqk$2 digitaldaemon.com...
 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c65enm$129$2 digitaldaemon.com...
 Well, this is where I could comment that we should be using the ::

 I take your point with the given example, but I would then suggest that

 short-circuit version be dropped. Since there's still the "!(...)' gunk

 why not just incline people to use aliases in all cases. I would prefer

 consistency, as I'm finding this the most vexing part of my use of

 not in the least "minor aggravation on occasion".

The short circuit version is there because people simply did not like the: Foo!(int).Foo construct for one member templates, and I didn't either.

Me either. But I like the inconsistency less. Since alias will be a well-used feature with templates anyway, why not remove the confusing/annoying inconsistency?
Apr 21 2004