www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Multiple alias this failed workaround...obscure error message

reply "matovitch" <camille.brugel laposte.net> writes:
I was looking for a workaround to multiple alias this (or 
opImplicitCast) the following trick doesn't work (why shouldn't 
it ?). The error message is quite obscure to me.


import std.stdio;

class A(Derived)
{
     alias cast(ref Derived)(this).x this;
}

class B : A!B
{
     float x;
}

class C : A!C
{
     int x;
}

void main()
{
     B b;
     b.x = 0.5;

     float f;
     f = b;
}


output :

source/app.d(5): Error: basic type expected, not cast
source/app.d(5): Error: no identifier for declarator int
source/app.d(5): Error: semicolon expected to close alias 
declaration
source/app.d(5): Error: Declaration expected, not 'cast'
Error: DMD compile run failed with exit code 1
Jun 11 2014
next sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
 Sent: Wednesday, June 11, 2014 at 8:07 PM
 From: "matovitch via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com>
 To: digitalmars-d-learn puremagic.com
 Subject: Multiple alias this failed workaround...obscure error message

 I was looking for a workaround to multiple alias this (or 
 opImplicitCast) the following trick doesn't work (why shouldn't 
 it ?). The error message is quite obscure to me.
 
 
 import std.stdio;
 
 class A(Derived)
 {
      alias cast(ref Derived)(this).x this;
 }
 
 class B : A!B
 {
      float x;
 }
 
 class C : A!C
 {
      int x;
 }
 
 void main()
 {
      B b;
      b.x = 0.5;
 
      float f;
      f = b;
 }
 
 
 output :
 
 source/app.d(5): Error: basic type expected, not cast
 source/app.d(5): Error: no identifier for declarator int
 source/app.d(5): Error: semicolon expected to close alias 
 declaration
 source/app.d(5): Error: Declaration expected, not 'cast'
 Error: DMD compile run failed with exit code 1
I don't believe that it's legal to use a cast in an alias declaration, and that's certainly what the error seems to be indicating. Also, using ref in a cast is definitely illegal regardless of where the cast is. ref is not part of a type. The only places that you can use it are function parameters, return types, and foreach variables. If you want to do anything like you seem to be trying to do, you're going to have to alias a function which does the cast for you rather than try and alias the variable itself. I also don't see anything here that would work as any kind of multiple alias this. - Jonathan M Davis
Jun 11 2014
parent reply "matovitch" <camille.brugel laposte.net> writes:
On Wednesday, 11 June 2014 at 20:53:21 UTC, Jonathan M Davis via 
Digitalmars-d-learn wrote:
 I don't believe that it's legal to use a cast in an alias 
 declaration, and
 that's certainly what the error seems to be indicating. Also, 
 using ref in a
 cast is definitely illegal regardless of where the cast is. ref 
 is not part
 of a type. The only places that you can use it are function 
 parameters, return
 types, and foreach variables. If you want to do anything like 
 you seem to be
 trying to do, you're going to have to alias a function which 
 does the cast for
 you rather than try and alias the variable itself.

 I also don't see anything here that would work as any kind of 
 multiple alias
 this.

 - Jonathan M Davis
Thank you, I was assuming D worked as C++ but ref not being part of type is so much better ! (According to Marc Schütz your solution isn't doing so well.) About alias working with identifier but not with (runtime) expression. Alias should work with compile time expression like map!(x=>2*x) right ? So a static cast should work isn't it ? (though static_cast doesn't exist in D :/)
Jun 11 2014
next sibling parent "matovitch" <camille.brugel laposte.net> writes:
If I quote de documentation :

"Any casting of a class reference to a derived class reference is 
done with a runtime check to make sure it really is a downcast. 
null is the result if it isn't. Note: This is equivalent to the 
behavior of the dynamic_cast operator in C++."

I explicitly kept track of the derived type as template parameter 
so that the cast could be performed statically (this is absurd 
:P).
Jun 11 2014
prev sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wed, 11 Jun 2014 23:01:31 +0000
matovitch via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 About alias working with identifier but not with (runtime)
 expression. Alias should work with compile time expression like
 map!(x=>2*x) right ? So a static cast should work isn't it ?
 (though static_cast doesn't exist in D :/)
alias is for _symbols_, not expressions. http://dlang.org/declaration.html#alias I really don't think that what you're trying to do is going to work. - Jonathan M Davis
Jun 11 2014
prev sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 11 June 2014 at 18:07:44 UTC, matovitch wrote:
 source/app.d(5): Error: basic type expected, not cast
 source/app.d(5): Error: no identifier for declarator int
 source/app.d(5): Error: semicolon expected to close alias 
 declaration
 source/app.d(5): Error: Declaration expected, not 'cast'
 Error: DMD compile run failed with exit code 1
This particular error stems from the fact that you can only define `alias this` to a symbol, but you are using a cast, which is an expression. For this, a helper function is required: class A(Derived) { auto castHelper() { return (cast(Derived) this).x; } } (Note that you also need to remove the `ref` inside the cast, because classes are already reference types, and the `ref` would mean a reference to a reference.) But this still doesn't work, as then the compiler crashes while it tries to do the cast, iff the alias this is there. This works: import std.stdio; class A(Derived) { auto castHelper() { return (cast(Derived) this).x; } //alias castHelper this; } class B : A!B { float x; } class C : A!C { int x; } void main() { auto b = new B; b.x = 0.5; auto c = new C; c.x = 42; float f = b.castHelper; writeln("b = ", f); int i = c.castHelper; writeln("c = ", i); } But if you enable the `alias this` line, it segfaults. You don't even need to reduce the calls to `castHelper` in the main function, it evidently doesn't get that far.
Jun 11 2014