www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - OpEquals and Interfaces

reply Christoph Mueller <ruunhb googlemail.com> writes:
I'm currently writing a library in D2 which uses intensively interfaces 
and i meet a problem by overloading the opEquals Operator.

In some of my implementations i want to compare an object through an 
interface of another instance

Unfortanetly, the opEquals Operator uses only Object parameters and 
according to the current DMD-Compiler it's not possible to cast implicit 
an Interface to an Object. (Got a nice compiler error)

Is there any reason to forbid implicit downcasting from any interface to 
Object?

Of course, explicit downcasting cast(Object) is also possible, but 
casting everytime for == operator is not really nice.

Chris


-- 
ruunhb [AT] googlemail.com
http://www.ruuns.de/blog
Apr 13 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 15:50:36 -0400, Christoph Mueller  
<ruunhb googlemail.com> wrote:

 I'm currently writing a library in D2 which uses intensively interfaces  
 and i meet a problem by overloading the opEquals Operator.

 In some of my implementations i want to compare an object through an  
 interface of another instance

 Unfortanetly, the opEquals Operator uses only Object parameters and  
 according to the current DMD-Compiler it's not possible to cast implicit  
 an Interface to an Object. (Got a nice compiler error)

 Is there any reason to forbid implicit downcasting from any interface to  
 Object?

Any good reason? No. But the stated reason is usually that interfaces don't necessarily have to be Objects, they can be COM objects, which 1) has no bearing in some OSes, and 2) does anyone use this feature?
 Of course, explicit downcasting cast(Object) is also possible, but  
 casting everytime for == operator is not really nice.

If you are using D2, there is a workaround: interface I { final bool opEquals(I other) { Object me = cast(Object)this; Object they = cast(Object)other; return equals(me, they); } } But it would be nice if the compiler did this automatically. There are other things that suck because interfaces are not assumed to be derived from Object. I think the whole COM interface hack needs to be revisited. -Steve
Apr 13 2010
next sibling parent Christoph Mueller <ruunhb googlemail.com> writes:
 If you are using D2, there is a workaround:

 interface I
 {
 final bool opEquals(I other)
 {
 Object me = cast(Object)this;
 Object they = cast(Object)other;
 return equals(me, they);
 }
 }

 But it would be nice if the compiler did this automatically. There are
 other things that suck because interfaces are not assumed to be derived
 from Object.

What kind of things also doesn't work relating to interfaces and Object ? -- ruunhb [AT] googlemail.com http://www.ruuns.de/blog
Apr 13 2010
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
Christoph Mueller is asking the exact problem that I've been having. :)

Steven Schveighoffer wrote:

 If you are using D2, there is a workaround:

 interface I
 {
    final bool opEquals(I other)
    {
       Object me = cast(Object)this;
       Object they = cast(Object)other;
       return equals(me, they);

Is 'equals' a function on this interface?
    }
 }

I could not make that work. The compiler is still trying to call Object.opEquals. At the risk of turning this forum to D.learn, I tried to have an explicit 'equals' member function on the interface and use that. This is what I have: import object; interface I { final bool opEquals(I other) { return equals(cast(Object)other); } bool equals(Object o); } class C : I { override bool opEquals(Object o) const { return true; } bool equals(Object o) { return this == o; } } void main() { I i = new C; i == i; // <-- Error line } But it still calls Object.opEquals: Error: function object.opEquals (Object lhs, Object rhs) is not callable using argument types (I,I) Error: cannot implicitly convert expression (i) of type deneme.I to object.Object Error: cannot implicitly convert expression (i) of type deneme.I to object.Object Ali
Apr 13 2010
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Steven Schveighoffer Wrote:

 Any good reason? No.
 
 But the stated reason is usually that interfaces don't necessarily have to  
 be Objects, they can be COM objects, which 1) has no bearing in some OSes,  
 and 2) does anyone use this feature?

Which feature? Interfaces? COM? upcasting? or opEquals? I don't use opEquals. :3
Apr 13 2010
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Steven Schveighoffer Wrote:

 On Tue, 13 Apr 2010 15:50:36 -0400, Christoph Mueller  
 <ruunhb googlemail.com> wrote:
 
 I'm currently writing a library in D2 which uses intensively interfaces  
 and i meet a problem by overloading the opEquals Operator.

 In some of my implementations i want to compare an object through an  
 interface of another instance

 Unfortanetly, the opEquals Operator uses only Object parameters and  
 according to the current DMD-Compiler it's not possible to cast implicit  
 an Interface to an Object. (Got a nice compiler error)

 Is there any reason to forbid implicit downcasting from any interface to  
 Object?

Any good reason? No. But the stated reason is usually that interfaces don't necessarily have to be Objects, they can be COM objects, which 1) has no bearing in some OSes, and 2) does anyone use this feature?

It could also be a C++ class
Apr 13 2010
next sibling parent reply Don <nospam nospam.com> writes:
Steven Schveighoffer wrote:
 On Tue, 13 Apr 2010 19:47:13 -0400, Jason House 
 <jason.james.house gmail.com> wrote:
 
 Steven Schveighoffer Wrote:

 On Tue, 13 Apr 2010 15:50:36 -0400, Christoph Mueller
 <ruunhb googlemail.com> wrote:

 I'm currently writing a library in D2 which uses intensively 

 and i meet a problem by overloading the opEquals Operator.

 In some of my implementations i want to compare an object through an
 interface of another instance

 Unfortanetly, the opEquals Operator uses only Object parameters and
 according to the current DMD-Compiler it's not possible to cast 

 an Interface to an Object. (Got a nice compiler error)

 Is there any reason to forbid implicit downcasting from any 

 Object?

Any good reason? No. But the stated reason is usually that interfaces don't necessarily have to be Objects, they can be COM objects, which 1) has no bearing in some OSes, and 2) does anyone use this feature?

It could also be a C++ class

C++ classes are already tagged with extern(C++) (i.e. there's a difference the compiler can grip to make it behave differently) Maybe that's the solution, make COM solutions extern(COM), or COM or something. That's fine also. Anything to then allow the compiler to assume unadorned interfaces are D objects. -Steve

I think we can just use extern(C++).
Apr 14 2010
parent reply Kagamin <spam here.lot> writes:
Steven Schveighoffer Wrote:

 Walter, can you confirm that extern(C++) interfaces are equivalent to  
 inheriting IUnknown?  If not, what are the differences?

The difference is COM ABI is standardized, C++ ABI is implementation-defined. If you are lucky, you can guess, which ABI is meant by extern(C++).
Apr 14 2010
parent reply Don <nospam nospam.com> writes:
Kagamin wrote:
 Steven Schveighoffer Wrote:
 
 Walter, can you confirm that extern(C++) interfaces are equivalent to  
 inheriting IUnknown?  If not, what are the differences?

The difference is COM ABI is standardized, C++ ABI is implementation-defined. If you are lucky, you can guess, which ABI is meant by extern(C++).

Well, yes, but C++ itself doesn't have interfaces. A COM interface is basically a MSVC virtual function table. Windows C++ compilers which support it, follow the Microsoft calling conventions, even if they use a different ABI for other classes. The only problem would be if C++ subsequently defined interfaces (in C++1x) and they were different. I think that's extremely unlikely, since MSVC defines __interface to be a COM interface. Note that extern(C++) is much more recent than the COM interface hack.
Apr 14 2010
parent reply Kagamin <spam here.lot> writes:
Don Wrote:

 I think that's extremely unlikely, since 
 MSVC defines __interface to be a COM interface.

It defines interface to be a C++ abstract class.
Apr 14 2010
parent reply Don <nospam nospam.com> writes:
Kagamin wrote:
 Don Wrote:
 
 I think that's extremely unlikely, since 
 MSVC defines __interface to be a COM interface.

It defines interface to be a C++ abstract class.

Yeah, OK, __interface is slightly broader, it's a superset of COM interfaces. But, all COM interfaces are C++ abstract classes. So, if we required extern(C++) in order to make it a COM interface, we'd be fine. Then we'd have the rule: all interfaces are derived from Object, unless they are extern(C++).
Apr 15 2010
next sibling parent reply Kagamin <spam here.lot> writes:
Don Wrote:

 Then we'd have the rule: all interfaces are derived from Object, unless 
 they are extern(C++).

So all COM methods will be required to be declared extern(System)? Won't this clash with extern function declaration?
Apr 15 2010
parent reply Don <nospam nospam.com> writes:
Kagamin wrote:
 Don Wrote:
 
 Then we'd have the rule: all interfaces are derived from Object, unless 
 they are extern(C++).

So all COM methods will be required to be declared extern(System)? Won't this clash with extern function declaration?

They have to use Windows calling conventions anyway.
Apr 15 2010
parent Kagamin <spam here.lot> writes:
Don Wrote:

 So all COM methods will be required to be declared extern(System)? Won't this
clash with extern function declaration?

They have to use Windows calling conventions anyway.

Yes, but we already have C++ in-place constructor clash with function declarations. Like MyClass inst(1,2);
Apr 15 2010
prev sibling parent Kagamin <spam here.lot> writes:
Don Wrote:

 Then we'd have the rule: all interfaces are derived from Object, unless 
 they are extern(C++).

I'd propose rule "all extern(D) interfaces are implemented by objects derived from Object", which is everything pure D type system needs, while allowing extensions.
Apr 15 2010
prev sibling parent Kagamin <spam here.lot> writes:
Steven Schveighoffer Wrote:

 Maybe that's the solution, make COM solutions extern(COM), or  COM or  
 something.  That's fine also.

Apr 14 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 18:04:04 -0400, Ali Çehreli <acehreli yahoo.com> wrote:

 Christoph Mueller is asking the exact problem that I've been having. :)

 Steven Schveighoffer wrote:

  > If you are using D2, there is a workaround:
  >
  > interface I
  > {
  >    final bool opEquals(I other)
  >    {
  >       Object me = cast(Object)this;
  >       Object they = cast(Object)other;
  >       return equals(me, they);

 Is 'equals' a function on this interface?

No, it's a new global function in object.di, and it's called opEquals, not equals. I guess I messed that up royally :) Just do me == they; That will call the function.
 But it still calls Object.opEquals:

 Error: function object.opEquals (Object lhs, Object rhs) is not callable  
 using argument types (I,I)

This is not Object.opEquals, it's object.opEquals -- note the capitalization. The latter is a standalone function in module object.
 Error: cannot implicitly convert expression (i) of type deneme.I to  
 object.Object
 Error: cannot implicitly convert expression (i) of type deneme.I to  
 object.Object

This is a bug. i == i should call the opEquals method on i. Instead, the compiler is trying to call the standalone opEquals(Object, Object) function. I confirmed with 2.043 that this is a bug. I'll file with a test case. -Steve
Apr 13 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 18:14:55 -0400, Kagamin <spam here.lot> wrote:

 Steven Schveighoffer Wrote:

 Any good reason? No.

 But the stated reason is usually that interfaces don't necessarily have  
 to
 be Objects, they can be COM objects, which 1) has no bearing in some  
 OSes,
 and 2) does anyone use this feature?

Which feature? Interfaces? COM? upcasting? or opEquals? I don't use opEquals. :3

COM via D interfaces. -Steve
Apr 13 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 17:27:20 -0400, Christoph Mueller  
<ruunhb googlemail.com> wrote:

 If you are using D2, there is a workaround:

 interface I
 {
 final bool opEquals(I other)
 {
 Object me = cast(Object)this;
 Object they = cast(Object)other;
 return equals(me, they);
 }
 }

 But it would be nice if the compiler did this automatically. There are
 other things that suck because interfaces are not assumed to be derived
 from Object.

What kind of things also doesn't work relating to interfaces and Object ?

Any base method of Object -- opCmp, toHash, or simply passing an interface to a function that accepts an Object. There are others, but I can't think of them right now. -Steve
Apr 13 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 19:16:21 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Tue, 13 Apr 2010 17:27:20 -0400, Christoph Mueller  
 <ruunhb googlemail.com> wrote:

 If you are using D2, there is a workaround:

 interface I
 {
 final bool opEquals(I other)
 {
 Object me = cast(Object)this;
 Object they = cast(Object)other;
 return equals(me, they);
 }
 }

 But it would be nice if the compiler did this automatically. There are
 other things that suck because interfaces are not assumed to be derived
 from Object.

What kind of things also doesn't work relating to interfaces and Object ?

Any base method of Object -- opCmp, toHash, or simply passing an interface to a function that accepts an Object.

Add toString to that, that's a biggie... -Steve
Apr 13 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 19:13:31 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:


 I confirmed with 2.043 that this is a bug.  I'll file with a test case.

http://d.puremagic.com/issues/show_bug.cgi?id=4088
Apr 13 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 13 Apr 2010 19:47:13 -0400, Jason House  
<jason.james.house gmail.com> wrote:

 Steven Schveighoffer Wrote:

 On Tue, 13 Apr 2010 15:50:36 -0400, Christoph Mueller
 <ruunhb googlemail.com> wrote:

 I'm currently writing a library in D2 which uses intensively  

 and i meet a problem by overloading the opEquals Operator.

 In some of my implementations i want to compare an object through an
 interface of another instance

 Unfortanetly, the opEquals Operator uses only Object parameters and
 according to the current DMD-Compiler it's not possible to cast  

 an Interface to an Object. (Got a nice compiler error)

 Is there any reason to forbid implicit downcasting from any interface  

 Object?

Any good reason? No. But the stated reason is usually that interfaces don't necessarily have to be Objects, they can be COM objects, which 1) has no bearing in some OSes, and 2) does anyone use this feature?

It could also be a C++ class

C++ classes are already tagged with extern(C++) (i.e. there's a difference the compiler can grip to make it behave differently) Maybe that's the solution, make COM solutions extern(COM), or COM or something. That's fine also. Anything to then allow the compiler to assume unadorned interfaces are D objects. -Steve
Apr 13 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 14 Apr 2010 07:29:28 -0400, Don <nospam nospam.com> wrote:

 Steven Schveighoffer wrote:
 On Tue, 13 Apr 2010 19:47:13 -0400, Jason House  
 <jason.james.house gmail.com> wrote:

 Steven Schveighoffer Wrote:

 On Tue, 13 Apr 2010 15:50:36 -0400, Christoph Mueller
 <ruunhb googlemail.com> wrote:

 I'm currently writing a library in D2 which uses intensively  

 and i meet a problem by overloading the opEquals Operator.

 In some of my implementations i want to compare an object through an
 interface of another instance

 Unfortanetly, the opEquals Operator uses only Object parameters and
 according to the current DMD-Compiler it's not possible to cast  

 an Interface to an Object. (Got a nice compiler error)

 Is there any reason to forbid implicit downcasting from any  

 Object?

Any good reason? No. But the stated reason is usually that interfaces don't necessarily have to be Objects, they can be COM objects, which 1) has no bearing in some OSes, and 2) does anyone use this feature?

It could also be a C++ class

difference the compiler can grip to make it behave differently) Maybe that's the solution, make COM solutions extern(COM), or COM or something. That's fine also. Anything to then allow the compiler to assume unadorned interfaces are D objects. -Steve

I think we can just use extern(C++).

If this is true, this is a no brainer! This shows my ignorance of COM or why IUnknown is a special interface :) If it's just because it's a C++ interface, then yeah, let's set that up. searching for D's explanation of how COM interfaces work I found this really helpful page :P http://www.digitalmars.com/d/2.0/COM.html Walter, can you confirm that extern(C++) interfaces are equivalent to inheriting IUnknown? If not, what are the differences? -Steve
Apr 14 2010