November 20, 2005
Hi,

Contrary to how the subject may sound, this is a suggestion for a small change in implicit template parameters. The spec says:

"If a template has exactly one member in it, and the name of that member is the same as the template name, that member is assumed to be referred to in a template instantiation"

I suggest an addition. Something like:

"If a template only has function members, all of which have the same name as the template, those are assumed to be referred to in a template instantiation."

Consider the following (nonsense) template defining a bunch of polymorphic
functions:

# template foo(T) {
#   T foo(int x) { return 1; }
#   T foo(double x) { return 2; }
# }

Those functions would then be accessed with eg. foo!(int). Eg:
foo!(int)(5) returns 1, foo!(int)(1.0) returns 2.

---

The reason I bumped into this was trying to implement array conversion functions:

# template conv(S:S[],D:D[]) {
#   D[] conv(S[] src) {
#     D[] dst;
#     dst.length = src.length;
#     foreach(int i, S s; src)
#       dst[i] = cast(D) s;
#     return dst;
#   }
# }

And then using a "templated typedef" for all basic types:

# template to(D:D[]) {
#   alias conv!(int[],D[]) to;
#   alias conv!(double[],D[]) to;
#   // etc...
# }

Allowing:

# const double[] x = [1.5,2.5,-0.9];
# int[] y = to!(int[])(x); // Doesn't compile. Needs to!(int[]).to(x);

(Ideally, I would like the syntax x.to!(int[]) to work, but this doesn't
work at all for templated functions. I may attend to this in a separate post.)

---

Concerning Implicit Template Properties:

I'm feeling slightly uncomfortable with the rule that removes the extra scope level when the template and a single parameter has the same name. Wouldn't it be better instead to make this explicit using the 'this' keyword:

# template something(T) {
#   T this(int x) {return 5;}
# }

# template SomethingElse(T) {
#   class this {
#     T x,y;
#   }
# }

---

Comments?

/Oskar


November 22, 2005
Oskar Linde wrote:
> Hi,
> 
> Contrary to how the subject may sound, this is a suggestion for a small change
> in implicit template parameters. The spec says:
> 
> "If a template has exactly one member in it, and the name of that member is the
> same as the template name, that member is assumed to be referred to in a
> template instantiation"
> 
> I suggest an addition. Something like:
> 
> "If a template only has function members, all of which have the same name as the
> template, those are assumed to be referred to in a template instantiation."
> 
> Consider the following (nonsense) template defining a bunch of polymorphic
> functions:
> 
> # template foo(T) {
> #   T foo(int x) { return 1; }
> #   T foo(double x) { return 2; }
> # }
> 
> Those functions would then be accessed with eg. foo!(int). Eg:
> foo!(int)(5) returns 1, foo!(int)(1.0) returns 2.

That makes sense, but be aware that right now, even this doesn't work:

template foo(T) {
  static if (1) {
    T foo(int x) { return 1; }
  }
}

int x = foo!(int)(5); // No, must use foo!(int).foo(5);
Walters indicated he's probably going to change this. But I hope that it would still work, even in extreme cases like:

template foo(T) {
  static if (is (T : int) ) {
    int foo(int x) { return 1; }
  } else {
    struct foo { T s; }
  }
}

And if that worked, your suggestion might work too.

> Concerning Implicit Template Properties:
> 
> I'm feeling slightly uncomfortable with the rule that removes the extra scope
> level when the template and a single parameter has the same name. Wouldn't it
> be better instead to make this explicit using the 'this' keyword:
> 
> # template something(T) {
> #   T this(int x) {return 5;}
> # }
> 
> # template SomethingElse(T) {
> #   class this {
> #     T x,y;
> #   }
> # }

I definitely like the idea -- but does it work? What happens when you need to use the 'this' pointer? How do you distinguish between the class and the instance?

 class this {
     this() {}
     this somefunc(this a) {
            this = a;
            return a.b==1 ? this : new this;
      }
   }

Another possibility might be to use the return keyword at the start of the declaration.


I would definitely be interested in something like one of these, if it was possible to prevent it from automatically triggering in template alias parameters (and if there was a way of triggering it later).

template t(alias a)
{
  void f() { writefln(typeid(a).typeof); }
}

template s(Z)
{
  Z s(int q) { return 1; }
}

t!(s!(int))

  ---> a is s!(int).s(),
but I want it to pass s!(int)

and later I want to invoke   s!(int).s(3)

I just feel that at the moment, some aspects of the language are too incomplete for the implicit template properties to really work well, right now it can be more of a nuisance.