www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 5710] New: cannot use delegates as parameters to non-global template

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710

           Summary: cannot use delegates as parameters to non-global
                    template
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Windows
            Status: NEW
          Keywords: rejects-valid
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: dsimcha yahoo.com



This pretty severely impacts the usability of template alias parameters for
lambda functions.

class Foo {
    uint doStuff(alias fun)(uint a, uint b) { return fun(a, b); }
}

void main() {
    auto foo = new Foo;

    uint add(uint a, uint b) { return a + b; }

    foo.doStuff!add(1, 2);
}

test9.d(10): Error: template instance cannot use local 'add' as parameter to
non-global template doStuff(alias fun)

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 06 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla digitalmars.com



10:16:43 PST ---
The reason this does not work is because the instantiation of the doStuff()
function would require *two* context pointers:

1. a 'this' pointer to the object Foo
2. a 'this' pointer to the stack frame of main()

and there can be only one.

It will work if you declare add() as being static, because then you're saying
that it does not need a context pointer to main().

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




So is this an WONTFIX, then?  Unfortunately it severely hurts my
std.parallelism design in some use cases, and a workaround for it would be a
significant PITA to implement, make the API uglier, and possibly be
inefficient.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




15:19:12 PST ---

 So is this an WONTFIX, then?
Unless there's an epiphany somewhere, yes. How would you suggest two hidden context pointers be handled? Is it clear that two context pointers are required (at least for this example)?
 Unfortunately it severely hurts my
 std.parallelism design in some use cases, and a workaround for it would be a
 significant PITA to implement, make the API uglier, and possibly be
 inefficient.
I don't know enough about your design to offer help with that. Perhaps instead of an alias parameter, make fun explicitly a delegate? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com



15:31:45 PST ---


 So is this an WONTFIX, then?
Unless there's an epiphany somewhere, yes. How would you suggest two hidden context pointers be handled? Is it clear that two context pointers are required (at least for this example)?
 Unfortunately it severely hurts my
 std.parallelism design in some use cases, and a workaround for it would be a
 significant PITA to implement, make the API uglier, and possibly be
 inefficient.
I don't know enough about your design to offer help with that. Perhaps instead of an alias parameter, make fun explicitly a delegate?
There are several things here. First, the compiler should figure out that add does not need a frame pointer and consider it a static inner function, not a delegate. Second, we need to agree that the reason you invoke is tied to the implementation - you use the same pointer for the class and for the hidden frame pointer, whereas of course there's no imposition to do so. The hidden "this" parameter could go pretty much anywhere else. One way or another we must fix this. Oddly, a number of similar uses do work "by mistake", so at this moment we don't have a clear grasp on what distinguishes cases that work from cases that don't. We need to pursue this like a bloodhound and aggressively make as many cases as possible work transparently. This is a major asset of D over virtually all other languages. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710






 So is this an WONTFIX, then?
Unless there's an epiphany somewhere, yes. How would you suggest two hidden context pointers be handled? Is it clear that two context pointers are required (at least for this example)?
Honestly, I don't know enough about the details of how DMD works under the hood to come up with a good answer, but my completely naive answer would be to pass the delegate context pointer in as a hidden argument between the explicit arguments and the hidden class instance pointer. The class instance pointer is still passed last (no special casing) and the delegate context pointer lives on the stack somewhere as a regular stack variable and gets passed in when needed.
 
 Unfortunately it severely hurts my
 std.parallelism design in some use cases, and a workaround for it would be a
 significant PITA to implement, make the API uglier, and possibly be
 inefficient.
I don't know enough about your design to offer help with that. Perhaps instead of an alias parameter, make fun explicitly a delegate?
This would be the workaround, but I probably won't implement it because: 1. If I still keep alias parameters, I'll have to have two implementations of map(), reduce() and friends. This is ugly from both an API and an implementation perspective. 2. Delegates can't be inlined. Aliases can. 3. Delegates can only be instantiations of templates. Aliases can be templates. This means that a nested template function would have to be explicitly instantiated. This is ugly. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




22:18:04 PST ---

 First, the compiler should figure out that add does not need a frame pointer
 and consider it a static inner function, not a delegate.
Delegates and functions are different types. Deciding, based on the contents of a function body, whether it is a function or a delegate makes for non-obvious changes in type. Secondly, people are going to access outer variables from a nested function, and will not expect it to break their code.
 Second, we need to agree that the reason you invoke is tied to the
 implementation - you use the same pointer for the class and for the hidden
 frame pointer, whereas of course there's no imposition to do so.
Making them use the same ABI means that they have the same type and are interchangeable. This is a big deal. I don't think this will survive "a class member function pointer is a different type than a nested function pointer".
 The hidden "this" parameter could go pretty much anywhere else.
 One way or another we must fix this. Oddly, a number of similar uses do work
 "by mistake", so at this moment we don't have a clear grasp on what
 distinguishes cases that work from cases that don't.
 We need to pursue this like a bloodhound and aggressively make as many cases as
 possible work transparently. This is a major asset of D over virtually all
 other languages.
Consider if we add another type - a function pointer with two context pointers. Now we have quite a menagerie: 1. function pointer 2. function pointer with context pointer (delegate) 3. function pointer with two context pointers Is that really where we want to go? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 06 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Rainer Schuetze <r.sagitario gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |r.sagitario gmx.de



PST ---
This could be implemented with a single context pointer, if the this pointer of
the Foo instance can be found through the stack frame pointer. In the example
the pointer to foo is already there, but in the more general case, a hidden
stack/closure variable needs to be used.

I'm not sure how much it would complicate code generation, though. It could end
up as a can of worms, e.g. having to deal with multiple aliases to different
kind of context pointers.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 07 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Brad Roberts <braddr puremagic.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |braddr puremagic.com



---

 Consider if we add another type - a function pointer with two context pointers.
 Now we have quite a menagerie:
 
 1. function pointer
 2. function pointer with context pointer (delegate)
 3. function pointer with two context pointers
 
 Is that really where we want to go?
Yes. They're just function parameters. Define how they're passed and pass 'em. It doesn't need to be fancy or tricky. It's not particularly different from passing dynamic arrays having a well defined parameter layout. Just considered it just a tuple of two pointers. It's not rocket science. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 07 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |k.hara.pg gmail.com



My idea:
doStuff receives a context pointer that points 'an array of context pointers'.
Backend receives code like follows...

uint doStuff(uint a, uint b, void** this)  // not void* this
{
    // (*this + 0) points the object Foo
    // (*this + 1) points the stack frame of main()

    //return fun(a, b);
    return fun(a, b, (*this + 1));
}

Caller of doStuff have to create array of context pointers.

void main(){
    ...
    //foo.doStuff!add(1, 2);
    void*[2] thisarray = [(stack frame of main), foo];
    doStuff(a, b, thisarray.ptr);
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jun 10 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---

 My idea:
 doStuff receives a context pointer that points 'an array of context pointers'.
 Backend receives code like follows...
 
 uint doStuff(uint a, uint b, void** this)  // not void* this
 {
     // (*this + 0) points the object Foo
     // (*this + 1) points the stack frame of main()
 
     //return fun(a, b);
     return fun(a, b, (*this + 1));
 }
 
 Caller of doStuff have to create array of context pointers.
 
 void main(){
     ...
     //foo.doStuff!add(1, 2);
     void*[2] thisarray = [(stack frame of main), foo];
     doStuff(a, b, thisarray.ptr);
 }
Sounds great if you can pull it off. I was thinking the same thing, but I'm not familiar enough with the DMD codebase to know how easy/hard it would be to implement. This would remove some really silly/annoying limitations from std.parallelism. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 19 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---

 1. function pointer
 2. function pointer with context pointer (delegate)
 3. function pointer with two context pointers
 
 Is that really where we want to go?
If it's really that much of a problem, how about we just forbid taking the address of functions with two context pointers? It would be a heck of a lot less of an annoying limitation than this bug. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 23 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---
Any chance of this getting fixed anytime soon now that we're addressing a whole
bunch of lambda-related issues?  If not, I think I can use UFCS to move
std.parallelism.map, reduce, etc. out of TaskPool w/o changing the call syntax,
and work around this bug.  This is kind of ugly, though, so I'd rather not do
so if this bug is going to get fixed.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 28 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




09:38:34 PDT ---
I think Kenji's design is very promising. I assume it uses static arrays, i.e.
no dynamic allocation. On the other hand, we need to think this through quite
carefully. One example is that some frames must be dynamically allocated, and
others don't. So the array of frame pointers would contain in the general case
a mix of pointers to the stack and pointers to the heap. Hopefully that doesn't
impact the design.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


klickverbot <code klickverbot.at> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code klickverbot.at



---

 If not, I think I can use UFCS to move
 std.parallelism.map, reduce, etc. out of TaskPool w/o changing the call syntax,
 and work around this bug.
I don't think you can, because D doesn't have ADL, so if somebody just has the TaskPool type, but not the module in scope, the free functions would not be found. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jul 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


deadalnix <deadalnix gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |deadalnix gmail.com




 The reason this does not work is because the instantiation of the doStuff()
 function would require *two* context pointers:
 
 1. a 'this' pointer to the object Foo
 2. a 'this' pointer to the stack frame of main()
 
 and there can be only one.
 
 It will work if you declare add() as being static, because then you're saying
 that it does not need a context pointer to main().
Why there could only be one ? I see no real problem about having 2 of them. Note that I have plenty of workaround on top of several forms of that issue. Passing the delegate as argument instead of alias is going to make things much slower. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com



11:01:01 PDT ---


 class Foo {
     uint doStuff(alias fun)(uint a, uint b) { return fun(a, b); }
 }
 
 void main() {
     auto foo = new Foo;
 
     uint add(uint a, uint b) { return a + b; }
 
     foo.doStuff!add(1, 2);
 }
This is definitely not good. I don't think we need to alter the ABI for this. The 'this' pointer of the frame isn't used inside doStuff, just inside the template instantiation. The compiler can be smart enough to recognize that fun(a, b) is really: fun(a, b, frameptr), and that frameptr is passed implicitly as a parameter. It does not have to be spelled out in the parameters to doStuff. I don't like the *spirit* of kenji's solution, that context pointers are an array. Given that this is a template, and the compiler has the ability to pass and receive, and write code for, any hidden parameter it wishes, it's simply a matter of lowering. Like foreach, which injects hidden code and function return handling. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710


Diggory <diggsey googlemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |diggsey googlemail.com



---
Kenji's solution means two context pointer delegates are just normal delegates
(still a function pointer and a context pointer) so they can still be passed
around as usual.

There's no need for dynamic allocation because if the stack frame referred to
by a delegate is invalid when the delegate is called, the results are already
undefined.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




14:50:59 PDT ---

 Kenji's solution means two context pointer delegates are just normal delegates
 (still a function pointer and a context pointer) so they can still be passed
 around as usual.
OK, but how does it devolve to a 'this' pointer for the class? In other words, doesn't the compiler have to treat 'this' in a special way while inside doStuff? Is that OK? I guess it's not too important, but it would be a new ABI call type, no? I wonder if it wouldn't be better to push 'foo' and then the stack frame on to the stack, and then the call to doStuff would look like: uint doStuff(uint a, uint b, void* this) { // *(&(this) + 0) points the object Foo // *(&(this) + 1) points the stack frame of main() //return fun(a, b); return fun(a, b, *(&this + 1)); } Would that not work? I'd actually rather just see another parameter: uint doStuff(uint a, uint b, void *this1, void *this) { return fun(a, b, this1); } That is simpler for me to understand, I don't see why the compiler can't do this. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---


 Kenji's solution means two context pointer delegates are just normal delegates
 (still a function pointer and a context pointer) so they can still be passed
 around as usual.
OK, but how does it devolve to a 'this' pointer for the class? In other words, doesn't the compiler have to treat 'this' in a special way while inside doStuff? Is that OK? I guess it's not too important, but it would be a new ABI call type, no? I wonder if it wouldn't be better to push 'foo' and then the stack frame on to the stack, and then the call to doStuff would look like: uint doStuff(uint a, uint b, void* this) { // *(&(this) + 0) points the object Foo // *(&(this) + 1) points the stack frame of main() //return fun(a, b); return fun(a, b, *(&this + 1)); } Would that not work? I'd actually rather just see another parameter: uint doStuff(uint a, uint b, void *this1, void *this) { return fun(a, b, this1); } That is simpler for me to understand, I don't see why the compiler can't do this.
How the parameters are actually passed is fairly irrelevant, the main problem which needs to be solved is how to store two context pointers in a delegate, when currently delegates look like this: struct dg { void* contextPtr; void* funcPtr; } If you add an extra context pointer, you have to either make all delegates bigger: struct dg { void* contextPtr1; void* contextPtr2; void* funcPtr; } Or have two or more types of delegates which cannot be used interchangeably (in which case they're fairly useless as delegates!) Kenji is suggesting something like this: struct dg { void* contextPtr; void* funcPtr; } struct multiContext { void* contextPtr1; void* contextPtr2; } The "multiContext" struct is completely invisible to anyone using the delegate, and it doesn't affect in the slightest how the delegate is called, you're still passing in one context pointer. The decoding into two context pointers is handled by the callee, because the callee knows how many context pointers it should have. (Think about it, how can a function not know how many context pointers it needs!) It should be possible to call a delegate without having to know anything about the receiver other than what arguments it takes. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




16:59:08 PDT ---


 How the parameters are actually passed is fairly irrelevant, the main problem
 which needs to be solved is how to store two context pointers in a delegate,
If you look closely at the original example, no delegates are used. add is passed by alias, not by delegate. But I see the point, if you took &foo.doStuff!add, you would be screwed. What about Rainer's idea? This would require less memory consumption from the stack. Anyone consider that this is no longer the case (in any valid solution so far)? auto dg = &foo.doStuff!add; assert(foo !is dg.ptr); Don't know if that's an unbreakable rule though... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---


 
 How the parameters are actually passed is fairly irrelevant, the main problem
 which needs to be solved is how to store two context pointers in a delegate,
If you look closely at the original example, no delegates are used. add is passed by alias, not by delegate. But I see the point, if you took &foo.doStuff!add, you would be screwed. What about Rainer's idea? This would require less memory consumption from the stack.
The problem with Rainer's idea is that the callee would need to know the layout of the stack frame in the context in which the delegate was bound, which in general it cannot know. If you refine it so that you arrange for part of the stack frame to follow a predefined layout so that the callee knows where to find the "this" pointer, you then need a second pointer to point to the beginning of the stack frame (because it may not be possible to place this structure at the start of the stack frame) and you end up with something that is identical to Kenji's solution. It only uses one extra pointer over what would be required if you had a dedicated 2 context pointer delegate type, so I don't think that memory consumption is much of a problem.
 Anyone consider that this is no longer the case (in any valid solution so far)?
 
 auto dg = &foo.doStuff!add;
 assert(foo !is dg.ptr);
 
 Don't know if that's an unbreakable rule though...
That assertion is only currently valid for member function delegates. Nested functions store the frame pointer in "dg.ptr". I would say that "foo" in this case is no longer strictly a member function, but is some weird mix between a member function and an anonymous nested function, so it's perfectly reasonable to expect it to behave differently in that case. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




18:10:18 PDT ---


 The problem with Rainer's idea is that the callee would need to know the layout
 of the stack frame in the context in which the delegate was bound, which in
 general it cannot know.
The generated function MUST know the context of main, or else it can't call add. Remember, add is passed as an alias, not a delegate. Even if add is passed as a delegate, it's calling the delegate from main's stack-frame (i.e. two identical calls separated by a re-assignment of the delegate would call two different functions). Bear in mind that each call to doStuff with a different alias is a *different* instantiation, even for calls with the same inner function types because of the alias parameter. It is OK for each instantiation to be aware of the stack offset for 'this'. And it's 2 extra words, not 1. You need to store the 'array of context pointers' on the stack, which you do not need if you know the layout of the stack frame. If you think about it, it is actually very little different from Kenji's idea: uint doStuff(uint a, uint b, void** this) // not void* this { // (*this + 0) points the object Foo // (*this + 1) points the stack frame of main() Rainer's: uint doStuff(uint a, uint b, void* this) { // this points the stack frame of main() // *(this + N) points the object Foo Note the difference is that N is a compile time constant, like Kenji's 1. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




---


 
 The problem with Rainer's idea is that the callee would need to know the layout
 of the stack frame in the context in which the delegate was bound, which in
 general it cannot know.
The generated function MUST know the context of main, or else it can't call add. Remember, add is passed as an alias, not a delegate. Even if add is passed as a delegate, it's calling the delegate from main's stack-frame (i.e. two identical calls separated by a re-assignment of the delegate would call two different functions). Bear in mind that each call to doStuff with a different alias is a *different* instantiation, even for calls with the same inner function types because of the alias parameter. It is OK for each instantiation to be aware of the stack offset for 'this'.
No, because you can call the same template instantiation with different "this" pointers even though the "alias" parameter is the same. Each "this" pointer will be at a different location in the stack frame, so "foo" can't possibly know which one to use.
 And it's 2 extra words, not 1.  You need to store the 'array of context
 pointers' on the stack, which you do not need if you know the layout of the
 stack frame.  If you think about it, it is actually very little different from
 Kenji's idea:
 
 uint doStuff(uint a, uint b, void** this)  // not void* this
 {
     // (*this + 0) points the object Foo
     // (*this + 1) points the stack frame of main()
 
 Rainer's:
 
 uint doStuff(uint a, uint b, void* this)
 {
     // this points the stack frame of main()
     // *(this + N) points the object Foo
 
 Note the difference is that N is a compile time constant, like Kenji's 1.
With Kenji's idea, you have 2 pointers on the stack: struct multi_context { stack_frame* base_ptr; // pointer to start of stack frame T* this_ptr; // pointer } struct stack_frame { // other stuff multi_context context; } "foo" is called by passing in a pointer to the "multi_context" struct from which both the "this_ptr" and "base_ptr" can be obtained. With Rainer's idea, you have 1 pointer on the stack: struct stack_frame { // other stuff T* this_ptr; } That is only a difference of one :P Rainer's idea needs a "this_ptr" on the stack otherwise there is no way for "foo" to access it, whereas Kenji's version doesn't. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 06 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5710




05:52:41 PDT ---

 
 No, because you can call the same template instantiation with different "this"
 pointers even though the "alias" parameter is the same. Each "this" pointer
 will be at a different location in the stack frame, so "foo" can't possibly
 know which one to use.
Yes, you are right, thanks for explaining.
 With Kenji's idea, you have 2 pointers on the stack:
 
 struct multi_context {
     stack_frame* base_ptr; // pointer to start of stack frame
     T* this_ptr; // pointer 
 }
 
 struct stack_frame {
     // other stuff
     multi_context context;
 }
 
 "foo" is called by passing in a pointer to the "multi_context" struct from
 which both the "this_ptr" and "base_ptr" can be obtained.
Likely the this_ptr is repeated inside the stack frame for normal access during the function. Anyway, the point is moot since only Kenji's solution is valid. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
May 07 2013