www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What's the rationale here? alias this and function arguments

reply "John Colvin" <john.loughran.colvin gmail.com> writes:
struct S
{
	int a;
	this(T)(T v)
	{
		this = v;
	}
	void foo(T)(T v)
	{
		import std.conv : to;
		a = v.to!int;
	}
	alias foo this;
}

void bar(S s){}

void main()
{
	S s0;
	s0 = "3"; //OK
	S s = "3"; //OK
	bar("3"); //Not OK
}

It would seem logical that the last one would work as well. 
What's the reasoning behind this?
Mar 10 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tue, 10 Mar 2015 10:27:13 +0000, John Colvin wrote:

 struct S {
 	int a;
 	this(T)(T v)
 	{
 		this =3D v;
 	}
 	void foo(T)(T v) {
 		import std.conv : to;
 		a =3D v.to!int;
 	}
 	alias foo this;
 }
=20
 void bar(S s){}
=20
 void main()
 {
 	S s0;
 	s0 =3D "3"; //OK S s =3D "3"; //OK bar("3"); //Not OK
 }
=20
 It would seem logical that the last one would work as well.
 What's the reasoning behind this?
autoconversion for function arguments can lead to bug-ridden code, and is=20 a perfect way to disaster. besides, it's ambiguous. let's imagine that we=20 have struct `S1`, which can be created from string too, and overload of=20 `bar` as `void bar (S1 s)`. what `bar` compiler should choose for `bar ("3")`? so compiler doesn't try to guess how to convert your function argument=20 from valid constructor args to structs. this decreases the change to=20 introduce a hard-to-detect bugs with implicit construction, and also=20 increases the readability (imagine surprised reader that sees `bar("3")`=20 in the code, but no `bar` overload that accepts string). C++ tries to be "smart" here, and fails. D doesn't try to be smart, as=20 it's not a compiler work to guess what you meant.=
Mar 10 2015
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 10 March 2015 at 10:36:21 UTC, ketmar wrote:
 On Tue, 10 Mar 2015 10:27:13 +0000, John Colvin wrote:

 struct S {
 	int a;
 	this(T)(T v)
 	{
 		this = v;
 	}
 	void foo(T)(T v) {
 		import std.conv : to;
 		a = v.to!int;
 	}
 	alias foo this;
 }
 
 void bar(S s){}
 
 void main()
 {
 	S s0;
 	s0 = "3"; //OK S s = "3"; //OK bar("3"); //Not OK
 }
 
 It would seem logical that the last one would work as well.
 What's the reasoning behind this?
autoconversion for function arguments can lead to bug-ridden code, and is a perfect way to disaster. besides, it's ambiguous. let's imagine that we have struct `S1`, which can be created from string too, and overload of `bar` as `void bar (S1 s)`. what `bar` compiler should choose for `bar ("3")`?
Ah yep, overloading, that was it. I have the feeling i've asked this before and someone else explained it to me but I had forgotten. Cheers
Mar 10 2015
prev sibling parent "Baz" <bb.temp gmx.com> writes:
On Tuesday, 10 March 2015 at 10:27:14 UTC, John Colvin wrote:
 struct S
 {
 	int a;
 	this(T)(T v)
 	{
 		this = v;
 	}
 	void foo(T)(T v)
 	{
 		import std.conv : to;
 		a = v.to!int;
 	}
 	alias foo this;
 }

 void bar(S s){}

 void main()
 {
 	S s0;
 	s0 = "3"; //OK
 	S s = "3"; //OK
 	bar("3"); //Not OK
 }

 It would seem logical that the last one would work as well. 
 What's the reasoning behind this?
Do you think that the parameter should be automatically created from the argument ? Is this kind of thing even possible in another context ? Your alias looks more like an ```opCall()```. To my eyes the strange thing is that if you add the following statement at the end of you sample: --- s(0); --- DMD outputs: ```Error: cannot resolve type for s.foo(T)(T v)```
Mar 10 2015