www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unqualified class name

reply Jeremy T. Gibson <jtgibson telus.net> writes:
I saw this thread -- 
https://forum.dlang.org/post/hdkvezicxfvehbtvjkfu forum.dlang.org 
-- which works at compile time (although templating seems like 
overkill for my purpose), but is there a simple way to get the 
unqualified name of a class at runtime without having to pass it 
through std.format?  `typeid(class).name` always yields the full 
classname, including its module information (i.e., 
"modulename.classname"), where I only want "classname" on its own.

I'm currently using manually-assigned literals to store the name 
of each class, which seems... wrong. ;-)

If it matters or makes things simpler, the class is attempting to 
report its own name in one of its own methods, rather than an 
external function attempting to deduce the name of an arbitrary 
object at runtime.
Aug 21 2021
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/21/21 10:33 AM, Jeremy T. Gibson wrote:

 `typeid(class).name` always yields the full classname, including its 
 module information (i.e., "modulename.classname"), where I only want 
 "classname" on its own.
I've been reminded of __traits(identifier) on this forum just yesterday: import std.stdio; class Coo { string name() const { return __traits(identifier, typeof(this)); } } void main() { auto c = new Coo(); writeln(c.name()); } Ali
Aug 21 2021
parent reply Jeremy T. Gibson <jtgibson telus.net> writes:
On Saturday, 21 August 2021 at 18:27:34 UTC, Ali Çehreli wrote:
     return __traits(identifier, typeof(this));
That works perfectly! Thanks. =)
Aug 21 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Saturday, 21 August 2021 at 21:13:58 UTC, Jeremy T. Gibson 
wrote:
 On Saturday, 21 August 2021 at 18:27:34 UTC, Ali Çehreli wrote:
     return __traits(identifier, typeof(this));
That works perfectly! Thanks. =)
This is exactly the solution you linked to in your first post, and found wanting. ```d class Whoami { string name() { return __traits(identifier, typeof(this)); } } class AnotherOne : Whoami { } unittest { assert((new Whoami).name == "Whoami"); assert((new AnotherOne).name == "Whoami"); } ```
Aug 21 2021
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 8/21/21 2:48 PM, jfondren wrote:
 On Saturday, 21 August 2021 at 21:13:58 UTC, Jeremy T. Gibson wrote:
 On Saturday, 21 August 2021 at 18:27:34 UTC, Ali =C3=87ehreli wrote:
 =C2=A0=C2=A0=C2=A0 return __traits(identifier, typeof(this));
That works perfectly!=C2=A0 Thanks. =3D)
=20 This is exactly the solution you linked to in your first post, and foun=
d=20
 wanting.
=20
 ```d
 class Whoami {
  =C2=A0=C2=A0=C2=A0 string name() {
  =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return __traits(identifier,=
typeof(this));
  =C2=A0=C2=A0=C2=A0 }
 }
 class AnotherOne : Whoami { }
=20
 unittest {
  =C2=A0=C2=A0=C2=A0 assert((new Whoami).name =3D=3D "Whoami");
  =C2=A0=C2=A0=C2=A0 assert((new AnotherOne).name =3D=3D "Whoami");
 }
 ```
I did not read the linked thread but a "this template parameter" seems=20 to work in this case: class Whoami { string name(this This)() const { return __traits(identifier, This); } } class AnotherOne : Whoami { } unittest { assert((new Whoami).name =3D=3D "Whoami"); assert((new AnotherOne).name =3D=3D "AnotherOne"); } void main() { } Ali
Aug 21 2021
parent jfondren <julian.fondren gmail.com> writes:
On Sunday, 22 August 2021 at 00:18:18 UTC, Ali Çehreli wrote:
 I did not read the linked thread but a "this template 
 parameter" seems to work in this case:

 class Whoami {
   string name(this This)() const {
     return __traits(identifier, This);
   }
 }
 class AnotherOne : Whoami { }

 unittest {
   assert((new Whoami).name == "Whoami");
   assert((new AnotherOne).name == "AnotherOne");
 }

 void main() {
 }

 Ali
That's not enough to make runtime dispatch out of static dispatch: ```d class Whoami { string name(this This)() const { return __traits(identifier, This); } string rtname() const { import std.path : extension; return typeid(this).name.extension[1 .. $]; } } class AnotherOne : Whoami { } unittest { import std.algorithm : map, equal; auto list = [new Whoami, new AnotherOne]; assert(list.map!(o => o.name).equal(["Whoami", "Whoami"])); assert(list.map!(o => o.rtname).equal(["Whoami", "AnotherOne"])); } ``` The next stage of complication is to have compiled library code that loops over Whoami[] getting some subtypes of Whoami that were defined unknowable to the library.
Aug 21 2021
prev sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Saturday, 21 August 2021 at 17:33:51 UTC, Jeremy T. Gibson 
wrote:
 is there a simple way to get the unqualified name of a class at 
 runtime without having to pass it through std.format?  
 `typeid(class).name` always yields the full classname, 
 including its module information (i.e., 
 "modulename.classname"), where I only want "classname" on its 
 own.
https://dlang.org/phobos/object.html#.TypeInfo_Class.name is all you have there, and it's just a string, so the simple way is to manipulate the string. This seems a bit silly but I'm not worried about VMS 2.0 coming along and changing how extensions work ("nodot".extension == "" however, so if module-less classes are possible then this would fail with a RangeError): ```d class Whoami { string report() { import std.path : extension; return "class: " ~ typeid(this).name.extension[1..$]; } } class AnotherOne : Whoami {} unittest { assert((new Whoami).report == "class: Whoami"); assert((new AnotherOne).report == "class: AnotherOne"); } string unqualified(string name) { import std.string : lastIndexOf; import std.algorithm : min; const i = name.lastIndexOf('.'); return i == -1 ? name : name[min(i+1, $) .. $]; } unittest { assert(typeid(new Whoami).name.unqualified == "Whoami"); assert(typeid(new AnotherOne).name.unqualified == "AnotherOne"); assert("".unqualified == ""); assert("x".unqualified == "x"); assert("x.".unqualified == ""); } ```
Aug 21 2021
parent Jeremy T. Gibson <jtgibson telus.net> writes:
On Saturday, 21 August 2021 at 18:45:07 UTC, jfondren wrote:
 On Saturday, 21 August 2021 at 17:33:51 UTC, Jeremy T. Gibson 
 wrote:
 is there a simple way to get the unqualified name of a class 
 at runtime without having to pass it through std.format?  
 `typeid(class).name` always yields the full classname, 
 including its module information (i.e., 
 "modulename.classname"), where I only want "classname" on its 
 own.
https://dlang.org/phobos/object.html#.TypeInfo_Class.name is all you have there, and it's just a string, so the simple way is to manipulate the string.
 string unqualified(string name) {
     import std.string : lastIndexOf;
     import std.algorithm : min;

     const i = name.lastIndexOf('.');
     return i == -1 ? name : name[min(i+1, $) .. $];
Parsing was always an option, but anytime I come across a solution where parsing/formatting seems to be the answer, it always feels more hacky than a genuine solution. Hacks can be fine, especially in low-frequency code like the stuff I'm revisiting this month, but I always prefer direct library-based or language-based solutions whenever humanly possible. Dlang's reference docs unfortunately assume a level of expertise with the language (especially, expertise with code generation and compiler specs) that makes it much harder for me to "ask the right questions" when I'm searching: I'm really not much of a programmer. Heh.
Aug 21 2021