generic toString() in a template class?

%u no at where.com
Tue Jan 16 11:38:42 PST 2007


I wonder how one could write generic toString() method in a template class?

Suppose, I have a template class S(T), and will pass in as type param: class
A, struct B, int C:

====================================
$ cat ts.d

class A{}

struct B{
  char[] toString()  {return "B";}
}

int c;

class S(T) {
  T obj;

char[] toString() {
  return obj.toString();
}

}

int main(char[][] args) {
  S!(A)   sa;
  S!(B*)  sb;
  S!(int) sc;

  printf("%.*s", sa.toString());
  printf("%.*s", sb.toString());
  printf("%.*s", sc.toString());

  return 0;
}

$ dmd.exe ts.d
ts.d(14): Error: no property 'toString' for type 'int'
ts.d(14): Error: function expected before (), not 1 of type int
ts.d(14): Error: cannot implicitly convert expression (1()) of type int to char[]
ts.d(22): template instance ts.S!(int) error instantiating
====================================

OK, no property 'toString' for type 'int'; let's use some trick to do function
overloading:

====================================
$ cat ts.d

import std.string;

class A{}

struct B{
  char[] toString()  {return "B";}
}

int c;

char[] toStringFunc(Object obj) {return obj.toString();}
char[] toStringFunc(int i)      {return format(i);}

class S(T) {
  T obj;

char[] toString() {
  return toStringFunc(obj);
}

}

int main(char[][] args) {
  S!(A)   sa;
  S!(B*)  sb;
  S!(int) sc;

  printf("%.*s", sa.toString());
  printf("%.*s", sb.toString());
  printf("%.*s", sc.toString());

  return 0;
}

$ dmd.exe ts.d
ts.d(18): function ts.toStringFunc (Object) does not match parameter types (B *)
ts.d(18): Error: cannot implicitly convert expression (this.obj) of type B *
to int
ts.d(25): template instance ts.S!(B *) error instantiating
====================================

OK, struct is not Object, so let's just add char[] toStringFunc(void*  obj)
{return "null";}

====================================
$ cat ts.d
import std.string;

class A{}

struct B{
  char[] toString()  {return "B";}
}

int c;

char[] toStringFunc(Object obj) {return obj.toString();}
char[] toStringFunc(int i)      {return format(i);}
char[] toStringFunc(void*  obj) {return "null";}

class S(T) {
  T obj;

char[] toString() {
  return toStringFunc(obj);
}

}

int main(char[][] args) {
  S!(A)   sa;
  S!(B*)  sb;
  S!(int) sc;

  printf("%.*s", sa.toString());
  printf("%.*s", sb.toString());
  printf("%.*s", sc.toString());

  return 0;
}

$ dmd.exe ts.d
ts.d(19): function ts.toStringFunc called with argument types:
        (A)
matches both:
        ts.toStringFunc(Object)
and:
        ts.toStringFunc(void*)
ts.d(25): template instance ts.S!(A) error instantiating
====================================

Come on! class A matches both (Object) and (void*)?!

How could one write a generic toString() method in a template class then?

My suggestions:

-- if the compiler see a basic type, int.toString(), translate into a function
that does the Right Thing; just as if .toString() is also a property of basic
types like int.max, int.min.

-- class A, matches (Object) better than (void*), so just do the Right thing
to choose overloaded-function(Object obj).


comments?



More information about the Digitalmars-d mailing list