digitalmars.D.bugs - [Issue 7897] New: Problem with alias template parameter
- d-bugmail puremagic.com (64/64) Apr 13 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (25/25) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (23/23) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (23/23) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (37/37) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (9/11) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (15/16) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (30/46) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (11/32) Apr 20 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
- d-bugmail puremagic.com (35/53) Apr 21 2012 http://d.puremagic.com/issues/show_bug.cgi?id=7897
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Summary: Problem with alias template parameter Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nobody puremagic.com ReportedBy: turkeyman gmail.com I've boiled this down as much as I can. My use case isn't clearly reflected here (significantly more complex). import std.traits; struct ExternFunction { string name; void* pFunction; } // loose function extern(C) void function() globalFunction; // functions contained in a struct struct Debug { extern(C) void function( const char* format, ... ) outputDebug; } __gshared Debug d; void main() { const(ExternFunction)* pImports = null; // register loose function is okay HookupEngineFunction!( globalFunction )( pImports ); // register function in struct (doesn't work, won't take alias for some reason?) HookupEngineFunction!( d.outputDebug )( pImports ); // register whole struct (fails via internal call to the function above, but with a different complaint) HookupEngineModule!( d )( pImports ); } private: // hook up a struct full of callback pointers void HookupEngineModule( alias s )( const(ExternFunction)* pImports ) { // iterate struct members foreach( m; __traits( allMembers, typeof( s ) ) ) { // !!! getMember doesn't work here... HookupEngineFunction!( __traits( getMember, s, m ) )( pImports ); } } void HookupEngineFunction( alias funcptr )( const(ExternFunction)* pImports ) { alias typeof( funcptr ) Type; static if( isFunctionPointer!Type ) { const(ExternFunction)* pExtern = pImports; // FindImport(...); funcptr = cast(Type)pExtern.pFunction; } } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 13 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Walter Bright <bugzilla digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |bugzilla digitalmars.com 11:44:45 PDT --- ====== // register function in struct (doesn't work, won't take alias for some reason?) HookupEngineFunction!( d.outputDebug )( pImports ); ====== This is failing to compile because outputDebug is a non-static member function of struct Debug. This means that a 'this' pointer is required. The parameter 'alias funcptr' to HookupEngineFunction requires an argument that is a symbolic alias. But you're supplying a runtime value, d.outputDebug, that cannot be evaluated at compile time. In other words, d.outputDebug would be a delegate, and delegates can only be constructed at runtime because they consist of a pair: a 'this' pointer and the address of the function. The 'this' pointer cannot be determined at compile time. If you make Debug.outputDebug a static member function, it will compile. This is not a compiler bug. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Walter Bright <bugzilla digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |INVALID 11:52:56 PDT --- ======== // !!! getMember doesn't work here... HookupEngineFunction!( __traits( getMember, s, m ) )( pImports ); ======== This is a similar issue. s here is a variable, and getMember is expecting a type. Rewriting as: HookupEngineFunction!( __traits( getMember, typeof(s), m ) )( pImports ); gets past that. But then we're back to the previous issue, no 'this' pointer at compile time. This is not a compiler bug, either. I suspect what you are doing is trying to do C++ "pointers to members". Perhaps this will help: http://www.drdobbs.com/blogs/cpp/231600610 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Actually no, I'm not trying to do pointer to member type stuff. As I saw it, this is just a single function pointer (surely that is strictly defined by the 'function' keyword?) in a struct. I'm addressing a static (well, __gshared) instance, 'd'. Shouldn't d be a singular instance, allocated in the data block, and thereby accessible at compile time? I figure this should effectively be no different than a __gshared void*. Have I misunderstood something rather fundamental about __gshared? This should make it effectively identical to a C global right? Ie, singular instance, allocated in the data block, and address known at compile time. Under that assumption, there's no technical reason the compiler shouldn't be able to alias that variable at compile time and generate appropriate code. If I'm mistaken about that, how do I produce a variable effectively identical to a C global? Like I say, this is a very boiled down case, and infact, this particular case is no longer directly relevant in my code, but the same scenario is coming up frequently. That is, I have a global instance of a structure, which I expect should be accessible at compile time... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Manu <turkeyman gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID | Here, I've simplified it some more. This is functionally identical to the first example, I just rephrased it to 'int' to remove any confusion about function pointers and intent. // member contained in a struct struct Thing { int x; } Thing thing; // this is effectively identical to declaring 'int x;' globally, it's just wrapped in a thin struct int x; // i'll also do it directly, to prove it works. void main() { // these 3 statements should be effectively identical thing.x = 10; // this works, obviously AliasTheStruct!( thing )(); // this works AliasTheInt!( thing.x )(); // this is the problem AliasTheInt!( x )(); // of course, this works fine } void AliasTheStruct( alias a )() { a.x = 10; } void AliasTheInt( alias a )() { a = 10; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 16:43:49 PDT ---As I saw it, this is just a single function pointer (surely that is strictly defined by the 'function' keyword?) in a struct.It isn't a function pointer. Non-static member methods are never a simple function pointer, they always require a 'this' pointer as well, as they are delegates. This is not like C++ member function pointers. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 Walter Bright <bugzilla digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|REOPENED |RESOLVED Resolution| |INVALID 16:49:40 PDT ---AliasTheInt!( thing.x )(); // this is the problemRight. It's a problem because thing.x is being passed as an *alias* parameter. An alias must be symbol, not a computation on a symbol. thing.x is semantically equivalent to: *(&thing + x.offsetof) which is not a symbol. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897extern(C) void function( const char* format, ... ) outputDebug; <- this is a function pointer. It's not a method, or a delegate. I have no idea why you're introducing methods and delegates into the conversation. But it doesn't matter, it's irrelevant to the problem here...As I saw it, this is just a single function pointer (surely that is strictly defined by the 'function' keyword?) in a struct.It isn't a function pointer. Non-static member methods are never a simple function pointer, they always require a 'this' pointer as well, as they are delegates. This is not like C++ member function pointers.Oooohkay, so now we get to the bottom of it. Right, well I didn't realise that restriction. I just assumed any statically addressable variable was alias-able. So this is a feature request then, not a bug. There's still technically no reason it shouldn't work, it's just not quite how alias is written? How much trouble would it be to extend 'alias' to include an offset value? This restriction makes it very difficult to drill down into structures via recursive enumeration. The workaround I've had to use is to use strings instead of aliases that can mixin an absolute reference, but it's really untidy, and again, messes with the editor a lot (syntax hilighting, auto-complete, etc). It also requires mixin(a) everywhere, and there are lots of cases where mixin() is invalid in the middle of an expression. This requires a further workaround to build the whole expression into a string and mix the whole thing in. I wonder if you could use lowering here to produce the same result via lowered mixin? Although it sounds much cleaner to simply add an offset to aliases. Another alternative could be to just invent the appropriate symbol when a reference like this appears. Symbol names follow the d scoping patterns right? In this case, the symbol would just be my.module.thing.x (or with whatever mangling happens to appear in D symbols). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------AliasTheInt!( thing.x )(); // this is the problemRight. It's a problem because thing.x is being passed as an *alias* parameter. An alias must be symbol, not a computation on a symbol. thing.x is semantically equivalent to: *(&thing + x.offsetof) which is not a symbol.
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897 18:00:42 PDT ---Oooohkay, so now we get to the bottom of it. Right, well I didn't realise that restriction. I just assumed any statically addressable variable was alias-able.Any *symbol* is aliasable. It isn't about addresses.So this is a feature request then, not a bug. There's still technically no reason it shouldn't work, it's just not quite how alias is written? How much trouble would it be to extend 'alias' to include an offset value?This is a significant redesign of what alias is.This restriction makes it very difficult to drill down into structures via recursive enumeration. The workaround I've had to use is to use strings instead of aliases that can mixin an absolute reference, but it's really untidy, and again, messes with the editor a lot (syntax hilighting, auto-complete, etc). It also requires mixin(a) everywhere, and there are lots of cases where mixin() is invalid in the middle of an expression. This requires a further workaround to build the whole expression into a string and mix the whole thing in. I wonder if you could use lowering here to produce the same result via lowered mixin? Although it sounds much cleaner to simply add an offset to aliases.It isn't simple, because having an offset makes it an expression, not a symbol. It's a substantial redesign.Another alternative could be to just invent the appropriate symbol when a reference like this appears. Symbol names follow the d scoping patterns right? In this case, the symbol would just be my.module.thing.x (or with whatever mangling happens to appear in D symbols).Can't you just pass a pointer around? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 20 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7897Yeah I see now, but I don't think that's what people intuitively expect. I've asked for help on various manifestations of this matter on IRC quite a few times, and so far, zero out of all the people who have helped me seem to understand that either. They almost all just said something like "yeah it seems to be a bit finicky, have you tried this, try passing a this kind of thing, try changing it this way", etc .. suggesting that nobody had any understanding of what they were trying to do, just fiddling with it until it stopped complaining. Perhaps it would be a good idea to add some informative error message stating the limitation. The whinge about 'this' certainly lost all meaning to me at least, I was absolutely convinced 'this' was perfectly calculable at compile time, and it should work. There was no mention of symbols.Oooohkay, so now we get to the bottom of it. Right, well I didn't realise that restriction. I just assumed any statically addressable variable was alias-able.Any *symbol* is aliasable. It isn't about addresses.:/ .. I think though that the mistake I made is what most people expect should be possible. At least all those that have tried to help me with it so far.So this is a feature request then, not a bug. There's still technically no reason it shouldn't work, it's just not quite how alias is written? How much trouble would it be to extend 'alias' to include an offset value?This is a significant redesign of what alias is.I don't think I can get a pointer to TLS data at compile time can I? Using the alias still allows the compiler to generate the correct TLS dereferencing code. In the cases where I use __gshared I suppose I could, but I'm not sure this would simplify the code at all. I can imagine it being more difficult to follow than the mixin version. Carrying a pointer interferes with typeof(), it also interferes with the ability to do allMemers, getMember on the instance (as opposed to the type). getMember only works on aliases(?), so I think I would need to generate mixin code that uses the strings produced by allMembers to generate expressions that reference the data I'm interested in anyway. I'll have a go at it, see how far I get. But I can imagine the result being very similar to the mixin approach, and probably no simpler for a 3rd person to follow. A direct alias is certainly be the most clear and concise way to go. Is it impossible to invent a new symbol when this case is encountered like I suggest? That could be a simple solution that fits the existing model. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------Another alternative could be to just invent the appropriate symbol when a reference like this appears. Symbol names follow the d scoping patterns right? In this case, the symbol would just be my.module.thing.x (or with whatever mangling happens to appear in D symbols).Can't you just pass a pointer around?
Apr 21 2012