www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Overriding to!string on enum types

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
Is it possible to override the behaviour of to!string(x) when x 
is an enum. I'm asking because this

enum CxxRefQualifier
{
     none,
     normalRef,
     rvalueRef
}

string toString(CxxRefQualifier refQ)  safe pure nothrow
{
     final switch (refQ)
     {
         case CxxRefQualifier.none: return "";
         case CxxRefQualifier.normalRef: return "&";
         case CxxRefQualifier.rvalueRef: return "&&";
     }
}

doesn't affect behaviour of to!string(x) when x is an instance of 
CxxRefQualifier.
Sep 02 2014
next sibling parent reply "evilrat" <evilrat666 gmail.com> writes:
On Tuesday, 2 September 2014 at 12:54:55 UTC, Nordlöw wrote:
 Is it possible to override the behaviour of to!string(x) when x 
 is an enum. I'm asking because this

 enum CxxRefQualifier
 {
     none,
     normalRef,
     rvalueRef
 }

 string toString(CxxRefQualifier refQ)  safe pure nothrow
 {
     final switch (refQ)
     {
         case CxxRefQualifier.none: return "";
         case CxxRefQualifier.normalRef: return "&";
         case CxxRefQualifier.rvalueRef: return "&&";
     }
 }

 doesn't affect behaviour of to!string(x) when x is an instance 
 of CxxRefQualifier.
i can think of two ways(both from memory) 1) specialized template override template to(T: enum)(T s) { string to(T s) { .. your custom code .. } } or just stringof CxxRefQualifier crq = CxxRefQualifier.normalRef; assert(crq == "normalRef");
Sep 02 2014
parent reply "evilrat" <evilrat666 gmail.com> writes:
sorry, i forgot everything.
here is example of how to do this
-----

import std.conv : to;

enum Test
{
  One,
  Two,
  Three,
}


template to(T: string)
{
  T to(A: Test)(A val)
  {
   final switch (val)
   {
    case Test.One: return "1";
    case Test.Two: return "2";
    case Test.Three: return "3";
   }
  }
}


void main()
{
assert(to!string(Test.One) == "1");
auto t = cast(Test)2;
assert(to!string(t) == "3");
assert(to!int("4") == 4); // shows original to! template works
}
Sep 02 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 2 September 2014 at 14:59:41 UTC, evilrat wrote:
 sorry, i forgot everything.
 here is example of how to do this
 -----

 import std.conv : to;

 enum Test
 {
  One,
  Two,
  Three,
 }


 template to(T: string)
 {
  T to(A: Test)(A val)
  {
   final switch (val)
   {
    case Test.One: return "1";
    case Test.Two: return "2";
    case Test.Three: return "3";
   }
  }
 }


 void main()
 {
 assert(to!string(Test.One) == "1");
 auto t = cast(Test)2;
 assert(to!string(t) == "3");
 assert(to!int("4") == 4); // shows original to! template works
 }
Word of warning: You are not overriding "to", but rather, simply defining your own "to" locally, which resolves as a better match in the context where you are using it. If you pass the enum to another function in another module, your "to" will NOT be called.
Sep 02 2014
parent "evilrat" <evilrat666 gmail.com> writes:
On Tuesday, 2 September 2014 at 15:42:36 UTC, monarch_dodra wrote:
 Word of warning: You are not overriding "to", but rather, 
 simply defining your own "to" locally, which resolves as a 
 better match in the context where you are using it.

 If you pass the enum to another function in another module, 
 your "to" will NOT be called.
i know. and because of that this template in same scope as enum
Sep 02 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 2 September 2014 at 12:54:55 UTC, Nordlöw wrote:
 Is it possible to override the behaviour of to!string(x) when x 
 is an enum. I'm asking because this

 enum CxxRefQualifier
 {
     none,
     normalRef,
     rvalueRef
 }

 string toString(CxxRefQualifier refQ)  safe pure nothrow
 {
     final switch (refQ)
     {
         case CxxRefQualifier.none: return "";
         case CxxRefQualifier.normalRef: return "&";
         case CxxRefQualifier.rvalueRef: return "&&";
     }
 }

 doesn't affect behaviour of to!string(x) when x is an instance 
 of CxxRefQualifier.
That won't work, because your "toString" is a free function. The module system doesn't allow this kind of "Koenig lookup"-like hijack. The only reason it allows for things like front/popFront and arrays, is that the other modules import std.array, and are "aware" of the functions. This is not true for user defined types. This may or may not be a feature :) Unless we allow defining "enum-member functions", AFAIK, it is impossible to override the printing behavior for enums... short of injecting your own modules in std.format/std.conv. Or to have a parameter "moduleLookup" in said template functions.
Sep 02 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 2 September 2014 at 15:41:17 UTC, monarch_dodra wrote:
 Unless we allow defining "enum-member functions", AFAIK, it is 
 impossible to override the printing behavior for enums...
... If your enum actually represents strings, then you could: enum CxxRefQualifier : string { none = "", normalRef = "&", rvalueRef = "&&", } That in itself is not enough, but you *can* cast your enum to string, and then print that, or pass that. See also: https://issues.dlang.org/show_bug.cgi?id=11571
Sep 02 2014