www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting a class' name, but not fully qualified?

reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
As the title says, I was wondering if there was a way to get the 
classes name at runtime, but not its fully qualified name. I want 
JUST the name of the class only. Obviously I could get the fully 
qualified name from the classinfo and then split it up to get the 
name of the class, but I don't want to do all that at runtime.

Is this possible or am I out of luck?
Mar 26 2014
next sibling parent Mike Parker <aldacron gmail.com> writes:
On 3/27/2014 3:16 PM, Jeremy DeHaan wrote:
 As the title says, I was wondering if there was a way to get the classes
 name at runtime, but not its fully qualified name. I want JUST the name
 of the class only. Obviously I could get the fully qualified name from
 the classinfo and then split it up to get the name of the class, but I
 don't want to do all that at runtime.

 Is this possible or am I out of luck?
I'm not aware of the class name being stored anywhere else in any other form, so even if you are using a Phobos function, or whatever, it's still going to have to deal with the FQN form before it hands you the name. But you don't have to split it. Just take a slice past the last '.'.
Mar 27 2014
prev sibling parent reply "JR" <zorael gmail.com> writes:
On Thursday, 27 March 2014 at 06:16:04 UTC, Jeremy DeHaan wrote:
 As the title says, I was wondering if there was a way to get 
 the classes name at runtime, but not its fully qualified name. 
 I want JUST the name of the class only.
So for a given class Foo, you want to extract the string "Foo"? class Foo { unittest() { assert(typeof(this).stringof == "Foo"); } } If that gets evaluated in runtime I guess you could store it in an enum.
Mar 27 2014
parent reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Thursday, 27 March 2014 at 10:01:40 UTC, JR wrote:
 On Thursday, 27 March 2014 at 06:16:04 UTC, Jeremy DeHaan wrote:
 As the title says, I was wondering if there was a way to get 
 the classes name at runtime, but not its fully qualified name. 
 I want JUST the name of the class only.
So for a given class Foo, you want to extract the string "Foo"? class Foo { unittest() { assert(typeof(this).stringof == "Foo"); } } If that gets evaluated in runtime I guess you could store it in an enum.
typeof(this) gives its fully qualified name though. I was looking for a way to get just the name of the class alone. I guess I can do a little processing since it happens in debug only, but I wanted to avoid it if possible. Thanks for the help, guys!
Mar 27 2014
parent reply "JR" <zorael gmail.com> writes:
On Thursday, 27 March 2014 at 17:41:14 UTC, Jeremy DeHaan wrote:
 typeof(this) gives its fully qualified name though. I was 
 looking for a way to get just the name of the class alone.
I guess I'm confused about what 'fully qualified name' entails. For a class Foo, is "Foo" not just the name of the class?
            assert(typeof(this).stringof == "Foo");
Mar 28 2014
parent reply "Matt" <webwraith fastmail.fm> writes:
On Friday, 28 March 2014 at 11:28:09 UTC, JR wrote:
 On Thursday, 27 March 2014 at 17:41:14 UTC, Jeremy DeHaan wrote:
 typeof(this) gives its fully qualified name though. I was 
 looking for a way to get just the name of the class alone.
I guess I'm confused about what 'fully qualified name' entails. For a class Foo, is "Foo" not just the name of the class?
           assert(typeof(this).stringof == "Foo");
I just ran the following on DMD 2.065: --- import std.stdio; class Foo{ int a; } void main(){ writeln ("stringof class: ", Foo.stringof); writeln ("classname: ", Foo.classinfo.name); } --- The following was the result: --- stringof class: Foo classname: classname.Foo --- I haven't tried with deeper derived trees, but this seems to suggest that the .stringof property provides the class name, WITHOUT the full qualification.
Mar 28 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 28 March 2014 at 13:28:00 UTC, Matt wrote:
 I haven't tried with deeper derived trees, but this seems to
 suggest that the .stringof property provides the class name,
 WITHOUT the full qualification.
Those can't be really compared. .stringof provides string representation of anything at compile-time. For class symbols it will be unqualified name of a symbol. Important thing is that stringifications happens only during compile-time and ignores polymorphism. .classinfo name is name for actual class instance referenced from the variable it was applied to. It happens to be fully qualified but key difference here is that it uses RTTI (run-time type information) to access "real" type of polymorphic entity. When working with classes you in most cases want the latter.
Mar 28 2014
parent reply "Matt" <webwraith fastmail.fm> writes:
On Friday, 28 March 2014 at 13:38:01 UTC, Dicebot wrote:

 .classinfo name is name for actual class instance referenced 
 from the variable it was applied to. It happens to be fully 
 qualified but key difference here is that it uses RTTI 
 (run-time type information) to access "real" type of 
 polymorphic entity.
Thanks for the clarification, Dicebot. Does it mention those points in the docs, because I don't remember seeing them? So we could be looking at something closer to: import std.string; import std.stdio; class Foo{ int a; } class Bar: Foo{ int b; } void main(){ Foo bar = new Bar(); writeln ("class name: " ~ bar.classinfo.name[bar.classinfo.name.lastIndexOf(".") .. $].dup); } if I'm correct?
Mar 30 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 30 March 2014 at 16:26:48 UTC, Matt wrote:
 On Friday, 28 March 2014 at 13:38:01 UTC, Dicebot wrote:

 .classinfo name is name for actual class instance referenced 
 from the variable it was applied to. It happens to be fully 
 qualified but key difference here is that it uses RTTI 
 (run-time type information) to access "real" type of 
 polymorphic entity.
Thanks for the clarification, Dicebot. Does it mention those points in the docs, because I don't remember seeing them? So we could be looking at something closer to: import std.string; import std.stdio; class Foo{ int a; } class Bar: Foo{ int b; } void main(){ Foo bar = new Bar(); writeln ("class name: " ~ bar.classinfo.name[bar.classinfo.name.lastIndexOf(".") .. $].dup); } if I'm correct?
Yes. You don't need .dup though and it will be `lastIndexOf + 1` for the start index but key idea is solid. This is not explicitly mentioned anywhere because "runtime type information" (http://dlang.org/phobos/object.html#.Classinfo) is a wide-spread term with strong meaning.
Mar 30 2014
parent reply "Matt" <webwraith fastmail.fm> writes:
On Sunday, 30 March 2014 at 16:33:47 UTC, Dicebot wrote:
 This is not explicitly mentioned anywhere because "runtime type 
 information" (http://dlang.org/phobos/object.html#.Classinfo) 
 is a wide-spread term with strong meaning.
what about .stringof? I don't think it mentions about the fact that that gets the string at compile time
Mar 30 2014
parent "Dicebot" <public dicebot.lv> writes:
On Sunday, 30 March 2014 at 16:42:54 UTC, Matt wrote:
 On Sunday, 30 March 2014 at 16:33:47 UTC, Dicebot wrote:
 This is not explicitly mentioned anywhere because "runtime 
 type information" 
 (http://dlang.org/phobos/object.html#.Classinfo) is a 
 wide-spread term with strong meaning.
what about .stringof? I don't think it mentions about the fact that that gets the string at compile time
http://dlang.org/property.html#stringof Term such as "source representation" has no meaning for run-time, at least not for natively compiled languages.
Mar 30 2014
prev sibling parent reply "w0rp" <devw0rp gmail.com> writes:
You could do the following.

class Klass {
     static class SubKlass {
     }
}

string baseName(ClassInfo classinfo) {
     import std.array;
     import std.algorithm : countUntil;
     import std.range : retro;

     string qualName = classinfo.name;

     size_t dotIndex = qualName.retro.countUntil('.');

     if (dotIndex < 0) {
         return qualName;
     }

     return qualName[$ - dotIndex .. $];
}

string classBaseName(Object instance) {
     if (instance is null) {
         return "null";
     }

     return instance.classinfo.baseName;
}

void main(string[] argv) {
     import std.stdio;

     writeln(Klass.classinfo.baseName);
     writeln(Klass.SubKlass.classinfo.baseName);

     Object x = new Klass();
     Object y = new Klass.SubKlass();

     writeln(x.classBaseName);
     writeln(y.classBaseName);
}

The above won't result in any extra allocation and there are two 
functions so you could find a class name both at compile time and 
a runtime without too much trouble.
Mar 28 2014
parent reply "JR" <zorael gmail.com> writes:
On Friday, 28 March 2014 at 13:42:43 UTC, w0rp wrote:
     size_t dotIndex = qualName.retro.countUntil('.');

     if (dotIndex < 0) {
size_t is unsigned. :3 (So ptrdiff_t -- or simply auto.)
Mar 28 2014
parent "w0rp" <devw0rp gmail.com> writes:
On Friday, 28 March 2014 at 20:47:39 UTC, JR wrote:
 On Friday, 28 March 2014 at 13:42:43 UTC, w0rp wrote:
    size_t dotIndex = qualName.retro.countUntil('.');

    if (dotIndex < 0) {
size_t is unsigned. :3 (So ptrdiff_t -- or simply auto.)
Oh yes, that is a bug. There's always at least one bug in an example.
Mar 28 2014