Thread overview
What's the rationale here? alias this and function arguments
Mar 10, 2015
John Colvin
Mar 10, 2015
ketmar
Mar 10, 2015
John Colvin
Mar 10, 2015
Baz
March 10, 2015
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?
March 10, 2015
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")`?

so compiler doesn't try to guess how to convert your function argument from valid constructor args to structs. this decreases the change to introduce a hard-to-detect bugs with implicit construction, and also increases the readability (imagine surprised reader that sees `bar("3")` 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 it's not a compiler work to guess what you meant.

March 10, 2015
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)```
March 10, 2015
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