generic toString() in a template class?

Chris Nicholson-Sauls ibisbasenji at gmail.com
Tue Jan 16 12:36:04 PST 2007


%u wrote:
> 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?

Current D, off the top of my head:

# class S (T) {
#   T obj ;
#
#   char[] toString () {
#     static if (is(T == class)) {
#       return obj.toString;
#     }
#     else static if (is(T == struct)) {
#       static if (is(typeof(T.toString() == char[])))
#         return obj.toString;
#       }
#       else {
#         static assert (false, "class S!(T): struct T must expose function char[] 
toString()");
#       }
#     }
#     else {
#       std.string.toString(obj);
#     }
#   }
# }

-- Chris Nicholson-Sauls



More information about the Digitalmars-d mailing list