Jump to page: 1 2
Thread overview
Virtual functions and inheritance
Jan 27, 2015
David Monagle
Jan 27, 2015
H. S. Teoh
Jan 27, 2015
David Monagle
Jan 27, 2015
Daniel Kozák
Jan 27, 2015
Marc Schütz
Jan 27, 2015
Baz
Jan 27, 2015
bearophile
Jan 27, 2015
Tobias Pankrath
Jan 29, 2015
Baz
Jan 29, 2015
Baz
Jan 29, 2015
Tobias Pankrath
January 27, 2015
Hi guys,

I'm a former C++ developer and really enjoying working with D now. I have a question that I hope some of you may be able to answer.

class Parent {
  @property string typeName() {
    return typeof(this).stringof;
  }
}

class Child : Parent {
}

void main() {
  auto p = new Parent;
  auto c = new Child;
  assert(p.typeName == "Parent");
  assert(p.typeName == "Child");
}


I'm looking for an explanation as to why this doesn't work, then a suggestion for how I may achieve child classes being able to generate a string description of their own type, without redefining the typeName property on each child. (I'm currently solving this with a mixin, but I was hoping for a better solution.

I'm assuming it doesn't work because either typeof(this) or .stringof is evaluated at compile time?
January 27, 2015
On Tue, Jan 27, 2015 at 04:38:57AM +0000, David Monagle via Digitalmars-d-learn wrote:
> Hi guys,
> 
> I'm a former C++ developer and really enjoying working with D now. I have a question that I hope some of you may be able to answer.
> 
> class Parent {
>   @property string typeName() {
>     return typeof(this).stringof;
>   }
> }

Try this:

	class Parent {
	    @property string typeName() {
		return typeid(this).toString();
	    }
	}


> class Child : Parent {
> }
> 
> void main() {
>   auto p = new Parent;
>   auto c = new Child;
>   assert(p.typeName == "Parent");
>   assert(p.typeName == "Child");

Bug: the second assert should have c.typeName. :-) But I got what you mean.


> }
> 
> 
> I'm looking for an explanation as to why this doesn't work, then a suggestion for how I may achieve child classes being able to generate a string description of their own type, without redefining the typeName property on each child. (I'm currently solving this with a mixin, but I was hoping for a better solution.
> 
> I'm assuming it doesn't work because either typeof(this) or .stringof
> is evaluated at compile time?

typeof(this) is evaluated at compile-time. To get runtime information,
you need to use typeid().

Of course, with my suggested change your code still won't work as-is, because typeid().toString() returns a fully-qualified name, so if your source file is test.d, it would return "test.Parent" and "test.Child". But you should be able to work with that. :-)


T

-- 
The volume of a pizza of thickness a and radius z can be described by the following formula: pi zz a. -- Wouter Verhelst
January 27, 2015
I can certainly work with that. Thank you very much! (and for pointing out my typo in the example)
January 27, 2015
V Tue, 27 Jan 2015 04:38:57 +0000
David Monagle via Digitalmars-d-learn
<digitalmars-d-learn@puremagic.com> napsáno:

> Hi guys,
> 
> I'm a former C++ developer and really enjoying working with D now. I have a question that I hope some of you may be able to answer.
> 
> class Parent {
>    @property string typeName() {
>      return typeof(this).stringof;
>    }
> }
> 
> class Child : Parent {
> }
> 
> void main() {
>    auto p = new Parent;
>    auto c = new Child;
>    assert(p.typeName == "Parent");
>    assert(p.typeName == "Child");
> }
> 
> 
> I'm looking for an explanation as to why this doesn't work, then a suggestion for how I may achieve child classes being able to generate a string description of their own type, without redefining the typeName property on each child. (I'm currently solving this with a mixin, but I was hoping for a better solution.
> 
> I'm assuming it doesn't work because either typeof(this) or .stringof is evaluated at compile time?

You can use this T:

class Parent {
    @property string typeName(this T)() {
        return T.stringof;
    }
}

class Child : Parent {
}

void main() {
    auto p = new Parent;
    auto c = new Child;

    assert(p.typeName == "Parent");
    assert(c.typeName == "Child");
}

January 27, 2015
On Tuesday, 27 January 2015 at 08:19:46 UTC, Daniel Kozák wrote:
> You can use this T:
>
> class Parent {
>     @property string typeName(this T)() {
>         return T.stringof;
>     }
> }
>
> class Child : Parent {
> }
>
> void main() {
>     auto p = new Parent;
>     auto c = new Child;
>
>     assert(p.typeName == "Parent");
>     assert(c.typeName == "Child");
> }

OTOH:

void main() {
    auto p = new Parent;
    auto c = new Child;

    assert(p.typeName == "Parent");
    assert(c.typeName == "Child");

    p = c;
    assert(p.typeName == "Parent");
}

It will still use the static type of the object that it's called on, not the dynamic type.
January 27, 2015
On Tuesday, 27 January 2015 at 08:19:46 UTC, Daniel Kozák wrote:
> You can use this T:
>
> class Parent {
>     @property string typeName(this T)() {
>         return T.stringof;
>     }
> }
>
> class Child : Parent {
> }
>
> void main() {
>     auto p = new Parent;
>     auto c = new Child;
>
>     assert(p.typeName == "Parent");
>     assert(c.typeName == "Child");
> }

Could 'this T' be used for a static constructor ?

-----
class Bar
{
    static T construct(this T, A...)(A a)
    {
        return new T(a);
    }
}
----

doesn't work. And similarly to the the orginal post:

-----
class Bar
{
    static typeof(this) construct(A...)(A a)
    {
        return new typeof(this)(a);
    }
}

class Foo: Bar{}
Foo foo= Foo.construct; // fail

----

construct() won't be redefined in the Bar descendants.
January 27, 2015
Baz:

> doesn't work. And similarly to the the orginal post:

I suggest to read some D documentation first, and program later.

Bye,
bearophile
January 27, 2015
> -----
> class Bar
> {
>     static T construct(this T, A...)(A a)
>     {
>         return new T(a);
>     }
> }
> ----
>
I think it's a bug that you can use a template this parameter (this T) on a static member function without a direct compilation error.

> -----
> class Bar
> {
>     static typeof(this) construct(A...)(A a)
>     {
>         return new typeof(this)(a);
>     }
> }
>

Because it's exactly the same to write it as

    static Bar construct(A...)(A a) { return new Bar(a); }

Of course this does not work. I don't know how to do it without one line of boilerplate per class or without supplying the type via template argument.

std.container.util : make takes the type to construct as an argument, but std.container do not form a class hierarchy.
January 29, 2015
On Tuesday, 27 January 2015 at 04:38:59 UTC, David Monagle wrote:
> Hi guys,
>
> I'm a former C++ developer and really enjoying working with D now. I have a question that I hope some of you may be able to answer.
>
> class Parent {
>   @property string typeName() {
>     return typeof(this).stringof;
>   }
> }
>
> class Child : Parent {
> }
>
> void main() {
>   auto p = new Parent;
>   auto c = new Child;
>   assert(p.typeName == "Parent");
>   assert(p.typeName == "Child");
> }
>
>
> I'm looking for an explanation as to why this doesn't work, then a suggestion for how I may achieve child classes being able to generate a string description of their own type, without redefining the typeName property on each child. (I'm currently solving this with a mixin, but I was hoping for a better solution.
>
> I'm assuming it doesn't work because either typeof(this) or .stringof is evaluated at compile time?

This is almost the same code as written initially,
let somone explain why the hell this is working:

---
module test;
import std.conv;

class Parent {
  @property final string typeName() {
    return to!string(this);
  }
}

class Child : Parent {
}

void main() {
  auto p = new Parent;
  auto c = new Child;
  assert(p.typeName == __MODULE__ ~ ".Parent");
  assert(c.typeName == __MODULE__ ~ ".Child");
}
---
January 29, 2015
even more weird:

---
module test;
import std.conv;

interface Meh{
    final string typeName()
    {return to!string(this);}
}

class Parent : Meh {}

class Child : Parent {}

void main() {
  auto p = new Parent;
  auto c = new Child;
  assert(p.typeName == __MODULE__ ~ ".Parent");
  assert(c.typeName == __MODULE__ ~ ".Child");
}
---
« First   ‹ Prev
1 2