www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Linker errors with Interfaces

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Excerpt from TDPL, p213-214:

interface Transmogrifier
{
    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }
    
    // implementation interface
private:
    void transmogrify();     
    void untransmogrify(); 
}

class CardboardBox : Transmogrifier
{
    override private void transmogrify()
    {
        // get in the box
    }
    
    override private void untransmogrify()
    {
        // get out of the box
    }
}

void play()
{
    writeln("just playing");
}

void aDayInLife(Transmogrifier device, string mood)
{
    if (mood == "play")
    {
        device.transmogrify();
        play();
        writeln(typeid(device));
        device.untransmogrify();
    }
    else if (mood == "experiment")
    {
        device.thereAndBack();
    }
}

import std.stdio;

void main()
{
    aDayInLife(new CardboardBox, "play");
}


Calling device.transmogrify() and device.untransmogrify() should not even be
allowed to compile. I can comment these out, but the linker will still fail
when there's a call to device.thereAndBack(); device is an object that inherits
from interface Transmogrifier, and "thereAndBack()" is a public method of the
interface, so I'm not sure whats wrong with that call.

I get these in both cases:

output\interface_test.obj(interface_test) 
 Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv
output\interface_test.obj(interface_test) 
 Error 42: Symbol Undefined
_D14interface_test14Transmogrifier14untransmogrifyMFZv


One more thing, here's a class that inherits from the same interface, but tries
to make the overriden methods non-private by mistake:
interface Transmogrifier
{

    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }
    
    // implementation interface
private:
    void transmogrify();       
    void untransmogrify();   
}

class CardboardBox : Transmogrifier
{
    override void transmogrify()
    {
        // get in the box
    }
    
    override void untransmogrify()
    {
        // get out of the box
    }
}

I get these errors:
interface_test.d(23): Error: function interface_test.CardboardBox.transmogrify
does not override any function
interface_test.d(28): Error: function
interface_test.CardboardBox.untransmogrify does not override any function

The book has nice plausible error message alternatives:
// Error: Cannot change protection of transmogrify from private to public
// Error: Cannot change protection of untransmogrify from private to public

I'd prefer if DMD put out those kinds of error messages in this case (or
something similar).
Aug 10 2010
next sibling parent Igor Lesik <curoles yahoo.com> writes:
I think, it is not linker error at all.
"private" in Transmogrifier prevents overriding; and since those 2 functions
are 
not
defined but still in use (vtbl) linker does not find them and complains.
Replace "private" with protected (in CardboardBox also) and it all works.

compiler should say that the functions are not overrided; I am sure a bug report
already filed for this issue

Igor

From: Andrej Mitrovic
Subject: Linker errors with Interfaces

Excerpt from TDPL, p213-214:

interface Transmogrifier
{
    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }
    
    // implementation interface
private:
    void transmogrify();    
    void untransmogrify(); 
}

class CardboardBox : Transmogrifier
{
    override private void transmogrify()
    {
        // get in the box
    }
    
    override private void untransmogrify()
    {
        // get out of the box
    }
}

void play()
{
    writeln("just playing");
}

void aDayInLife(Transmogrifier device, string mood)
{
    if (mood == "play")
    {
        device.transmogrify();
        play();
        writeln(typeid(device));
        device.untransmogrify();
    }
    else if (mood == "experiment")
    {
        device.thereAndBack();
    }
}

import std.stdio;

void main()
{
    aDayInLife(new CardboardBox, "play");
}


Calling device.transmogrify() and device.untransmogrify() should not even be 
allowed to compile. I can comment these out, but the linker will still fail
when 

there's a call to device.thereAndBack(); device is an object that inherits from 
interface Transmogrifier, and "thereAndBack()" is a public method of the 
interface, so I'm not sure whats wrong with that call.

I get these in both cases:

output\interface_test.obj(interface_test) 
Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv
output\interface_test.obj(interface_test) 
Error 42: Symbol Undefined 
_D14interface_test14Transmogrifier14untransmogrifyMFZv


One more thing, here's a class that inherits from the same interface, but tries 
to make the overriden methods non-private by mistake:
interface Transmogrifier
{

    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }
    
    // implementation interface
private:
    void transmogrify();      
    void untransmogrify();  
}

class CardboardBox : Transmogrifier
{
    override void transmogrify()
    {
        // get in the box
    }
    
    override void untransmogrify()
    {
        // get out of the box
    }
}

I get these errors:
interface_test.d(23): Error: function interface_test.CardboardBox.transmogrify 
does not override any function
interface_test.d(28): Error: function
interface_test.CardboardBox.untransmogrify 

does not override any function

The book has nice plausible error message alternatives:
// Error: Cannot change protection of transmogrify from private to public
// Error: Cannot change protection of untransmogrify from private to public

I'd prefer if DMD put out those kinds of error messages in this case (or 
something similar).



      
Aug 10 2010
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--000e0cd594d2464992048d8b7307
Content-Type: text/plain; charset=ISO-8859-1

Private does not prevent overriding, final prevents overriding. Private
prevents the methods from being explicitly called from either user code or
any derived classes.

On Wed, Aug 11, 2010 at 8:08 AM, Igor Lesik <curoles yahoo.com> wrote:

 I think, it is not linker error at all.
 "private" in Transmogrifier prevents overriding; and since those 2
 functions are
 not
 defined but still in use (vtbl) linker does not find them and complains.
 Replace "private" with protected (in CardboardBox also) and it all works.

 compiler should say that the functions are not overrided; I am sure a bug
 report
 already filed for this issue

 Igor

 From: Andrej Mitrovic
 Subject: Linker errors with Interfaces

 Excerpt from TDPL, p213-214:

 interface Transmogrifier
 {
    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }

    // implementation interface
 private:
    void transmogrify();
    void untransmogrify();
 }

 class CardboardBox : Transmogrifier
 {
    override private void transmogrify()
    {
        // get in the box
    }

    override private void untransmogrify()
    {
        // get out of the box
    }
 }

 void play()
 {
    writeln("just playing");
 }

 void aDayInLife(Transmogrifier device, string mood)
 {
    if (mood == "play")
    {
        device.transmogrify();
        play();
        writeln(typeid(device));
        device.untransmogrify();
    }
    else if (mood == "experiment")
    {
        device.thereAndBack();
    }
 }

 import std.stdio;

 void main()
 {
    aDayInLife(new CardboardBox, "play");
 }


 Calling device.transmogrify() and device.untransmogrify() should not even
 be
 allowed to compile. I can comment these out, but the linker will still fail
 when

 there's a call to device.thereAndBack(); device is an object that inherits
 from
 interface Transmogrifier, and "thereAndBack()" is a public method of the
 interface, so I'm not sure whats wrong with that call.

 I get these in both cases:

 output\interface_test.obj(interface_test)
 Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier12transmogrifyMFZv
 output\interface_test.obj(interface_test)
 Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier14untransmogrifyMFZv


 One more thing, here's a class that inherits from the same interface, but
 tries
 to make the overriden methods non-private by mistake:
 interface Transmogrifier
 {

    // client interface
    final void thereAndBack()
    {
        transmogrify();
        untransmogrify();
    }

    // implementation interface
 private:
    void transmogrify();
    void untransmogrify();
 }

 class CardboardBox : Transmogrifier
 {
    override void transmogrify()
    {
        // get in the box
    }

    override void untransmogrify()
    {
        // get out of the box
    }
 }

 I get these errors:
 interface_test.d(23): Error: function
 interface_test.CardboardBox.transmogrify
 does not override any function
 interface_test.d(28): Error: function
 interface_test.CardboardBox.untransmogrify

 does not override any function

 The book has nice plausible error message alternatives:
 // Error: Cannot change protection of transmogrify from private to public
 // Error: Cannot change protection of untransmogrify from private to public

 I'd prefer if DMD put out those kinds of error messages in this case (or
 something similar).

--000e0cd594d2464992048d8b7307 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Private does not prevent overriding, final prevents overriding. Private pre= vents the methods from being explicitly called from either user code or any= derived classes.<br><br><div class=3D"gmail_quote">On Wed, Aug 11, 2010 at= 8:08 AM, Igor Lesik <span dir=3D"ltr">&lt;<a href=3D"mailto:curoles yahoo.= com">curoles yahoo.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">I think, it is no= t linker error at all.<br> &quot;private&quot; in Transmogrifier prevents overriding; and since those = 2 functions are<br> not<br> defined but still in use (vtbl) linker does not find them and complains.<br=

l works.<br> <br> compiler should say that the functions are not overrided; I am sure a bug r= eport<br> already filed for this issue<br> <br> Igor<br> <br> From: Andrej Mitrovic<br> Subject: Linker errors with Interfaces<br> <div><div></div><div class=3D"h5"><br> Excerpt from TDPL, p213-214:<br> <br> interface Transmogrifier<br> {<br> =A0 =A0// client interface<br> =A0 =A0final void thereAndBack()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0transmogrify();<br> =A0 =A0 =A0 =A0untransmogrify();<br> =A0 =A0}<br> <br> =A0 =A0// implementation interface<br> private:<br> =A0 =A0void transmogrify();<br> =A0 =A0void untransmogrify();<br> }<br> <br> class CardboardBox : Transmogrifier<br> {<br> =A0 =A0override private void transmogrify()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0// get in the box<br> =A0 =A0}<br> <br> =A0 =A0override private void untransmogrify()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0// get out of the box<br> =A0 =A0}<br> }<br> <br> void play()<br> {<br> =A0 =A0writeln(&quot;just playing&quot;);<br> }<br> <br> void aDayInLife(Transmogrifier device, string mood)<br> {<br> =A0 =A0if (mood =3D=3D &quot;play&quot;)<br> =A0 =A0{<br> =A0 =A0 =A0 =A0device.transmogrify();<br> =A0 =A0 =A0 =A0play();<br> =A0 =A0 =A0 =A0writeln(typeid(device));<br> =A0 =A0 =A0 =A0device.untransmogrify();<br> =A0 =A0}<br> =A0 =A0else if (mood =3D=3D &quot;experiment&quot;)<br> =A0 =A0{<br> =A0 =A0 =A0 =A0device.thereAndBack();<br> =A0 =A0}<br> }<br> <br> import std.stdio;<br> <br> void main()<br> {<br> =A0 =A0aDayInLife(new CardboardBox, &quot;play&quot;);<br> }<br> <br> <br> Calling device.transmogrify() and device.untransmogrify() should not even b= e<br> allowed to compile. I can comment these out, but the linker will still fail= when<br> <br> there&#39;s a call to device.thereAndBack(); device is an object that inher= its from<br> interface Transmogrifier, and &quot;thereAndBack()&quot; is a public method= of the<br> interface, so I&#39;m not sure whats wrong with that call.<br> <br> I get these in both cases:<br> <br> output\interface_test.obj(interface_test)<br> Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrify= MFZv<br> output\interface_test.obj(interface_test)<br> Error 42: Symbol Undefined<br> _D14interface_test14Transmogrifier14untransmogrifyMFZv<br> <br> <br> One more thing, here&#39;s a class that inherits from the same interface, b= ut tries<br> to make the overriden methods non-private by mistake:<br> interface Transmogrifier<br> {<br> <br> =A0 =A0// client interface<br> =A0 =A0final void thereAndBack()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0transmogrify();<br> =A0 =A0 =A0 =A0untransmogrify();<br> =A0 =A0}<br> <br> =A0 =A0// implementation interface<br> private:<br> =A0 =A0void transmogrify();<br> =A0 =A0void untransmogrify();<br> }<br> <br> class CardboardBox : Transmogrifier<br> {<br> =A0 =A0override void transmogrify()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0// get in the box<br> =A0 =A0}<br> <br> =A0 =A0override void untransmogrify()<br> =A0 =A0{<br> =A0 =A0 =A0 =A0// get out of the box<br> =A0 =A0}<br> }<br> <br> I get these errors:<br> interface_test.d(23): Error: function interface_test.CardboardBox.transmogr= ify<br> does not override any function<br> interface_test.d(28): Error: function interface_test.CardboardBox.untransmo= grify<br> <br> does not override any function<br> <br> The book has nice plausible error message alternatives:<br> // Error: Cannot change protection of transmogrify from private to public<b= r> // Error: Cannot change protection of untransmogrify from private to public= <br> <br> I&#39;d prefer if DMD put out those kinds of error messages in this case (o= r<br> something similar).<br> <br> <br> <br> <br> </div></div></blockquote></div><br> --000e0cd594d2464992048d8b7307--
Aug 11 2010
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2010-08-11 08:33:00 -0400, Andrej Mitrovic 
<andrej.mitrovich gmail.com> said:

 Private does not prevent overriding, final prevents overriding. Private
 prevents the methods from being explicitly called from either user code or
 any derived classes.

The D spec says private member functions are not virtual. Not that I agree with it, but it's like this. "All non-static non-private non-template member functions are virtual." <http://www.digitalmars.com/d/2.0/function.html> The worst part of it is that changing a function from private to public, or the reverse, is a breaking ABI change because it affects the vtable. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 11 2010
prev sibling next sibling parent reply Adrian Matoga <epi atari8.info> writes:
 I get these in both cases:
 
 output\interface_test.obj(interface_test) 
  Error 42: Symbol Undefined
_D14interface_test14Transmogrifier12transmogrifyMFZv
 output\interface_test.obj(interface_test) 
  Error 42: Symbol Undefined
_D14interface_test14Transmogrifier14untransmogrifyMFZv

I reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian
Aug 11 2010
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--000e0cd47cd6c6a8f0048d8c8a72
Content-Type: text/plain; charset=ISO-8859-1

Reading from TPDL again, the "final void thereandback()" method in the
interface is what the user code is expected to call. That method calls two
private methods. But it will call the two private methods in the interface,
not the two from the derived class (since private methods are not virtual).
E.g. calling thereandback() explicitly from a derived object will call the
interface method, since it is final, which then calls the private methods
from the interface.

It's like a dead-end here.

On Wed, Aug 11, 2010 at 3:23 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 DMD and TDPL will get in sync one day, I hope.

 2010/8/11 Adrian Matoga <epi atari8.info>

  I get these in both cases:
 output\interface_test.obj(interface_test)  Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier12transmogrifyMFZv
 output\interface_test.obj(interface_test)  Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier14untransmogrifyMFZv

I reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian


--000e0cd47cd6c6a8f0048d8c8a72 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Reading from TPDL again, the &quot;final void thereandback()&quot; method i= n the interface is what the user code is expected to call. That method call= s two private methods. But it will call the two private methods in the inte= rface, not the two from the derived class (since private methods are not vi= rtual). E.g. calling thereandback() explicitly from a derived object will c= all the interface method, since it is final, which then calls the private m= ethods from the interface.<br> <br>It&#39;s like a dead-end here. <br><br><div class=3D"gmail_quote">On We= d, Aug 11, 2010 at 3:23 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href= =3D"mailto:andrej.mitrovich gmail.com">andrej.mitrovich gmail.com</a>&gt;</= span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">DMD and TDPL will= get in sync one day, I hope.<br><br><div class=3D"gmail_quote">2010/8/11 A= drian Matoga <span dir=3D"ltr">&lt;<a href=3D"mailto:epi atari8.info" targe= t=3D"_blank">epi atari8.info</a>&gt;</span><div> <div></div><div class=3D"h5"><br><blockquote class=3D"gmail_quote" style=3D= "margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padd= ing-left: 1ex;"> <div><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; = border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> I get these in both cases:<br> <br> output\interface_test.obj(interface_test) =A0Error 42: Symbol Undefined _D1= 4interface_test14Transmogrifier12transmogrifyMFZv<br> output\interface_test.obj(interface_test) =A0Error 42: Symbol Undefined _D1= 4interface_test14Transmogrifier14untransmogrifyMFZv<br> </blockquote> <br></div> I reported this as a bug a few days ago:<br> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4542" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4542</a><br> <br> I like the NVI idiom and hope this will finally work in future releases.<br=
<font color=3D"#888888">

Adrian<br> </font></blockquote></div></div></div><br> </blockquote></div><br> --000e0cd47cd6c6a8f0048d8c8a72--
Aug 11 2010
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--000e0cd5707a506227048d8c2911
Content-Type: text/plain; charset=ISO-8859-1

DMD and TDPL will get in sync one day, I hope.

2010/8/11 Adrian Matoga <epi atari8.info>

 I get these in both cases:
 output\interface_test.obj(interface_test)  Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier12transmogrifyMFZv
 output\interface_test.obj(interface_test)  Error 42: Symbol Undefined
 _D14interface_test14Transmogrifier14untransmogrifyMFZv

I reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian

--000e0cd5707a506227048d8c2911 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable DMD and TDPL will get in sync one day, I hope.<br><br><div class=3D"gmail_q= uote">2010/8/11 Adrian Matoga <span dir=3D"ltr">&lt;<a href=3D"mailto:epi a= tari8.info">epi atari8.info</a>&gt;</span><br><blockquote class=3D"gmail_qu= ote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 20= 4, 204); padding-left: 1ex;"> <div class=3D"im"><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0p= t 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"=

<br> output\interface_test.obj(interface_test) =A0Error 42: Symbol Undefined _D1= 4interface_test14Transmogrifier12transmogrifyMFZv<br> output\interface_test.obj(interface_test) =A0Error 42: Symbol Undefined _D1= 4interface_test14Transmogrifier14untransmogrifyMFZv<br> </blockquote> <br></div> I reported this as a bug a few days ago:<br> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4542" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4542</a><br> <br> I like the NVI idiom and hope this will finally work in future releases.<br=
<font color=3D"#888888">

Adrian<br> </font></blockquote></div><br> --000e0cd5707a506227048d8c2911--
Aug 11 2010