www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - typeinfo[] construction

reply "Kris" <fu bar.com> writes:
How does one construct & expose a typeinfo array, plus the corresponding arg 
array, without actually calling a function? Is there a neat template trick 
to do this? Without allocating from the heap? Appreciate any suggestions. 
Nov 14 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <dlat7b$cpr$1 digitaldaemon.com>, Kris says...
How does one construct & expose a typeinfo array, plus the corresponding arg 
array, without actually calling a function? Is there a neat template trick 
to do this? Without allocating from the heap? Appreciate any suggestions. 

Well, nothing that qualifies as 'neat' anyway (you've probably been down this road before). You could roll a set of templates that accomodate up to n types:
 template TypeinfoList(T1, T2, T3){
 		static const TypeInfo[] TypeinfoList =[
 			typeid(T1),
 			typeid(T2),
 			typeid(T3)
 		];
 }

(BTW, anybody willing to draft up a template-vararg specification?) So yea, the above template keeps the data off of the heap and works great. As for "the corresponding arg array", I'm don't know what you're after. Maybe you could hit me with some pseudocode or a use-case? - EricAnderton at yahoo
Nov 14 2005
parent "Kris" <fu bar.com> writes:
Thanks Eric;

What I'm looking for is an inline version of the _arguments & _argptr pair 
that one has access to within a variadic-parameter function. That is, to 
construct the equivalent of _arguments & _argptr on the fly.

What you illustrate below is partway there. In a similar vein, is it 
possible to do /something/ like this:

template TypeInfoList()
{
  TypeInfo[] TypeInfoList (...) {return _arguments;}
}

auto ti = TypeInfoList!(7, 3.14159, "foo", x, y, z);



"pragma" <pragma_member pathlink.com> wrote in message 
news:dlb435$17i0$1 digitaldaemon.com...
 In article <dlat7b$cpr$1 digitaldaemon.com>, Kris says...
How does one construct & expose a typeinfo array, plus the corresponding 
arg
array, without actually calling a function? Is there a neat template trick
to do this? Without allocating from the heap? Appreciate any suggestions.

Well, nothing that qualifies as 'neat' anyway (you've probably been down this road before). You could roll a set of templates that accomodate up to n types:
 template TypeinfoList(T1, T2, T3){
 static const TypeInfo[] TypeinfoList =[
 typeid(T1),
 typeid(T2),
 typeid(T3)
 ];
 }

(BTW, anybody willing to draft up a template-vararg specification?) So yea, the above template keeps the data off of the heap and works great. As for "the corresponding arg array", I'm don't know what you're after. Maybe you could hit me with some pseudocode or a use-case? - EricAnderton at yahoo

Nov 14 2005
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Kris wrote:
 How does one construct & expose a typeinfo array, plus the corresponding arg 
 array, without actually calling a function? Is there a neat template trick 
 to do this? Without allocating from the heap? Appreciate any suggestions. 

Possible, I think, but likely somewhat messy. One of the problems I ran into while playing with this is that template specialization fails if you try to operate solely on parameter type. ie. template TI(int v) { ... } template TI(char v) { ... } TI!('a'); is ambiguous. As is: TI!(cast(char)'a'); You could get around this by building your parameter list like so: alias TI!(int,1, TI!(char,'a', Empty)) TwoParams; Which I suppose could be simplified to: alias MakeParams!(int,1, char,'a') TwoParams; But this still feels a tad clunky. It's worth noting that this doesn't manage to resolve the ambiguity either: struct Set1 { const int p1 = 1; const char p2 = 'a'; alias MakeParams!(p1,p2) Params; } However, Don's approach does, at the risk of being even more verbose: template p1() { const int p1 = 1; } template p2() { const char p2 = 'a'; } alias MakeParams(p1,p2) Params; Note that in this last example, the template parameters for MakeParams must be aliases, ie. template MakeParams(alias p1, alias p2) {...} What problem are you trying to solve? :-) I think this could be worked into something usable, but it may be easier with a specific goal in mind. Sean
Nov 14 2005
parent reply "Kris" <fu bar.com> writes:
Thanks, Sean.

Looking at it more closely, I'm not sure if it's really possible. Here's a 
rough, but compilable, example of what I getting at:

struct S {TypeInfo[] ti; void* args;}

template Foo(T = S)
{
        S Foo(...)
        {
                S s;
                s.ti = _arguments;
                s.args = _argptr;
                return s;
        }
}

void main()
{
        auto list = Foo!()(1, 2, 3, 4);

        // do something with list.args & list.ti
}

But that leaves pointers into potentially invalid stack space. Any further 
ideas?





"Sean Kelly" <sean f4.ca> wrote in message 
news:dlb5f1$1c1p$1 digitaldaemon.com...
 Kris wrote:
 How does one construct & expose a typeinfo array, plus the corresponding 
 arg array, without actually calling a function? Is there a neat template 
 trick to do this? Without allocating from the heap? Appreciate any 
 suggestions.

Possible, I think, but likely somewhat messy. One of the problems I ran into while playing with this is that template specialization fails if you try to operate solely on parameter type. ie. template TI(int v) { ... } template TI(char v) { ... } TI!('a'); is ambiguous. As is: TI!(cast(char)'a'); You could get around this by building your parameter list like so: alias TI!(int,1, TI!(char,'a', Empty)) TwoParams; Which I suppose could be simplified to: alias MakeParams!(int,1, char,'a') TwoParams; But this still feels a tad clunky. It's worth noting that this doesn't manage to resolve the ambiguity either: struct Set1 { const int p1 = 1; const char p2 = 'a'; alias MakeParams!(p1,p2) Params; } However, Don's approach does, at the risk of being even more verbose: template p1() { const int p1 = 1; } template p2() { const char p2 = 'a'; } alias MakeParams(p1,p2) Params; Note that in this last example, the template parameters for MakeParams must be aliases, ie. template MakeParams(alias p1, alias p2) {...} What problem are you trying to solve? :-) I think this could be worked into something usable, but it may be easier with a specific goal in mind. Sean

Nov 14 2005
parent reply Sean Kelly <sean f4.ca> writes:
Kris wrote:
 Thanks, Sean.
 
 Looking at it more closely, I'm not sure if it's really possible. Here's a 
 rough, but compilable, example of what I getting at:
 
 struct S {TypeInfo[] ti; void* args;}
 
 template Foo(T = S)
 {
         S Foo(...)
         {
                 S s;
                 s.ti = _arguments;
                 s.args = _argptr;
                 return s;
         }
 }
 
 void main()
 {
         auto list = Foo!()(1, 2, 3, 4);
 
         // do something with list.args & list.ti
 }
 
 But that leaves pointers into potentially invalid stack space. Any further 
 ideas?

The templates in your example really aren't necessary, given what the code is doing, so assuming it's okay for this stuff to be sorted out at run-time, perhaps you should simply focus on copying the _arguments array and _argptr data to the heap. Here's a quick go at it that seems to work: import std.c.stdio; import std.c.string; struct ParamList { TypeInfo[] info; void* args; } ParamList getParamList( ... ) { ParamList list; size_t size = 0; list.info = _arguments.dup; foreach( TypeInfo t; _arguments ) size += t.tsize(); list.args = new ubyte[size]; memcpy( list.args, _argptr, size ); return list; } void main() { ParamList list = getParamList( 1, 2, 3 ); for( int i = 0; i < 3; ++i ) printf( "%i\n", cast(int) (cast(int*)list.args)[i] ); }
Nov 14 2005
parent reply "Kris" <fu bar.com> writes:
Thanks again, Sean.

Was hoping to construct the list at compile time, and avoid the heap 
allocation. D apparently cannot populate non-static arrays of any type, let 
alone variable type. Seems I was hoping for too much :-(




"Sean Kelly" <sean f4.ca> wrote in message 
news:dlbmt8$2k0i$1 digitaldaemon.com...
 Kris wrote:
 Thanks, Sean.

 Looking at it more closely, I'm not sure if it's really possible. Here's 
 a rough, but compilable, example of what I getting at:

 struct S {TypeInfo[] ti; void* args;}

 template Foo(T = S)
 {
         S Foo(...)
         {
                 S s;
                 s.ti = _arguments;
                 s.args = _argptr;
                 return s;
         }
 }

 void main()
 {
         auto list = Foo!()(1, 2, 3, 4);

         // do something with list.args & list.ti
 }

 But that leaves pointers into potentially invalid stack space. Any 
 further ideas?

The templates in your example really aren't necessary, given what the code is doing, so assuming it's okay for this stuff to be sorted out at run-time, perhaps you should simply focus on copying the _arguments array and _argptr data to the heap. Here's a quick go at it that seems to work: import std.c.stdio; import std.c.string; struct ParamList { TypeInfo[] info; void* args; } ParamList getParamList( ... ) { ParamList list; size_t size = 0; list.info = _arguments.dup; foreach( TypeInfo t; _arguments ) size += t.tsize(); list.args = new ubyte[size]; memcpy( list.args, _argptr, size ); return list; } void main() { ParamList list = getParamList( 1, 2, 3 ); for( int i = 0; i < 3; ++i ) printf( "%i\n", cast(int) (cast(int*)list.args)[i] ); }

Nov 14 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
Kris wrote:
 Thanks again, Sean.
 
 Was hoping to construct the list at compile time, and avoid the heap 
 allocation. D apparently cannot populate non-static arrays of any type, let 
 alone variable type. Seems I was hoping for too much :-(

I still think this might be possible, but doing so seems nontrivial. I foresee some char string voodoo ala Don's itoa example to build the _argptr data segment, and the syntax to construct the list wouldn't be quite as painless. Unless there's a pressing reason to do this at compile-time it's probably not worth the trouble :-) You can always initialize this stuff on module load anyway. Sean
Nov 14 2005
prev sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
Kris wrote:
 D apparently cannot populate non-static arrays of any
 type, let alone variable type. Seems I was hoping for too much :-(

I'm not sure, but I'd be thoroughly amazed if that was possible, even in theory. Non-static in itself implies runtime, right? That in turn implies heap allocation, right? And at compile time we don't even have that heap, right?
Nov 15 2005
parent reply kris <fu bar.org> writes:
Georg Wrede wrote:
 Kris wrote:
 
 D apparently cannot populate non-static arrays of any
 type, let alone variable type. Seems I was hoping for too much :-(

I'm not sure, but I'd be thoroughly amazed if that was possible, even in theory. Non-static in itself implies runtime, right?

Yes and no. Theoretically, the space required can be allocated upon the stack. Optionally the TypeInfo[] noted can be constructed and populated at compile time also. What's left is the population of the _arptr value array: that would be done at runtime; but inline.
 
 That in turn implies heap allocation, right?

In this case, I was looking for a way to get these on the stack.
 
 And at compile time we don't even have that heap, right?

Nov 15 2005
parent Sean Kelly <sean f4.ca> writes:
kris wrote:
 Georg Wrede wrote:
 Kris wrote:

 D apparently cannot populate non-static arrays of any
 type, let alone variable type. Seems I was hoping for too much :-(

I'm not sure, but I'd be thoroughly amazed if that was possible, even in theory. Non-static in itself implies runtime, right?

Yes and no. Theoretically, the space required can be allocated upon the stack. Optionally the TypeInfo[] noted can be constructed and populated at compile time also. What's left is the population of the _arptr value array: that would be done at runtime; but inline.

Theoretically, I think this could be done at compile-time by building a char string containing the appropriate data and assigning a const void* to it. Thus the three parameters: char 'a' char 'b' int 5 would be encoded to something roughly like this (ignoring big/little endian rules and such): "ab\0\0\u5\0\0\0" using template code. But doing this elegantly would likely require a set of template operations to build upon, and unless Don's been quite busy in the past week I doubt this exists yet. For the moment, I'd mark this up as possibly good fodder for a paper on advanced D template programming and live with a simpler solution. Sean
Nov 15 2005