std.typecons wrap interface with NVI

TheFlyingFiddle theflyingfiddle at gmail.com
Sat Feb 1 22:36:27 PST 2014


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.


More information about the Digitalmars-d-learn mailing list