Jump to page: 1 2
Thread overview
return type and templates
Nov 22, 2013
Andrea Fontana
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
bearophile
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Andrea Fontana
Nov 22, 2013
Andrea Fontana
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Timon Gehr
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Andrea Fontana
Nov 22, 2013
Timon Gehr
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Andrea Fontana
Nov 22, 2013
Dicebot
Nov 22, 2013
Timon Gehr
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Timon Gehr
Nov 22, 2013
Jonathan M Davis
Nov 22, 2013
Ali Çehreli
November 22, 2013
I've seen many different topic about this, but they don't explain what's wrong with this "proposed" feature. Who can explain me why this can't be added to language? Does it broke something?

// Trivial example:

struct Test
{
	@property
	auto value(T)() if (is(T == int)) { return _intValue; }

	@property
	void value(T)(T val) if (is(T == int)) { _intValue = val; }

	private int _intValue;
}

void main()
{
	Test s;
	s.value!int(3); // Works

	s.value(3); // Works, magic
	s.value = 3; // Works, magic

	int t1 = s.value!int; // Works
	auto t2 = s.value!int; // Works

	auto t4 = s.value; // Doesn't work (and i don't think it should)
	int t3 = s.value; // <--Doesn't work (can this feature be implemented?)
	
}
November 22, 2013
On Friday, November 22, 2013 10:24:38 Andrea Fontana wrote:
> I've seen many different topic about this, but they don't explain what's wrong with this "proposed" feature. Who can explain me why this can't be added to language? Does it broke something?
> 
> // Trivial example:
> 
> struct Test
> {
> 	@property
> 	auto value(T)() if (is(T == int)) { return _intValue; }
> 
> 	@property
> 	void value(T)(T val) if (is(T == int)) { _intValue = val; }
> 
> 	private int _intValue;
> }

> 	auto t4 = s.value; // Doesn't work (and i don't think it should)
> 	int t3 = s.value; // <--Doesn't work (can this feature be
> implemented?)

And how would it know what type value should be instantiated with. It only knows in the case of

s.value(7)

because you gave it a value from which the compiler was able to infer the type. You didn't tell it anything in the case of

s.value

And it's not like the compiler can look at the template constraint and guess what will work or not - especially when template constraints can be arbitrarily complex. As far as the compiler is concerned, it's just a boolean expression which determines whether a given template instantiation is valid or not. At most, it's used for overloading when there are multiple templates which would otherwise match the given arguments. It's not going to work for the compiler to figure out what types might work with a given template constraint and then have it pick one when you don't tell the template what type to be instantiated with.

- Jonathan M Davis
November 22, 2013
Jonathan M Davis:

> It's not going to work for the compiler to figure out what
> types might work with a given template constraint and then
> have it pick one when you don't tell the template what
> type to be instantiated with.

It could work if the type system become more powerful, but what are the costs in compiler complexity, compilation times, and possible bugs in user code?

Bye,
bearophile
November 22, 2013
On Friday, November 22, 2013 11:24:30 bearophile wrote:
> Jonathan M Davis:
> > It's not going to work for the compiler to figure out what
> > types might work with a given template constraint and then
> > have it pick one when you don't tell the template what
> > type to be instantiated with.
> 
> It could work if the type system become more powerful, but what are the costs in compiler complexity, compilation times, and possible bugs in user code?

What's it going to do? Try ever type that it knows about and see which happens to work? Try every type that it sees in the template constraint (particularly those in is expressions) and see if any of them work? It's a feature which sounds like you're trying to write AI. I don't think that even makes sense to attempt it. If there's really a type that makes sense by default, then just give a default template argument. Why try and make the compiler more complicated, particularly when it's questionable that it's a solvable problem, and it's pretty much a guarantee that it would have a high efficiency cost even if you could pull it off.

- Jonathan M Davis
November 22, 2013
On Friday, 22 November 2013 at 10:34:12 UTC, Jonathan M Davis wrote:
> On Friday, November 22, 2013 11:24:30 bearophile wrote:
>> Jonathan M Davis:
>> > It's not going to work for the compiler to figure out what
>> > types might work with a given template constraint and then
>> > have it pick one when you don't tell the template what
>> > type to be instantiated with.
>> 
>> It could work if the type system become more powerful, but what
>> are the costs in compiler complexity, compilation times, and
>> possible bugs in user code?
>
> What's it going to do? Try ever type that it knows about and see which happens
> to work? Try every type that it sees in the template constraint (particularly
> those in is expressions) and see if any of them work? It's a feature which
> sounds like you're trying to write AI. I don't think that even makes sense to
> attempt it. If there's really a type that makes sense by default, then just
> give a default template argument. Why try and make the compiler more
> complicated, particularly when it's questionable that it's a solvable problem,
> and it's pretty much a guarantee that it would have a high efficiency cost even
> if you could pull it off.
>
> - Jonathan M Davis

I just mean:

int t = s.value;  // Means  int t = s.value!int;

If there's a problem with template instantiatio is the same we have now.
Now I have to write:

int t = s.value!int;

so if there's a problem with !int, it's just like now.

It's just a syntactic sugar, no new feature... Am I wrong?



November 22, 2013
On Friday, 22 November 2013 at 10:50:58 UTC, Andrea Fontana wrote:
> On Friday, 22 November 2013 at 10:34:12 UTC, Jonathan M Davis wrote:
>> On Friday, November 22, 2013 11:24:30 bearophile wrote:
>>> Jonathan M Davis:
>>> > It's not going to work for the compiler to figure out what
>>> > types might work with a given template constraint and then
>>> > have it pick one when you don't tell the template what
>>> > type to be instantiated with.
>>> 
>>> It could work if the type system become more powerful, but what
>>> are the costs in compiler complexity, compilation times, and
>>> possible bugs in user code?
>>
>> What's it going to do? Try ever type that it knows about and see which happens
>> to work? Try every type that it sees in the template constraint (particularly
>> those in is expressions) and see if any of them work? It's a feature which
>> sounds like you're trying to write AI. I don't think that even makes sense to
>> attempt it. If there's really a type that makes sense by default, then just
>> give a default template argument. Why try and make the compiler more
>> complicated, particularly when it's questionable that it's a solvable problem,
>> and it's pretty much a guarantee that it would have a high efficiency cost even
>> if you could pull it off.
>>
>> - Jonathan M Davis
>
> I just mean:
>
> int t = s.value;  // Means  int t = s.value!int;
>
> If there's a problem with template instantiatio is the same we have now.
> Now I have to write:
>
> int t = s.value!int;
>
> so if there's a problem with !int, it's just like now.
>
> It's just a syntactic sugar, no new feature... Am I wrong?

Maybe it could be extended to function call if there's no ambiguities.

something like;

void test(int a, long b);

test(s.value, t.value);  => test(s.value!int, t.value!long);

just if test has no abiguities with overload or template params. In this case we can throw an exception and template param must be explicit.


November 22, 2013
On Friday, November 22, 2013 11:50:57 Andrea Fontana wrote:
> I just mean:
> 
> int t = s.value;  // Means  int t = s.value!int;
> 
> If there's a problem with template instantiatio is the same we
> have now.
> Now I have to write:
> 
> int t = s.value!int;
> 
> so if there's a problem with !int, it's just like now.
> 
> It's just a syntactic sugar, no new feature... Am I wrong?

Again, how is the compiler supposed to have any clue that you want to instantiate value with int in the case of

int t = s.value;

The left-hand side of the expression has no impact on the type of the right- hand side, and you have not given the compiler any information as to what template argument should be given to value. s.value(3) only works because you've given value a function argument from which the corresponding template argument can be inforred. With s.value, you've given no indication whatsoever as to what value should be instantiated with.

If you want a default template argument, then give it one. e.g.

@property auto value(T = int)() if (is(T == int)) { return _intValue; }

But I don't know how you expect the compiler to have any clue what type value should be instantiated with when you haven't given it any template arguments and there are no function arguments to infer the template arguments from - especially when this what the compiler really sees

template value(T)
    if(is(T == int))
{
    @property auto value() { return _intValue; }
}

and it doesn't even look at the template constraint, let alone the contents of the template, until you attempt to instantiate the template. And it's not going to be able to try and instantiate the template without having any template arguments.

- Jonathan M Davis
November 22, 2013
On 11/22/2013 01:29 PM, Jonathan M Davis wrote:
> On Friday, November 22, 2013 11:50:57 Andrea Fontana wrote:
>> I just mean:
>>
>> int t = s.value;  // Means  int t = s.value!int;
>>
>> If there's a problem with template instantiatio is the same we
>> have now.
>> Now I have to write:
>>
>> int t = s.value!int;
>>
>> so if there's a problem with !int, it's just like now.
>>
>> It's just a syntactic sugar, no new feature... Am I wrong?
>
> Again, how is the compiler supposed to have any clue that you want to
> instantiate value with int in the case of
>
> int t = s.value;
>
> The left-hand side of the expression has no impact on the type of the right-
> hand side,

If you mean the type of the variable declaration, then yes it does.

int delegate(int) dg1 = x=>x;
float delegate(float) dg2 = x=>x;

static assert(!is(typeof(x=>x)));

> and you have not given the compiler any information as to what
> template argument should be given to value.

Well, technically, in this case there is only one choice.

> s.value(3) only works because
> you've given value a function argument from which the corresponding template
> argument can be inforred. With s.value, you've given no indication whatsoever
> as to what value should be instantiated with.
>
> If you want a default template argument, then give it one. e.g.
>
> @property auto value(T = int)() if (is(T == int)) { return _intValue; }
>
> But I don't know how you expect the compiler to have any clue what type value
> should be instantiated with when you haven't given it any template arguments
> and there are no function arguments to infer the template arguments from -
> especially when this what the compiler really sees
>
> template value(T)
>      if(is(T == int))
> {
>      @property auto value() { return _intValue; }
> }
>
> and it doesn't even look at the template constraint, let alone the contents of
> the template, until you attempt to instantiate the template. And it's not
> going to be able to try and instantiate the template without having any
> template arguments.
> ...

The request would be reasonable if 'value' was declared as follows though:

@property T value(T)() if (is(T == int)) { return _intValue; }

i.e. the fact that the template argument equals the type of the resulting call can be read off directly from the signature. This is in the same ballpark as the existing IFTI features.


November 22, 2013
On Friday, 22 November 2013 at 12:29:25 UTC, Jonathan M Davis wrote:
> On Friday, November 22, 2013 11:50:57 Andrea Fontana wrote:
>> I just mean:
>> 
>> int t = s.value;  // Means  int t = s.value!int;
>> 
>> If there's a problem with template instantiatio is the same we
>> have now.
>> Now I have to write:
>> 
>> int t = s.value!int;
>> 
>> so if there's a problem with !int, it's just like now.
>> 
>> It's just a syntactic sugar, no new feature... Am I wrong?
>
> Again, how is the compiler supposed to have any clue that you want to
> instantiate value with int in the case of
>
> int t = s.value;
>
> The left-hand side of the expression has no impact on the type of the right-
> hand side, and you have not given the compiler any information as to what
> template argument should be given to value. s.value(3) only works because
> you've given value a function argument from which the corresponding template
> argument can be inforred. With s.value, you've given no indication whatsoever
> as to what value should be instantiated with.
>
> If you want a default template argument, then give it one. e.g.
>
> @property auto value(T = int)() if (is(T == int)) { return _intValue; }
>
> But I don't know how you expect the compiler to have any clue what type value
> should be instantiated with when you haven't given it any template arguments
> and there are no function arguments to infer the template arguments from -
> especially when this what the compiler really sees
>
> template value(T)
>     if(is(T == int))
> {
>     @property auto value() { return _intValue; }
> }
>
> and it doesn't even look at the template constraint, let alone the contents of
> the template, until you attempt to instantiate the template. And it's not
> going to be able to try and instantiate the template without having any
> template arguments.
>
> - Jonathan M Davis


I don't know how compiler works internally. (is there any documentation other than the comments and code itself?)

So probably I'm wrong about what compiler knows and not.
Parsing this:

int t = s.value;

I assumed that it knows - when is trying to instatiate s.value template - that "s.value" is part of an assignment and that it will be assigned to an int. So if template argument is missed and s.value returns T, T should be int. But if I understand your answer, right-hand side can't see left-hand side.

By the way the default value doesn't works for me because in my library I have to choose from many different template. So i have to do every time:

int i = asd.value!int;
string s = asd.value!string;
long l = asd.value!long;

and so on... and i hoped I could do:

int i = asd.value;
string s = asd.value;
long l = asd.value;

Ok, if it's impossible, never mind :)
November 22, 2013
On Friday, November 22, 2013 14:29:46 Timon Gehr wrote:
> The request would be reasonable if 'value' was declared as follows though:
> 
> @property T value(T)() if (is(T == int)) { return _intValue; }
> 
> i.e. the fact that the template argument equals the type of the resulting call can be read off directly from the signature. This is in the same ballpark as the existing IFTI features.

How so? IFTI works by inferring the template arguments from the function arguments. In this case, for the compiler to figure out a type that it could use to instantiate the template, it would have to disect the template constraint, which is compeletly different. Yes, this particular template constraint is very simplistic, but the compiler doesn't even look at the template constraint until it has a type to test with it, and in most cases, it would have no way of inferring what types might work even if it did look.

Trying to get the compiler to infer T for value would be a drastic change to how it deals with templates, and at best, it would be able to figure out what to do in only the most simplistic of cases. In fact, the only cases that it could figure it out would very simplistic cases where there was only one possible answer, and if there's only one type that will work with a template, then there really wasn't much point in templatizing it in the first place. And as soon as there are multiple types which could work with a template, the compiler couldn't figure out the correct type no matter how smart it was, because it would need a way of choosing which of the options to take. e.g.

template foo(T)
     if(is(T == int) || is(T == byte))
{
    ...
}

Should foo be instantiated with int or byte? Both are equally valid.

The OP has come up with a contrived example where it seems obvious to him what type the compiler should use to instantiate a template which has been given no template arguments and no function arguments to infer the template arguments from. But the compiler has no plumbing for figuring out such a thing, and adding such plumbing would be pointless, because it would only work in contrived cases such as this one where there was no point in templatizing the function in the first place.

- Jonathan M Davis
« First   ‹ Prev
1 2