www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Question about typeof(this)

reply Jacob Carlborg <doob me.com> writes:
I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof 
where it says:

"typeof(this) will generate the type of what this  would be in a 
non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the same 
result, but it doesn't. It prints:

main.Bar
main.Foo

instead of:

main.Foo
main.Foo

Is this a bug or have I misunderstood the docs?


module main;

import std.stdio;

class Bar
{
	void method ()
	{
		writeln(typeid(typeof(this)));
		writeln(typeid(this));
	}
}

class Foo : Bar {}

void main ()
{
	auto foo = new Foo;
	foo.method;
}

-- 
/Jacob Carlborg
Sep 07 2010
next sibling parent reply Don <nospam nospam.com> writes:
Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof 
 where it says:
 
 "typeof(this) will generate the type of what this  would be in a 
 non-static member function, even if not in a member function. "
 
  From that I got the impression that the code below would print the same 
 result, but it doesn't. It prints:
 
 main.Bar
 main.Foo
 
 instead of:
 
 main.Foo
 main.Foo
 
 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.
 
 
 module main;
 
 import std.stdio;
 
 class Bar
 {
     void method ()
     {
         writeln(typeid(typeof(this)));
         writeln(typeid(this));
     }
 }
 
 class Foo : Bar {}
 
 void main ()
 {
     auto foo = new Foo;
     foo.method;
 }
 

Sep 07 2010
parent reply Jacob Carlborg <doob me.com> writes:
On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".
 module main;

 import std.stdio;

 class Bar
 {
 void method ()
 {
 writeln(typeid(typeof(this)));
 writeln(typeid(this));
 }
 }

 class Foo : Bar {}

 void main ()
 {
 auto foo = new Foo;
 foo.method;
 }


-- /Jacob Carlborg
Sep 07 2010
parent reply Don <nospam nospam.com> writes:
Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.
Sep 07 2010
parent reply Jacob Carlborg <doob me.com> writes:
On 2010-09-07 22:32, Don wrote:
 Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.

I think Scala can handle this problem, the following text is a snippet from a paper called "Scalable Component Abstractions" (link at the bottom), page 4 "Type selection and singleton types": class C { protected var x = 0; def incr: this.type = { x = x + 1; this } } class D extends C { def decr: this.type = { x = x - 1; this } } "Then we can chain calls to the incr and decr method, as in val d = new D; d.incr.decr; Without the singleton type this.type, this would not have been possible, since d.incr would be of type C, which does not have a decr member. In that sense, this.type is similar to (covariant uses of ) Kim Bruce's mytype construct [5]." I'm not very familiar with Scala but the above code example seems to work as I want typeof(this) to work. http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf -- /Jacob Carlborg
Sep 10 2010
parent reply Pelle <pelle.mansson gmail.com> writes:
On 09/10/2010 03:20 PM, Jacob Carlborg wrote:
 On 2010-09-07 22:32, Don wrote:
 Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.

I think Scala can handle this problem, the following text is a snippet from a paper called "Scalable Component Abstractions" (link at the bottom), page 4 "Type selection and singleton types": class C { protected var x = 0; def incr: this.type = { x = x + 1; this } } class D extends C { def decr: this.type = { x = x - 1; this } } "Then we can chain calls to the incr and decr method, as in val d = new D; d.incr.decr; Without the singleton type this.type, this would not have been possible, since d.incr would be of type C, which does not have a decr member. In that sense, this.type is similar to (covariant uses of ) Kim Bruce's mytype construct [5]." I'm not very familiar with Scala but the above code example seems to work as I want typeof(this) to work. http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf

You can do this in D, but the syntax is clumsy. And it uses templates. class C { int x; T incr(this T)() { x += 1; return cast(T)this; // clumsy, but always works (?) } } class D : C { T decr(this T)() { x -= 1; return cast(T)this; } } void main() { D d = new D; d.decr.incr.decr.incr.incr; writeln(d.x); }
Sep 10 2010
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2010-09-10 16:53, Pelle wrote:
 On 09/10/2010 03:20 PM, Jacob Carlborg wrote:
 On 2010-09-07 22:32, Don wrote:
 Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.

I think Scala can handle this problem, the following text is a snippet from a paper called "Scalable Component Abstractions" (link at the bottom), page 4 "Type selection and singleton types": class C { protected var x = 0; def incr: this.type = { x = x + 1; this } } class D extends C { def decr: this.type = { x = x - 1; this } } "Then we can chain calls to the incr and decr method, as in val d = new D; d.incr.decr; Without the singleton type this.type, this would not have been possible, since d.incr would be of type C, which does not have a decr member. In that sense, this.type is similar to (covariant uses of ) Kim Bruce's mytype construct [5]." I'm not very familiar with Scala but the above code example seems to work as I want typeof(this) to work. http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf

You can do this in D, but the syntax is clumsy. And it uses templates. class C { int x; T incr(this T)() { x += 1; return cast(T)this; // clumsy, but always works (?) } } class D : C { T decr(this T)() { x -= 1; return cast(T)this; } } void main() { D d = new D; d.decr.incr.decr.incr.incr; writeln(d.x); }

I had no idea about this, thanks. I don't like the templates but I guess it's better than nothing. -- /Jacob Carlborg
Sep 12 2010
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2010-09-10 16:53, Pelle wrote:
 On 09/10/2010 03:20 PM, Jacob Carlborg wrote:
 On 2010-09-07 22:32, Don wrote:
 Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.

I think Scala can handle this problem, the following text is a snippet from a paper called "Scalable Component Abstractions" (link at the bottom), page 4 "Type selection and singleton types": class C { protected var x = 0; def incr: this.type = { x = x + 1; this } } class D extends C { def decr: this.type = { x = x - 1; this } } "Then we can chain calls to the incr and decr method, as in val d = new D; d.incr.decr; Without the singleton type this.type, this would not have been possible, since d.incr would be of type C, which does not have a decr member. In that sense, this.type is similar to (covariant uses of ) Kim Bruce's mytype construct [5]." I'm not very familiar with Scala but the above code example seems to work as I want typeof(this) to work. http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf

You can do this in D, but the syntax is clumsy. And it uses templates. class C { int x; T incr(this T)() { x += 1; return cast(T)this; // clumsy, but always works (?) } } class D : C { T decr(this T)() { x -= 1; return cast(T)this; } } void main() { D d = new D; d.decr.incr.decr.incr.incr; writeln(d.x); }

I've done some testing with this template parameters and it actually works as I want it to, but I don't understand why it has to be a template. Both templates and typeof are resolved at compile time so I don't understand why it can't work with typeof. I have this example now: module main; import std.stdio; class Base { void foo (this T) () { writeln(T.stringof); writeln(typeof(this).stringof); } } class Foo : Base { } void main() { auto foo = new Foo; foo.foo; } It will print: Foo Base To me this template parameters look unnecessary, typeof should be able to handle this. In the above "foo" method I think T should be equal to typeof(this). -- /Jacob Carlborg
Sep 12 2010
parent Don <nospam nospam.com> writes:
Jacob Carlborg wrote:
 On 2010-09-10 16:53, Pelle wrote:
 On 09/10/2010 03:20 PM, Jacob Carlborg wrote:
 On 2010-09-07 22:32, Don wrote:
 Jacob Carlborg wrote:
 On 2010-09-07 17:29, Don wrote:
 Jacob Carlborg wrote:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?

typeof(this) gives the *compile-time* type of this. Inside Bar, it has to return 'Bar'. typeid(this) gives the *runtime* type of this. So it can work that it's Bar is actually a Foo.

I know that typeof(this) is a compile time expression but in this case I think the compiler has all the necessary information at compile time. Note that I'm not calling "method" on a base class reference, I'm calling it on the static type "Foo". In this case I think typeof(this) would resolve to the type of the receiver, i.e. the type of"foo".

Even though in this instance it could work out which derived class is being used, it's not allowed to use that information while compiling method(). There is only ONE function method(), and it has to work for Bar, and all classes derived from Bar.

I think Scala can handle this problem, the following text is a snippet from a paper called "Scalable Component Abstractions" (link at the bottom), page 4 "Type selection and singleton types": class C { protected var x = 0; def incr: this.type = { x = x + 1; this } } class D extends C { def decr: this.type = { x = x - 1; this } } "Then we can chain calls to the incr and decr method, as in val d = new D; d.incr.decr; Without the singleton type this.type, this would not have been possible, since d.incr would be of type C, which does not have a decr member. In that sense, this.type is similar to (covariant uses of ) Kim Bruce's mytype construct [5]." I'm not very familiar with Scala but the above code example seems to work as I want typeof(this) to work. http://www.scala-lang.org/sites/default/files/odersky/ScalableComponent.pdf

You can do this in D, but the syntax is clumsy. And it uses templates. class C { int x; T incr(this T)() { x += 1; return cast(T)this; // clumsy, but always works (?) } } class D : C { T decr(this T)() { x -= 1; return cast(T)this; } } void main() { D d = new D; d.decr.incr.decr.incr.incr; writeln(d.x); }

I've done some testing with this template parameters and it actually works as I want it to, but I don't understand why it has to be a template. Both templates and typeof are resolved at compile time so I don't understand why it can't work with typeof. I have this example now: module main; import std.stdio; class Base { void foo (this T) () { writeln(T.stringof); writeln(typeof(this).stringof); } } class Foo : Base { } void main() { auto foo = new Foo; foo.foo; } It will print: Foo Base To me this template parameters look unnecessary, typeof should be able to handle this. In the above "foo" method I think T should be equal to typeof(this).

(1) make it a template, so that the function is duplicated for every derived class (that's what this solution is doing); OR (2) use runtime type information. Both of these have unacceptable consequences in general.
Sep 14 2010
prev sibling parent reply Stanislav Blinov <blinov loniir.ru> writes:
  07.09.2010 17:00, Jacob Carlborg пишет:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof 
 where it says:

 "typeof(this) will generate the type of what this would be in a 
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the 
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?


 module main;

 import std.stdio;

 class Bar
 {
 void method ()
 {
 writeln(typeid(typeof(this)));
 writeln(typeid(this));
 }
 }

 class Foo : Bar {}

 void main ()
 {
 auto foo = new Foo;
 foo.method;
 }

your very same example in Typeid section. Inside Bar.method, typeof(this) yields a type (Bar), and typeid for types gets you, well, typeid for types :) typeid(this), hovewer, should get typeinfo for most derived class, which it does.
Sep 07 2010
parent reply Jacob Carlborg <doob me.com> writes:
On 2010-09-07 17:34, Stanislav Blinov wrote:
 07.09.2010 17:00, Jacob Carlborg пишет:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?


 module main;

 import std.stdio;

 class Bar
 {
 void method ()
 {
 writeln(typeid(typeof(this)));
 writeln(typeid(this));
 }
 }

 class Foo : Bar {}

 void main ()
 {
 auto foo = new Foo;
 foo.method;
 }

your very same example in Typeid section. Inside Bar.method, typeof(this) yields a type (Bar), and typeid for types gets you, well, typeid for types :) typeid(this), hovewer, should get typeinfo for most derived class, which it does.

No it's not the same example. In the example on the Expressions page typeid is used on the static type A with the dynamic type B. I have both the static and dynamic type Foo. I think in my example the compiler have all the necessary information at compile time and typeof(this) would resolve to the type of the receiver, i.e. the type of "foo" which is Foo. -- /Jacob Carlborg
Sep 07 2010
parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
Jacob Carlborg wrote:
 On 2010-09-07 17:34, Stanislav Blinov wrote:
 07.09.2010 17:00, Jacob Carlborg пишет:
 I'm reading http://www.digitalmars.com/d/2.0/declaration.html#Typeof
 where it says:

 "typeof(this) will generate the type of what this would be in a
 non-static member function, even if not in a member function. "

 From that I got the impression that the code below would print the
 same result, but it doesn't. It prints:

 main.Bar
 main.Foo

 instead of:

 main.Foo
 main.Foo

 Is this a bug or have I misunderstood the docs?


 module main;

 import std.stdio;

 class Bar
 {
 void method ()
 {
 writeln(typeid(typeof(this)));
 writeln(typeid(this));
 }
 }

 class Foo : Bar {}

 void main ()
 {
 auto foo = new Foo;
 foo.method;
 }

your very same example in Typeid section. Inside Bar.method, typeof(this) yields a type (Bar), and typeid for types gets you, well, typeid for types :) typeid(this), hovewer, should get typeinfo for most derived class, which it does.

No it's not the same example. In the example on the Expressions page typeid is used on the static type A with the dynamic type B. I have both the static and dynamic type Foo. I think in my example the compiler have all the necessary information at compile time and typeof(this) would resolve to the type of the receiver, i.e. the type of "foo" which is Foo.

that in this particular case compiler may have sufficient information, but there are plenty of cases when it may not: e.g. class Foo is in a separate module or even separate library. After all, method actually has signature Bar.method(), not Foo.method().
Sep 07 2010