| Thread overview | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 11, 2015 How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Hello. I just found that the following code compiles without any problem:
struct Foo { int val; string name; }
Foo foo = {1, "one"};
auto t = foo.tupleof;
Trying to use `alias` i.o. `auto` above fails.
Now IIUC, trying to take the address of t fails, so it's still a compile- time-only construct without "real" i.e. runtime existence. The tuple is in fact an AliasSeq, no? In which case, I would have thought that `alias` (for compile-time symbols) and not `auto` (for runtime variables) would be the appropriate choice.
Can someone please explain this situation? Thanks.
--
Shriramana Sharma, Penguin #395953
| ||||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | On Friday, 11 December 2015 at 11:18:39 UTC, Shriramana Sharma wrote: > Hello. I just found that the following code compiles without any problem: > > struct Foo { int val; string name; } > Foo foo = {1, "one"}; > auto t = foo.tupleof; > > Trying to use `alias` i.o. `auto` above fails. > > Now IIUC, trying to take the address of t fails, so it's still a compile- time-only construct without "real" i.e. runtime existence. The tuple is in fact an AliasSeq, no? In which case, I would have thought that `alias` (for compile-time symbols) and not `auto` (for runtime variables) would be the appropriate choice. > > Can someone please explain this situation? Thanks. alias can refer to types, templates, template argument lists and compile-time expressions. It can't refer to run-time variables. auto can refer only to run-time values. foo is run-time value. foo.tupleof is also run-time value, like an object of some template instance of std.typecons.Tuple. The template arguments list of std.typecons.Tuple is a compile-time sequence that you can put in AliasSeq. typeof(foo.tupleof) is a type list to which you can only refer with alias or use as template arguments for some template. For example you can put typeof(foo.tupleof) in AliasSeq: alias FooFieldTypes = AliasSeq!(typeof(foo.tupleof)); http://dpaste.dzfl.pl/decbc38e6e71 | |||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | On 12/11/2015 12:18 PM, Shriramana Sharma wrote: > Hello. I just found that the following code compiles without any problem: > > struct Foo { int val; string name; } > Foo foo = {1, "one"}; > auto t = foo.tupleof; > > Trying to use `alias` i.o. `auto` above fails. > ... The alias should compile. This is a compiler bug. Workaround: import std.stdio; alias Seq(T...)=T; void main(){ struct Foo{int val;string name;} Foo foo={1,"one"}; alias t=Seq!(foo.tupleof); } However, this still might not do what you want. The above alias is the same as alias t=Seq!(Foo.tupleof);. This is a general and arbitrary limitation of alias declarations. > Now IIUC, trying to take the address of t fails, so it's still a compile- > time-only construct without "real" i.e. runtime existence. The tuple is in > fact an AliasSeq, no? In which case, I would have thought that `alias` (for > compile-time symbols) and not `auto` (for runtime variables) would be the > appropriate choice. > > Can someone please explain this situation? Thanks. > The line auto t=foo.tupleof; declares two variables and aliases them into a Seq of name 't'. (It is the same as Seq!(int,string) t=foo.tupleof; ) t[0] and t[1] are two distinct variables. This is also why you were not able take the address of t. | |||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | On 12/11/2015 03:12 PM, ZombineDev wrote:
>
> alias can refer to types, templates, template argument lists and
> compile-time expressions. It can't refer to run-time variables.
Yes it can.
void main(){
int x=0;
alias y=x;
y=2;
assert(x==2)
}
It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).
| |||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | On Friday, 11 December 2015 at 14:12:16 UTC, ZombineDev wrote: > [...] In short, the current D terminology calls: compile-time lists -> AliasSeq (http://dlang.org/phobos/std_meta#AliasSeq) run-time values of type lists -> Tuple (http://dlang.org/phobos/std_typecons#.Tuple) Another example: Tuple!(int, string)(3, "apples") obj; obj is a run-time tuple of the integer 3 and the string "apples". The template arguments int and string are a type list (and a special case of an alias sequence). alias Point2D = Tuple!(int, "x", int, "" ~ 'y'); auto point_a = Point2D(3, 4); auto point_b = Point2D(1, -7); Point2D is an alias to the type Tuple!(int, "x", int, "" ~ 'y'), which is a template instance of the Tuple(Specs...) template. The (int, "x", int, "" ~ 'y') template arguments have both types and compile-time expressions among them and that's why we call it an alias sequence and not just a type list. point_a and point_b are tuples of two ints and are run-time values. You can put the template arguments used for Point2D in a AliasSeq: alias Point3DTemplateArgs = AliasSeq!(float, "x", int, "y", double, "z"); And you can use those template args to make a new instance of the Tuple template: alias Point3D = Tuple!(Point3DTemplateArgs); Some runtime values can also be computed at compile-time and you can use them for enums. http://dpaste.dzfl.pl/a05cf181331d (I think that only the output of "2:" is inconsistent.) Also I found this article, which maybe helpful: http://dlang.org/ctarguments.html | |||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Friday, 11 December 2015 at 14:25:45 UTC, Timon Gehr wrote:
> On 12/11/2015 03:12 PM, ZombineDev wrote:
>>
>> alias can refer to types, templates, template argument lists and
>> compile-time expressions. It can't refer to run-time variables.
>
> Yes it can.
>
> void main(){
> int x=0;
> alias y=x;
> y=2;
> assert(x==2)
> }
>
> It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).
Yeah, I forgot to add that it can refer to symbols. Using this featue, you can implement a pass by name function (in addition to pass by value and pass by reference / address).
| |||
December 11, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | On Friday, 11 December 2015 at 14:56:01 UTC, ZombineDev wrote:
> On Friday, 11 December 2015 at 14:25:45 UTC, Timon Gehr wrote:
>> On 12/11/2015 03:12 PM, ZombineDev wrote:
>>>
>>> alias can refer to types, templates, template argument lists and
>>> compile-time expressions. It can't refer to run-time variables.
>>
>> Yes it can.
>>
>> void main(){
>> int x=0;
>> alias y=x;
>> y=2;
>> assert(x==2)
>> }
>>
>> It cannot refer to a field or method of a runtime variable though (it still compiles, but the 'this' reference is just thrown away).
>
> Yeah, I forgot to add that it can refer to symbols. Using this featue, you can implement a pass by name function (in addition to pass by value and pass by reference / address).
To clarify: By using alias you can refer to one symbol through another name.
So alias can refer to variables, but not to values.
Currently, I think this is restricted to only symbols of run-time variables in the same scope (same function, same class, etc.) - only one level of indirection.
| |||
December 12, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | ZombineDev wrote: > In short, the current D terminology calls: > compile-time lists -> AliasSeq > (http://dlang.org/phobos/std_meta#AliasSeq) > run-time values of type lists -> Tuple > (http://dlang.org/phobos/std_typecons#.Tuple) Excellent explanation. I keep looking for a "Like" or "Upvote" button on this forum. :-) Thanks! -- Shriramana Sharma, Penguin #395953 | |||
December 12, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ZombineDev | ZombineDev wrote: >>struct Foo { int val; string name; } >>Foo foo = {1, "one"}; >>auto t = foo.tupleof; >> >> Trying to use `alias` i.o. `auto` above fails. >> >> Now IIUC, trying to take the address of t fails, so it's still > > auto can refer only to run-time values. > > foo is run-time value. In which case, why should taking its address fail? If I try to do: auto tp = &t; I'm getting: Error: tuple(__t_field_0, __t_field_1) is not an lvalue What the!? *After* I assign it to a variable, it still says it's not an lvalue? I mean I understand if I can't take the address of a compiler- created temporary rvalue, but why can't I take its address even after I assign it to a newly created variable? Does the variable t have an address in memory or not? I understand that: alias t2 = foo.tupleof; doesn't work since you cannot give an alias to an rvalue temporary, since t2 would be pointing to nothing after the (immediate) destruction of the temporary tuple object. But I can still do: alias t2 = t; So why can't I do: auto tp = &t; ??? Note that the following, which should be equivalent, works: alias FooTuple = Tuple!(int, string); FooTuple footu = FooTuple(1, "one"); auto ttp = &footu; -- Shriramana Sharma, Penguin #395953 | |||
December 12, 2015 Re: How is `auto` and not `alias` appropriate for alias sequences? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | Another twist to this is that the tuple created by .tupleof doesn't really seem to be a new object of type Tuple!() but rather a "view" of sorts onto the original object itself in the form of a tuple, else the example provided at http://dlang.org/spec/class.html i.e.: class Foo { int x; long y; } void test(Foo foo) { foo.tupleof[0] = 1; // set foo.x to 1 foo.tupleof[1] = 2; // set foo.y to 2 foreach (x; foo.tupleof) write(x); // prints 12 } wouldn't be able to set values to the original class instance via whatever .tupleof generates. So the exact nature of the object produced by .tupleof is still a mystery to me. Would be good if someone threw more light on it. Also: what is the use of presenting the members of a struct/class as a tuple? Is it iteration? -- Shriramana Sharma, Penguin #395953 | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply