www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - compile-time opIndex

reply Steven Schveighoffer <schveiguy yahoo.com> writes:
We currently have the ability to do opIndex for simulating an array or 
other type indexed at runtime.

But we have no way to simulate the ability of tuple indexing. Such an 
ability would unleash a huge amount of possibilities, including 
user-defined tuple types.

Let's designate a straw man name: opTupleIndex.

In essence, if you have foo[n], where n is a compile-time constant, then 
opTupleIndex would be instantiated (if defined) like:

opTupleIndex!n

Then you can have user-defined tuples that are simple to define:

struct KeyValuePair(K, V)
{
    K key;
    V value;
    enum length = 2;
    ref K opTupleIndex(int x) if(x == 0) { return key;}
    ref V opTupleIndex(int x) if(x == 1) { return value;}
}

auto x = KeyValuePair!(int, string)(1, "hi");

static assert(typeof(x[0]) == int);
static assert(typeof(x[1]) == string);
x[0] = 4;
x[1] = "hi";

Note here I have all the mechanisms that real tuples have, but I have 
control over what happens when accessing each element, and I do not need 
opIndex to change its return type based on a runtime parameter (one of 
the limitations of the current system).

I'm not huge on tuple usage, so I'm not sure if I'm missing something. 
Currently there is some debate as to whether to add a "byPair" range to 
builtin AAs, because the return value from 'front' is hard to define. 
This might go a long way in helping such a case.

Does this sound like something worth having? We likely would have to 
error if both opIndex and opTupleIndex are defined for a specific type.

-Steve
Dec 18 2014
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
Have you seen my http://wiki.dlang.org/DIP63 ?
Dec 18 2014
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/18/14 10:44 AM, Dicebot wrote:
 Have you seen my http://wiki.dlang.org/DIP63 ?
I admit this is somewhat over my head, but it seems to be more focused on types. I will note that your example: struct Pack(T...) { alias expand = T; alias expand this; } I don't think this would work, since you can't alias a value to a type? But I don't use tuples regularly, so I am not sure where exactly expand is used. I thought it was to convert a concrete struct into a tuple of values, not a type tuple. I don't disagree with the idea of having operators inside templates, I just don't know if it solves the problem I was looking at. -Steve
Dec 18 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 18 December 2014 at 16:15:09 UTC, Steven 
Schveighoffer wrote:
 On 12/18/14 10:44 AM, Dicebot wrote:
 Have you seen my http://wiki.dlang.org/DIP63 ?
I admit this is somewhat over my head, but it seems to be more focused on types.
In D there is no special built-in value tuple concept. It is all same thing but emulating this behavior for symbols and types is much more difficult compared to values. This is the reason for such focus - rest is not really a problem.
 I will note that your example:

 struct Pack(T...)
 {
    alias expand = T;
    alias expand this;
 }

 I don't think this would work, since you can't alias a value to 
 a type?
Try this and be surprised :) `alias this` affects any symbol lookup and this pattern results in pretty interesting behavior. But it is still not good enough as described in the DIP.
 But I don't use tuples regularly, so I am not sure where 
 exactly expand is used. I thought it was to convert a concrete 
 struct into a tuple of values, not a type tuple.
You can ignore expansion for now, it was motivating use case but DIP itself defines tools of defining user types that act like built-in tuples - which fits the theme of your original proposal. It also briefly speculates why adding such features to structs does not seem a good idea. Also there is no difference between tuple of values and type tuple, it is same entity.
 I don't disagree with the idea of having operators inside 
 templates, I just don't know if it solves the problem I was 
 looking at.
Your original snippet seems to implementable within proposed DIP if you replace struct with raw template. You will lose struct properties like having actual instance but those don't exist for built-in tuples either.
Dec 18 2014
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/18/14 11:34 AM, Dicebot wrote:
 On Thursday, 18 December 2014 at 16:15:09 UTC, Steven Schveighoffer wrote:
 I don't disagree with the idea of having operators inside templates, I
 just don't know if it solves the problem I was looking at.
Your original snippet seems to implementable within proposed DIP if you replace struct with raw template. You will lose struct properties like having actual instance but those don't exist for built-in tuples either.
So the discussion is here: https://github.com/D-Programming-Language/druntime/pull/1070 Essentially, we want to implement a range which gives access to builtin-AA elements via a pair or tuple. The first element will be the key, the second the value. But we also want to allow changing the value, and getting the key by reference (if, for instance, it's a huge struct). The big issue here is that people are worried about putting in some 'hacky' type returned from 'front' for this range, when "builtin tuples are around the corner." We don't want to have people get used to having one API, and then have to switch to another API when real tuples are released. So having an actual concrete instance is important here. 'front' doesn't return a type it returns a value tuple. Oh, and we can't use std.typecons.Tuple because that's in Phobos, this is druntime. (and my assertion is that front.key and front.value should work instead of having to use front[0] and front[1]!) -Steve
Dec 18 2014
parent reply "Dicebot" <public dicebot.lv> writes:
I wasn't subscribed to druntime changes thus missed this 
discussion. Will chime in there soon.
Dec 18 2014
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/18/14 11:54 AM, Dicebot wrote:
 I wasn't subscribed to druntime changes thus missed this discussion.
 Will chime in there soon.
Ping, still waiting on this :) -Steve
Dec 30 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 30 December 2014 at 15:48:03 UTC, Steven 
Schveighoffer wrote:
 On 12/18/14 11:54 AM, Dicebot wrote:
 I wasn't subscribed to druntime changes thus missed this 
 discussion.
 Will chime in there soon.
Ping, still waiting on this :) -Steve
*blush*
Dec 30 2014
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/30/14 10:51 AM, Dicebot wrote:
 On Tuesday, 30 December 2014 at 15:48:03 UTC, Steven Schveighoffer wrote:
 On 12/18/14 11:54 AM, Dicebot wrote:
 I wasn't subscribed to druntime changes thus missed this discussion.
 Will chime in there soon.
Ping, still waiting on this :)
*blush*
OK, I see your response, but I'm still curious as to how/whether your DIP would solve it. Any thoughts on the feature brought up in this thread? -Steve
Dec 30 2014
parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 30 December 2014 at 16:25:05 UTC, Steven 
Schveighoffer wrote:
 On 12/30/14 10:51 AM, Dicebot wrote:
 On Tuesday, 30 December 2014 at 15:48:03 UTC, Steven 
 Schveighoffer wrote:
 On 12/18/14 11:54 AM, Dicebot wrote:
 I wasn't subscribed to druntime changes thus missed this 
 discussion.
 Will chime in there soon.
Ping, still waiting on this :)
*blush*
OK, I see your response, but I'm still curious as to how/whether your DIP would solve it. Any thoughts on the feature brought up in this thread? -Steve
In this specific case I actually expected this to work: struct S { int key, value; import std.typetuple; alias asTuple = TypeTuple!(this.tupleof); alias asTuple this; } void main() { S s; s[0] = 42; } However it does not seem to recognize that `this` pointer is available in such specific invocation. It can be a bug or there may be a legitimate reason preventing it - not entirely sure. Unfortunately I have never completely understood cases when alias is able to preserve context pointer and when it can't. If it worked though, my proposal would allow more customized access: struct S { int x; template MyTuple() { alias opIndex(size_t i) = S.x; } alias MyTuple this; // note it is not MyTuple!() } void main() { S s; s[100] = 42; assert(s[50] == 42); } It is not exactly the thing you were originally looking for but I am against any attempt to try adding template argument list flavor to "normal" aggregates - it creates many new corner cases to consider. One example was mentioned in DIP - if `static opIndex` is the thing why can't you do S[0] but only s[0]? It is static after all! More tricky stuff to explain - not worth the feature in my opinion.
Dec 31 2014
prev sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Thu, Dec 18, 2014 at 03:44:18PM +0000, Dicebot via Digitalmars-d wrote:
 Have you seen my http://wiki.dlang.org/DIP63 ?
Ahhh, finally I understand what this DIP is all about. :-D I like it. +1. T -- If blunt statements had a point, they wouldn't be blunt...
Dec 18 2014
parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 18 December 2014 at 18:04:10 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 On Thu, Dec 18, 2014 at 03:44:18PM +0000, Dicebot via 
 Digitalmars-d wrote:
 Have you seen my http://wiki.dlang.org/DIP63 ?
Ahhh, finally I understand what this DIP is all about. :-D I like it. +1. T
Unfortunately when trying to implement this in DMD I have encountered many difficulties with existing DMD tree structure - it simply does not allow to express such entities without serious restructuring. And I am no proficient enough in DMD to do such a major change on my own - thus it remains frozen :(
Dec 18 2014
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/18/14 10:43 AM, Steven Schveighoffer wrote:

 struct KeyValuePair(K, V)
 {
     K key;
     V value;
     enum length = 2;
     ref K opTupleIndex(int x) if(x == 0) { return key;}
     ref V opTupleIndex(int x) if(x == 1) { return value;}
 }
Or with more recent changes to the compiler: template opTupleIndex(int x) if (x == 0) { alias opTupleIndex = key;} template opTupleIndex(int x) if (x == 1) { alias opTupleIndex = value;} -Steve
Dec 18 2014
prev sibling next sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12/18/14 16:43, Steven Schveighoffer via Digitalmars-d wrote:
 We currently have the ability to do opIndex for simulating an array or other
type indexed at runtime.
 
 But we have no way to simulate the ability of tuple indexing. Such an ability
would unleash a huge amount of possibilities, including user-defined tuple
types.
struct TupleWannabe(S) { typeof(S.tupleof) tupleof; static __memberWannabe() { string s; foreach (I, _; typeof(S.tupleof)) s ~= `ref `~S.tupleof[I].stringof~`() property { return tupleof[`~I.stringof~`]; } `; return s; } mixin(__memberWannabe()); alias tupleof this; } struct S { int key; string val; } alias ST = TupleWannabe!S; void main() { ST s = ST(1, "blah"); s.key = 2; s.val = "yada"; s[0] = 42; s[1] = "etc"; } SCNR. Happy new year! artur
Dec 31 2014
prev sibling next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Dec 31, 2014 at 10:34:07PM +0100, Artur Skawina via Digitalmars-d wrote:
 On 12/18/14 16:43, Steven Schveighoffer via Digitalmars-d wrote:
 We currently have the ability to do opIndex for simulating an array
 or other type indexed at runtime.
 
 But we have no way to simulate the ability of tuple indexing. Such
 an ability would unleash a huge amount of possibilities, including
 user-defined tuple types.
struct TupleWannabe(S) { typeof(S.tupleof) tupleof; static __memberWannabe() { string s; foreach (I, _; typeof(S.tupleof)) s ~= `ref `~S.tupleof[I].stringof~`() property { return tupleof[`~I.stringof~`]; } `; return s; } mixin(__memberWannabe()); alias tupleof this; } struct S { int key; string val; } alias ST = TupleWannabe!S; void main() { ST s = ST(1, "blah"); s.key = 2; s.val = "yada"; s[0] = 42; s[1] = "etc"; } SCNR. Happy new year!
[...] Very nice! Now make it work for int* and string*, but indexing the tuple returns (non-pointer) int and string. This is the original use case that prompted this ER, btw, so if it can't be achieved, then we haven't solved anything. T -- In theory, there is no difference between theory and practice.
Dec 31 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 31 December 2014 at 21:37:37 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 Very nice! Now make it work for int* and string*, but indexing 
 the tuple
 returns (non-pointer) int and string. This is the original use 
 case that
 prompted this ER, btw, so if it can't be achieved, then we 
 haven't
 solved anything.
My original point was that it shouldn't be done even if it can be done.
Dec 31 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Dec 31, 2014 at 09:41:18PM +0000, Dicebot via Digitalmars-d wrote:
 On Wednesday, 31 December 2014 at 21:37:37 UTC, H. S. Teoh via Digitalmars-d
 wrote:
Very nice! Now make it work for int* and string*, but indexing the
tuple returns (non-pointer) int and string. This is the original use
case that prompted this ER, btw, so if it can't be achieved, then we
haven't solved anything.
My original point was that it shouldn't be done even if it can be done.
Point. But that means we've gone nowhere with AA .byPair(). If I wanted to stir up controversy, I'd say that the ultimate cause of this issue was the fact that struct fields can't be ref; otherwise it would be a non-problem (make .key and .value ref, and then .tupleof will Just Work(tm)). T -- Bare foot: (n.) A device for locating thumb tacks on the floor.
Dec 31 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 31 December 2014 at 22:05:37 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 Point. But that means we've gone nowhere with AA .byPair().

 If I wanted to stir up controversy, I'd say that the ultimate 
 cause of
 this issue was the fact that struct fields can't be ref; 
 otherwise it
 would be a non-problem (make .key and .value ref, and then 
 .tupleof will
 Just Work(tm)).
struct S(Key, Value) { private: Key* _key; Value* _value; public: ref Key key() property { return *this._key; } ref Key value() property { return *this._value; } } and no need for tuple weirdness.
Dec 31 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Dec 31, 2014 at 10:35:18PM +0000, Dicebot via Digitalmars-d wrote:
 On Wednesday, 31 December 2014 at 22:05:37 UTC, H. S. Teoh via Digitalmars-d
 wrote:
Point. But that means we've gone nowhere with AA .byPair().

If I wanted to stir up controversy, I'd say that the ultimate cause
of this issue was the fact that struct fields can't be ref; otherwise
it would be a non-problem (make .key and .value ref, and then
.tupleof will Just Work(tm)).
struct S(Key, Value) { private: Key* _key; Value* _value; public: ref Key key() property { return *this._key; } ref Key value() property { return *this._value; } } and no need for tuple weirdness.
That's what I have right now. The catch is how to make S behave like a tuple. Or perhaps that's a fool's errand, and we should rename the function to .byKeyValue, and leave .byPair for Phobos where it can just package up .key and .value pairs in std.typecons.Tuple, as people demanded. T -- IBM = I'll Buy Microsoft!
Dec 31 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 31 December 2014 at 22:47:05 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 That's what I have right now. The catch is how to make S behave 
 like a
 tuple.
I don't know why it was considered an important/worthy goal. Trying to provide API based on tuples just hides the fact that there is no real working implementation for them.
Dec 31 2014
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Wed, Dec 31, 2014 at 10:53:37PM +0000, Dicebot via Digitalmars-d wrote:
 On Wednesday, 31 December 2014 at 22:47:05 UTC, H. S. Teoh via Digitalmars-d
 wrote:
That's what I have right now. The catch is how to make S behave like
a tuple.
I don't know why it was considered an important/worthy goal. Trying to provide API based on tuples just hides the fact that there is no real working implementation for them.
I don't know either. The last time round, the byPair PR was shot down because people demanded Tuple support. *shrug* Yet another stalemate. T -- Acid falls with the rain; with love comes the pain.
Dec 31 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 31 December 2014 at 22:58:57 UTC, H. S. Teoh via 
Digitalmars-d wrote:
 people demanded Tuple support.
Was it bearophile? :P I can't stop feeling that it is simply not recognized enough how bad D tuples are if such request arises. I'd personally try to avoid those in almost all cases where it is practically feasible.
Dec 31 2014
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 12/31/14 6:05 PM, Dicebot wrote:
 On Wednesday, 31 December 2014 at 22:58:57 UTC, H. S. Teoh via
 Digitalmars-d wrote:
 people demanded Tuple support.
Was it bearophile? :P I can't stop feeling that it is simply not recognized enough how bad D tuples are if such request arises. I'd personally try to avoid those in almost all cases where it is practically feasible.
Right now, ranges properly work with phobos ONLY if they are tuples (specifically std.typecons.Tuple). The idea is that eventually there will be more support for builtin tuples, and at that point, the requirement will shift to the builtin tuple. The "fear" is that if you have .key and .value support, and somehow this is impossible to support and also support builtin tuples (I highly doubt this), then we wouldn't be able to use builtin tuples as a return type for aa.byPair.front. Thereby making AA's incompatible with phobos ranges. IMO, having SOMETHING in AA.byPair is better than nothing. I really am not worried at all about range tuple support, and I think it will be doable when "real tuples" arrive -- support will be additive. And I'm also with you that if you don't have .key .value support, this isn't worth having. -Steve
Jan 01 2015
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Thu, Jan 01, 2015 at 01:42:45PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 On 12/31/14 6:05 PM, Dicebot wrote:
On Wednesday, 31 December 2014 at 22:58:57 UTC, H. S. Teoh via
Digitalmars-d wrote:
people demanded Tuple support.
Was it bearophile? :P I can't stop feeling that it is simply not recognized enough how bad D tuples are if such request arises. I'd personally try to avoid those in almost all cases where it is practically feasible.
Right now, ranges properly work with phobos ONLY if they are tuples (specifically std.typecons.Tuple). The idea is that eventually there will be more support for builtin tuples, and at that point, the requirement will shift to the builtin tuple. The "fear" is that if you have .key and .value support, and somehow this is impossible to support and also support builtin tuples (I highly doubt this), then we wouldn't be able to use builtin tuples as a return type for aa.byPair.front. Thereby making AA's incompatible with phobos ranges. IMO, having SOMETHING in AA.byPair is better than nothing. I really am not worried at all about range tuple support, and I think it will be doable when "real tuples" arrive -- support will be additive. And I'm also with you that if you don't have .key .value support, this isn't worth having.
[...] The way I see it, this is an acceptable compromise: 1) Have .byKeyValue in druntime, which returns a struct with .key and .value; 2) Have .byPair in Phobos (via UFCS), which wraps around .byKeyValue and returns a Tuple of .key and .value. T -- Question authority. Don't ask why, just do it.
Jan 01 2015
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"H. S. Teoh via Digitalmars-d"  wrote in message 
news:mailman.3979.1420139660.9932.digitalmars-d puremagic.com...

 The way I see it, this is an acceptable compromise:

 1) Have .byKeyValue in druntime, which returns a struct with .key and
 .value;

 2) Have .byPair in Phobos (via UFCS), which wraps around .byKeyValue and
 returns a Tuple of .key and .value.
I agree with this.
Jan 02 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/1/15 2:12 PM, H. S. Teoh via Digitalmars-d wrote:
 On Thu, Jan 01, 2015 at 01:42:45PM -0500, Steven Schveighoffer via
Digitalmars-d wrote:
 And I'm also with you that if you don't have .key .value support, this
 isn't worth having.
[...] The way I see it, this is an acceptable compromise: 1) Have .byKeyValue in druntime, which returns a struct with .key and ..value; 2) Have .byPair in Phobos (via UFCS), which wraps around .byKeyValue and returns a Tuple of .key and .value.
You don't need to wrap, just reimplement (The _aaRange primitives are accessible, I tried it). I don't see any reason to nest these, and they can be unrelated. As I said before, you can shoehorn the primitives into whatever you want in Phobos. So I'm more interested in getting the .byKeyValue, we can call it that if people like it better. I don't care at all what, if anything, goes into Phobos. -Steve
Jan 02 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Steven Schveighoffer"  wrote in message 
news:m862b3$230o$1 digitalmars.com...

 You don't need to wrap, just reimplement (The _aaRange primitives are 
 accessible, I tried it). I don't see any reason to nest these, and they 
 can be unrelated. As I said before, you can shoehorn the primitives into 
 whatever you want in Phobos.
You should wrap, unless we want to make _aaRange part of the stable api.
Jan 02 2015
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/2/15 7:40 AM, Daniel Murphy wrote:
 "Steven Schveighoffer"  wrote in message
 news:m862b3$230o$1 digitalmars.com...

 You don't need to wrap, just reimplement (The _aaRange primitives are
 accessible, I tried it). I don't see any reason to nest these, and
 they can be unrelated. As I said before, you can shoehorn the
 primitives into whatever you want in Phobos.
You should wrap, unless we want to make _aaRange part of the stable api.
Why, because phobos developers aren't aware of druntime's activities? -Steve
Jan 02 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Steven Schveighoffer"  wrote in message 
news:m86645$26iu$1 digitalmars.com...

 Why, because phobos developers aren't aware of druntime's activities?
Ideally, yes.
Jan 02 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/2/15 12:37 PM, Daniel Murphy wrote:
 "Steven Schveighoffer"  wrote in message
 news:m86645$26iu$1 digitalmars.com...

 Why, because phobos developers aren't aware of druntime's activities?
Ideally, yes.
Nobody from phobos or druntime can commit changes that break the other accidentally. But, it's not really important to me how the phobos range looks, so I'll drop the argument. -Steve
Jan 02 2015
prev sibling parent reply "Martin Nowak" <code dawg.eu> writes:
On Friday, 2 January 2015 at 12:40:41 UTC, Daniel Murphy wrote:
 You should wrap, unless we want to make _aaRange part of the 
 stable api.
Yep, please don't rely on runtime internals. Wrapping front can be inlined and optimized.
Jan 02 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/2/15 8:24 AM, Martin Nowak wrote:
 On Friday, 2 January 2015 at 12:40:41 UTC, Daniel Murphy wrote:
 You should wrap, unless we want to make _aaRange part of the stable api.
Yep, please don't rely on runtime internals. Wrapping front can be inlined and optimized.
Well, as I said, I couldn't care less about Phobos implementation :) As long as it's as fast, wrap away. -Steve
Jan 02 2015
prev sibling parent Artur Skawina via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12/31/14 22:35, H. S. Teoh via Digitalmars-d wrote:
 On Wed, Dec 31, 2014 at 10:34:07PM +0100, Artur Skawina via Digitalmars-d
wrote:
 On 12/18/14 16:43, Steven Schveighoffer via Digitalmars-d wrote:
 We currently have the ability to do opIndex for simulating an array
 or other type indexed at runtime.

 But we have no way to simulate the ability of tuple indexing. Such
 an ability would unleash a huge amount of possibilities, including
 user-defined tuple types.
struct TupleWannabe(S) { typeof(S.tupleof) tupleof; static __memberWannabe() { string s; foreach (I, _; typeof(S.tupleof)) s ~= `ref `~S.tupleof[I].stringof~`() property { return tupleof[`~I.stringof~`]; } `; return s; } mixin(__memberWannabe()); alias tupleof this; } struct S { int key; string val; } alias ST = TupleWannabe!S; void main() { ST s = ST(1, "blah"); s.key = 2; s.val = "yada"; s[0] = 42; s[1] = "etc"; } SCNR. Happy new year!
Very nice! Now make it work for int* and string*, but indexing the tuple
OP only asked for tuple-like indexing for UDTs.
 returns (non-pointer) int and string. This is the original use case that
 prompted this ER, btw, so if it can't be achieved, then we haven't
 solved anything.
That is not supported by the _language_. It lacks (1) references and (2) means of controlling object lifetimes. You can easily add a `Ref!` wrapper, but, because of the latter issue, these types of hacks are not a good idea in general. artur
Jan 01 2015