www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Problem of undefined behaviour with overloaded methods and overloaded

reply knex <cqgblxlzym xhfiukczcf.com> writes:
I came across a strange thing and I am not sure if this is a bug 
or just an undefined behaviour of a compiler. Here is some sample 
code to present the case:

//

alias BoolFirst = void delegate(bool b, string s);
alias StringFirst = void delegate(string s, bool b);

class Caller {
     void call(BoolFirst bs) { bs(true, "text"); }
     void call(StringFirst sb) { sb("text", true); }
}

class Writer {
     import std.stdio;
     void write(bool b, string s) { writeln("bool+string:", b, 
"/", s); }
     void write(string s, bool b) { writeln("string+bool:", s, 
"/", b); }
}

void main() {
     new Caller().call(&new Writer().write);
}

//

As you can see, I have two classes, both having two overloaded 
methods. Writer has some dummy printing methods for bool and 
string, differing with the order of the arguments, while Caller 
takes one of these methods as a delegate and invokes it. In 
main() I create objects of these classes and call Caller's call() 
with Writer's write().

But - as far as I understand - this call is ambiguous, and 
compiler does not know what should be done here: calling 
call/write pair for bool+string or for string+bool parameters. 
Nevertheless the code compiles and the program runs the fist 
variant. The funny thing is that swapping write() methods in the 
source file causes calling the second one. But OK, suppose that 
this is and should be treated as an undefined behaviour. What is 
actually disturbing here, is that casting like 
c.call(cast(BoolFirst) &w.write) compiles, although is not 
necessary, because not casting works the same way, but casting 
c.call(cast(StringFirst) &w.write) - which should help here in 
calling string+bool variant - does not compile, and the compiler 
says that "Caller.call called with argument types (void 
delegate(string s, bool b)) matches both (...)", which is clearly 
true. Moreover, swapping write() methods again causes the exact 
opposite behaviour: cast(StringFirst) compiles, but is useless, 
and cast(BoolFirst) does not compile at all.

So, is this a bug, or am I just not getting something? In the 
first case, is there some kind of a workaround for the 
possibility of calling both variants (without changing the code 
of Caller and Writer classes)? In the last case, how should I do 
it properly?

I am using DMD32 D Compiler v2.075.0 on Linux.
Aug 01 2017
next sibling parent knex <cqgblxlzym xhfiukczcf.com> writes:
Erratum:
which is clearly true ---> which is clearly untrue
Aug 01 2017
prev sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Tuesday, 1 August 2017 at 11:07:59 UTC, knex wrote:
 I came across a strange thing and I am not sure if this is a 
 bug or just an undefined behaviour of a compiler. Here is some 
 sample code to present the case:

 //

 alias BoolFirst = void delegate(bool b, string s);
 alias StringFirst = void delegate(string s, bool b);

 class Caller {
     void call(BoolFirst bs) { bs(true, "text"); }
     void call(StringFirst sb) { sb("text", true); }
 }

 class Writer {
     import std.stdio;
     void write(bool b, string s) { writeln("bool+string:", b, 
 "/", s); }
     void write(string s, bool b) { writeln("string+bool:", s, 
 "/", b); }
 }

 void main() {
     new Caller().call(&new Writer().write);
 }

 //

 As you can see, I have two classes, both having two overloaded 
 methods. Writer has some dummy printing methods for bool and 
 string, differing with the order of the arguments, while Caller 
 takes one of these methods as a delegate and invokes it. In 
 main() I create objects of these classes and call Caller's 
 call() with Writer's write().

 But - as far as I understand - this call is ambiguous, and 
 compiler does not know what should be done here: calling 
 call/write pair for bool+string or for string+bool parameters. 
 Nevertheless the code compiles and the program runs the fist 
 variant. The funny thing is that swapping write() methods in 
 the source file causes calling the second one. But OK, suppose 
 that this is and should be treated as an undefined behaviour. 
 What is actually disturbing here, is that casting like 
 c.call(cast(BoolFirst) &w.write) compiles, although is not 
 necessary, because not casting works the same way, but casting 
 c.call(cast(StringFirst) &w.write) - which should help here in 
 calling string+bool variant - does not compile, and the 
 compiler says that "Caller.call called with argument types 
 (void delegate(string s, bool b)) matches both (...)", which is 
 clearly true. Moreover, swapping write() methods again causes 
 the exact opposite behaviour: cast(StringFirst) compiles, but 
 is useless, and cast(BoolFirst) does not compile at all.

 So, is this a bug, or am I just not getting something? In the 
 first case, is there some kind of a workaround for the 
 possibility of calling both variants (without changing the code 
 of Caller and Writer classes)? In the last case, how should I 
 do it properly?

 I am using DMD32 D Compiler v2.075.0 on Linux.
looks like a bug to me. Please report at issues.dlang.org
Aug 01 2017
parent knex <cqgblxlzym xhfiukczcf.com> writes:
On Tuesday, 1 August 2017 at 11:30:07 UTC, John Colvin wrote:
 looks like a bug to me. Please report at issues.dlang.org
Let it be, then. Reported at https://issues.dlang.org/show_bug.cgi?id=17710
Aug 02 2017