www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - std.typecons wrap interface with NVI

reply "Matthew Dudley" <pontifechs gmail.com> writes:
This is the general outline of what I'm trying to do:



import std.typecons; //wrap

import std.stdio;


interface FooBar
{
public:
	void foo();
	void bar();

	final void both() // NVI
		{
			foo();
			bar();
		}
}

class Baz
{
public:
	void foo() { writeln("foo"); }
	void bar() { writeln("bar"); }
}

void main()
{
	auto baz = new Baz();
	auto foobar = baz.wrap!(FooBar)();
	// causes this wall-o-text error -- http://pastebin.com/Pa5dHQtN
	// Which at the end says:

	// /usr/local/Cellar/dmd/2.064.2/import/std/typecons.d(2779): 
Error: static assert  "Source Baz does not have structural 
conformance to (FooBar)"

}


I'm still learning D, but this seems like it should work. If I 
explicitly implement FooBar in Baz, everything's groovy, but this 
isn't. Is this a bug in wrap or am I misunderstanding the 
intention of wrap or NVI?

Also as a side note, if I use an abstract class instead of an 
interface, things explode in similarly large wall-o-text fashion. 
Is there a reason for abstract classes aren't or can't be used 
for wrap?
Feb 01 2014
next sibling parent reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
On Sunday, 2 February 2014 at 01:19:22 UTC, Matthew Dudley wrote:
 This is the general outline of what I'm trying to do:



 import std.typecons; //wrap

 import std.stdio;


 interface FooBar
 {
 public:
 	void foo();
 	void bar();

 	final void both() // NVI
 		{
 			foo();
 			bar();
 		}
 }

 class Baz
 {
 public:
 	void foo() { writeln("foo"); }
 	void bar() { writeln("bar"); }
 }

 void main()
 {
 	auto baz = new Baz();
 	auto foobar = baz.wrap!(FooBar)();
 	// causes this wall-o-text error -- 
 http://pastebin.com/Pa5dHQtN
 	// Which at the end says:

 	// /usr/local/Cellar/dmd/2.064.2/import/std/typecons.d(2779): 
 Error: static assert  "Source Baz does not have structural 
 conformance to (FooBar)"

 }
 I'm still learning D, but this seems like it should work. If I 
 explicitly implement FooBar in Baz, everything's groovy, but 
 this isn't. Is this a bug in wrap or am I misunderstanding the 
 intention of wrap or NVI?
You are getting the point of NVI i think, that part is correct. I don't know why NVI dosn't work together with wrapping but i would assume it is a bug. Conseptually NVI does not change the behavior of the wrapped object so it shouldn't be a problem. (Abstract classes are a problem here though see below). As far as wrap goes i am not sure what the intention behind it is. It would be a cool feature if it allowed wrapping of structs but... it dosn't. It could have some use in avoiding the need of writing adapter classes for code you can't change but other then that it should imho be avoided. Templates and interface inheritance in general makes the feature unessasary.
 Also as a side note, if I use an abstract class instead of an 
 interface, things explode in similarly large wall-o-text 
 fashion. Is there a reason for abstract classes aren't or can't 
 be used for wrap?
class FooBar { abstract void foo(); void bar() { writeln("Hello from FooBar.bar"); } } class Baz { void foo() { writeln("Hello from Baz.foo"); } voir bar() { writeln("Hello from Baz.bar"); } } void main() { auto baz = new Baz(); baz.bar(); auto wrapped = baz.wrap!(FooBar); wrapped.bar(); //Which bar should be called? } Wrapping a type into an interface should not change the behaviour of the wrapped types operations. In the example above what would the wrapped.bar() call do? Would it call bar in FooBar? or bar in Baz? maby both? There is no clear defined rule of what to do here. I'm guessing this is why they decided to not support implementation wrapping. (Note it could have been defined but it's not.) Also wrapping does try to simulate how Go does duck typing and there is no inheritance there so i'm guessing that was a factor in the design.
Feb 01 2014
parent reply "Dicebot" <public dicebot.lv> writes:
`wrap` has relatively simple meaning: for any interface I and 
class C it generates class C' inheriting I and implementing all 
methods of I in terms of forwarding calls to methods of C with 
same name and signature.

What does happen here is that `wrap` was not implemented with NVI 
in mind and tries to override `both` in C' which, of course, 
can't work.

File an enhancement request for `wrap` to become aware of NVI.
Feb 02 2014
parent "Matthew Dudley" <pontifechs gmail.com> writes:
On Sunday, 2 February 2014 at 11:07:41 UTC, Dicebot wrote:
 `wrap` has relatively simple meaning: for any interface I and 
 class C it generates class C' inheriting I and implementing all 
 methods of I in terms of forwarding calls to methods of C with 
 same name and signature.

 What does happen here is that `wrap` was not implemented with 
 NVI in mind and tries to override `both` in C' which, of 
 course, can't work.

 File an enhancement request for `wrap` to become aware of NVI.
That's kinda what I suspected was happening. I've added it to bugzilla: https://d.puremagic.com/issues/show_bug.cgi?id=12064 Thanks guys
Feb 02 2014
prev sibling parent "Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
On Sunday, 2 February 2014 at 01:19:22 UTC, Matthew Dudley wrote:
 This is the general outline of what I'm trying to do:



 import std.typecons; //wrap

 import std.stdio;


 interface FooBar
 {
 public:
 	void foo();
 	void bar();

 	final void both() // NVI
 		{
 			foo();
 			bar();
 		}
 }
It seems that wrap is expecting your type to implement both(). I think this should be considered a bug and placed in bugzilla. On another note: import std.typecons: wrap;
Feb 01 2014