Jump to page: 1 2
Thread overview
Problem: Cannot create class out of nothing using witchcraft
Oct 15, 2013
DoctorCaptain
Oct 15, 2013
Benjamin Thaut
Oct 15, 2013
Benjamin Thaut
Oct 15, 2013
DoctorCaptain
Oct 15, 2013
DoctorCaptain
Oct 15, 2013
DoctorCaptain
Oct 16, 2013
DoctorCaptain
Oct 16, 2013
Benjamin Thaut
Oct 16, 2013
DoctorCaptain
Oct 16, 2013
Benjamin Thaut
Oct 16, 2013
Benjamin Thaut
Oct 16, 2013
Benjamin Thaut
Oct 16, 2013
Benjamin Thaut
Oct 16, 2013
DoctorCaptain
Oct 16, 2013
DoctorCaptain
Oct 16, 2013
DoctorCaptain
Oct 16, 2013
Benjamin Thaut
Oct 15, 2013
Artur Skawina
October 15, 2013
dmd v2.063.2

Hi there! I'm terribly hopeful that you're more interested in the
problem at hand than my choice of title.

I've been using D for a while as my language of choice for
various projects here and there, and I've recently discovered
that template programming is magic. This is good. As part of the
process of finding anything magic that also works, I've been
going completely overboard with it. This involves, among other
things, creating empty classes using templates and mixins at
compile time, to build an inheritance hierarchy to do fancy
things. This is all essentially irrelevant, but brings us to my
issue.

The next logical step in my adventure here was to see if I could
create classes that weren't empty, but in fact has data members,
generated at compile time using variadic templates. The first
run-through went super well, and I was able to create classes
with arbitrary primitive data types.

However, ultimately I wanted these compile-time-generated classes
with arbitrary data members to have data members that were of the
type of the other classes that were also generated at compile
time.

That is to say, I want to generate, at compile time, classes like
this:

class MyClass {
     crazyTemplate!("MagicClassOne").MagicClassOne t1;
     crazyTemplate2!("MagicClassTwo").MagicClassTwo t2;
}

such that crazyTemplate and crazyTemplate2 each generate a class
definition at compile time, accessible as defined by the string
parameter.

For example:

template crazyTemplate(string classname) {
     mixin(`class ` ~ className ~ ` {}`);
}

The bare class-generating templates work, and generating classes
that have arbitrary members at compile time using variadic
templates given an arbitrary list of basic types works, but as
soon as I try to use these template-generated classes as the
types of the members of this variadic template, things go awry.

I feel like what I'm trying to explain is a bit difficult to
parse without a minimal working example, so here is one:

code
-------------
import std.stdio;
import std.typetuple;
import std.traits;
import std.conv;

class BaseClass {}

template ChildT(string className)
{
     mixin(`class ` ~ className ~ ` : BaseClass {}`);
}

template isChildOrBaseClass(T)
{
     enum bool isChildOrBaseClass = is(T : BaseClass);
}

template GrabBagT(string className, T...)
     if (allSatisfy!(isChildOrBaseClass, T))
{
     mixin(genClassStr!(T)(className));
}

string genClassStr(T...)(string className)
{
     string classStr = "";
     classStr ~= `static class ` ~ className ~ ` : BaseClass`;
     classStr ~= `{`;
     // Demonstrate that the template itself is not the problem
     classStr ~= `    ChildT!("BestChild").BestChild t1000;`;
     // Add arbitrary data members
     foreach (i, TI; T)
     {
         // Neither of these work with the generated classes, but
the first
         // will work if GrabBagT is called with primitive types
and its
         // constraint is commented out
         //classStr ~= fullyQualifiedName!(TI) ~ ` t` ~
to!(string)(i) ~ `;`;
         //classStr ~= __traits(identifier, TI) ~ ` t` ~
to!(string)(i) ~ `;`;
     }
     classStr ~= `    void printAttempts() {`;
     foreach (i, TI; T)
     {
         classStr ~= `    writeln(` ~ to!string(i) ~ `);`;
     }
     classStr ~= `    }`;
     classStr ~= `}`;
     return classStr;
}

int main(string[] args)
{
     alias ChildT!("WorstChild").WorstChild WorstChild;
     alias ChildT!("MiddleChild").MiddleChild MiddleChild;

     auto magicObject = new GrabBagT!(
         "MagicClass", WorstChild, MiddleChild).MagicClass();

     //auto magicObject = new GrabBagT!(
     //    "MagicClass", int, float).MagicClass();

     magicObject.printAttempts();

     return 0;
}
-------------

That should compile and print out "0" and "1". Note the template
constraint that bars the template instantiator from trying to
instantiate GrabBagT with anything other than types that can be
implicitly treated as type BaseClass. I tried using
__traits(identifier) and fullyQualifiedName to get the actual
type of the alias passed in (like the BestChild declaration), but
the latter gives a mangled name, and the former gives just
whatever the bare alias was.

In any case. If the fullyQualifiedName line is uncommented, the
error is:

------------
classAttributeGen.d(22): Error: undefined identifier
'__T6ChildTVAyaa10_576f7273744368696c64Z'
classAttributeGen.d(22): Error:
classAttributeGen.__T6ChildTVAyaa10_576f7273744368696c64Z.WorstChild
is used as a type
classAttributeGen.d(22): Error: undefined identifier
'__T6ChildTVAyaa11_4d6964646c654368696c64Z'
classAttributeGen.d(22): Error:
classAttributeGen.__T6ChildTVAyaa11_4d6964646c654368696c64Z.MiddleChild
is used as a type
classAttributeGen.d(54): Error: template instance
classAttributeGen.GrabBagT!("MagicClass", WorstChild,
MiddleChild) error instantiating
------------

If the __traits line is uncommented instead, the error is:

------------
classAttributeGen.d(22): Error: undefined identifier WorstChild
classAttributeGen.d(22): Error: undefined identifier MiddleChild
classAttributeGen.d(54): Error: template instance
classAttributeGen.GrabBagT!("MagicClass", WorstChild,
MiddleChild) error instantiating
------------

Of particular note is that we are giving the class a
ChildT!("BestChild").BestChild member, which shows that simply
using the empty-class-generating-templates is not the problem,
but rather the way the type tuple is fed in to the variadic
template.

If the GrabBagT constraint is commented out, the uncommented
magicObject instantiation is commented, the commented magicObject
instantiation is uncommented, and the fullyQualifiedName line is
uncommented, then this will also compile, demonstrating that a
tuple of primitive data types can be used to generate classes at
compile time with arbitrary, primitive data members.

Ultimately, the problem I am trying to solve is generating class
definitions at compile time with arbitrary, templated data
members. If this is the wrong way to do it, by all means point me
in the right direction. However, as an exercise to the community,
is it even possible to do it the way I'm attempting here? Is it
possible to do at all? Is there something awful about how
templates are passed around that makes it fundamentally
impossible to get their underlying type information, like with
the working BestClass member, if they're passed in as template
type parameters?

If what I am asking is unclear, I will be more than happy to
explain in a different way. I tried to be simultaneously as
succinct and as comprehensive as possible with what the issue is.
I also tried to find the answer to this problem, as I have with
every other problem I've faced with D, through an exhaustive
search of the various resources available to us, but alas I could
find nothing. Of course, this is a fairly esoteric scenario, so
that's entirely acceptable. That said, ideally the definitive
answer can be found in future searches by finding this post.

With a quiet but definitive stepping-aside to the inquiry of
"What why are you doing this."
October 15, 2013
Am 15.10.2013 10:03, schrieb DoctorCaptain:
> dmd v2.063.2
>
> Hi there! I'm terribly hopeful that you're more interested in the
> problem at hand than my choice of title.
>
> I've been using D for a while as my language of choice for
> various projects here and there, and I've recently discovered
> that template programming is magic. This is good. As part of the
> process of finding anything magic that also works, I've been
> going completely overboard with it. This involves, among other
> things, creating empty classes using templates and mixins at
> compile time, to build an inheritance hierarchy to do fancy
> things. This is all essentially irrelevant, but brings us to my
> issue.
>
> The next logical step in my adventure here was to see if I could
> create classes that weren't empty, but in fact has data members,
> generated at compile time using variadic templates. The first
> run-through went super well, and I was able to create classes
> with arbitrary primitive data types.
>
> However, ultimately I wanted these compile-time-generated classes
> with arbitrary data members to have data members that were of the
> type of the other classes that were also generated at compile
> time.
>
> That is to say, I want to generate, at compile time, classes like
> this:
>
> class MyClass {
>       crazyTemplate!("MagicClassOne").MagicClassOne t1;
>       crazyTemplate2!("MagicClassTwo").MagicClassTwo t2;
> }
>
> such that crazyTemplate and crazyTemplate2 each generate a class
> definition at compile time, accessible as defined by the string
> parameter.
>
> For example:
>
> template crazyTemplate(string classname) {
>       mixin(`class ` ~ className ~ ` {}`);
> }
>
> The bare class-generating templates work, and generating classes
> that have arbitrary members at compile time using variadic
> templates given an arbitrary list of basic types works, but as
> soon as I try to use these template-generated classes as the
> types of the members of this variadic template, things go awry.
>
> I feel like what I'm trying to explain is a bit difficult to
> parse without a minimal working example, so here is one:
>
> code
> -------------
> import std.stdio;
> import std.typetuple;
> import std.traits;
> import std.conv;
>
> class BaseClass {}
>
> template ChildT(string className)
> {
>       mixin(`class ` ~ className ~ ` : BaseClass {}`);
> }
>
> template isChildOrBaseClass(T)
> {
>       enum bool isChildOrBaseClass = is(T : BaseClass);
> }
>
> template GrabBagT(string className, T...)
>       if (allSatisfy!(isChildOrBaseClass, T))
> {
>       mixin(genClassStr!(T)(className));
> }
>
> string genClassStr(T...)(string className)
> {
>       string classStr = "";
>       classStr ~= `static class ` ~ className ~ ` : BaseClass`;
>       classStr ~= `{`;
>       // Demonstrate that the template itself is not the problem
>       classStr ~= `    ChildT!("BestChild").BestChild t1000;`;
>       // Add arbitrary data members
>       foreach (i, TI; T)
>       {
>           // Neither of these work with the generated classes, but
> the first
>           // will work if GrabBagT is called with primitive types
> and its
>           // constraint is commented out
>           //classStr ~= fullyQualifiedName!(TI) ~ ` t` ~
> to!(string)(i) ~ `;`;
>           //classStr ~= __traits(identifier, TI) ~ ` t` ~
> to!(string)(i) ~ `;`;
>       }
>       classStr ~= `    void printAttempts() {`;
>       foreach (i, TI; T)
>       {
>           classStr ~= `    writeln(` ~ to!string(i) ~ `);`;
>       }
>       classStr ~= `    }`;
>       classStr ~= `}`;
>       return classStr;
> }
>
> int main(string[] args)
> {
>       alias ChildT!("WorstChild").WorstChild WorstChild;
>       alias ChildT!("MiddleChild").MiddleChild MiddleChild;
>
>       auto magicObject = new GrabBagT!(
>           "MagicClass", WorstChild, MiddleChild).MagicClass();
>
>       //auto magicObject = new GrabBagT!(
>       //    "MagicClass", int, float).MagicClass();
>
>       magicObject.printAttempts();
>
>       return 0;
> }
> -------------
>
> That should compile and print out "0" and "1". Note the template
> constraint that bars the template instantiator from trying to
> instantiate GrabBagT with anything other than types that can be
> implicitly treated as type BaseClass. I tried using
> __traits(identifier) and fullyQualifiedName to get the actual
> type of the alias passed in (like the BestChild declaration), but
> the latter gives a mangled name, and the former gives just
> whatever the bare alias was.
>
> In any case. If the fullyQualifiedName line is uncommented, the
> error is:
>
> ------------
> classAttributeGen.d(22): Error: undefined identifier
> '__T6ChildTVAyaa10_576f7273744368696c64Z'
> classAttributeGen.d(22): Error:
> classAttributeGen.__T6ChildTVAyaa10_576f7273744368696c64Z.WorstChild
> is used as a type
> classAttributeGen.d(22): Error: undefined identifier
> '__T6ChildTVAyaa11_4d6964646c654368696c64Z'
> classAttributeGen.d(22): Error:
> classAttributeGen.__T6ChildTVAyaa11_4d6964646c654368696c64Z.MiddleChild
> is used as a type
> classAttributeGen.d(54): Error: template instance
> classAttributeGen.GrabBagT!("MagicClass", WorstChild,
> MiddleChild) error instantiating
> ------------
>
> If the __traits line is uncommented instead, the error is:
>
> ------------
> classAttributeGen.d(22): Error: undefined identifier WorstChild
> classAttributeGen.d(22): Error: undefined identifier MiddleChild
> classAttributeGen.d(54): Error: template instance
> classAttributeGen.GrabBagT!("MagicClass", WorstChild,
> MiddleChild) error instantiating
> ------------
>
> Of particular note is that we are giving the class a
> ChildT!("BestChild").BestChild member, which shows that simply
> using the empty-class-generating-templates is not the problem,
> but rather the way the type tuple is fed in to the variadic
> template.
>
> If the GrabBagT constraint is commented out, the uncommented
> magicObject instantiation is commented, the commented magicObject
> instantiation is uncommented, and the fullyQualifiedName line is
> uncommented, then this will also compile, demonstrating that a
> tuple of primitive data types can be used to generate classes at
> compile time with arbitrary, primitive data members.
>
> Ultimately, the problem I am trying to solve is generating class
> definitions at compile time with arbitrary, templated data
> members. If this is the wrong way to do it, by all means point me
> in the right direction. However, as an exercise to the community,
> is it even possible to do it the way I'm attempting here? Is it
> possible to do at all? Is there something awful about how
> templates are passed around that makes it fundamentally
> impossible to get their underlying type information, like with
> the working BestClass member, if they're passed in as template
> type parameters?
>
> If what I am asking is unclear, I will be more than happy to
> explain in a different way. I tried to be simultaneously as
> succinct and as comprehensive as possible with what the issue is.
> I also tried to find the answer to this problem, as I have with
> every other problem I've faced with D, through an exhaustive
> search of the various resources available to us, but alas I could
> find nothing. Of course, this is a fairly esoteric scenario, so
> that's entirely acceptable. That said, ideally the definitive
> answer can be found in future searches by finding this post.
>
> With a quiet but definitive stepping-aside to the inquiry of
> "What why are you doing this."

If I move the alias declarations of WorstChild and MiddleChild outside of main end then uncomment the __traits(identifier, ...) line it works.

-- 
Kind Regards
Benjamin Thaut
October 15, 2013
Your going way to complicated by actually passing the variadic arguments to the generator function. If you don't pass the variadic arguments to the generator function its way simpler and also works ;-)

http://dpaste.dzfl.pl/59e2547b
October 15, 2013
On 10/15/13 10:03, DoctorCaptain wrote:
> If what I am asking is unclear, I will be more than happy to explain in a different way. I tried to be simultaneously as succinct and as comprehensive as possible with what the issue is.

I'm not sure what exactly you're trying to do, but...

The issue is just that you are trying to access types that are
not available inside the GrabBagT template. With /built-in/ types
this of course works, as 'int' etc are always known.
One way to deal with that would be:

   template GrabBagT(string className, T...)
        if (allSatisfy!(isChildOrBaseClass, T))
   {
        mixin(genClassStr!(T.length)(className));
   }

   string genClassStr(size_t TL)(string className)
   {
        string classStr = "";
        classStr ~= `static class ` ~ className ~ ` : BaseClass`;
        classStr ~= `{`;
        // Demonstrate that the template itself is not the problem
        classStr ~= `    ChildT!("BestChild").BestChild t1000;`;
        // Add arbitrary data members
        foreach (i; 0..TL)
            classStr ~= "T["~ to!(string)(i) ~ `] t` ~ to!(string)(i) ~ `;`;
        classStr ~= `    void printAttempts() {`;
        foreach (i; 0..TL)
            classStr ~= `    writeln(` ~ to!string(i) ~ `);`;
        classStr ~= `    }`;
        classStr ~= `}`;
        return classStr;
   }

artur
October 15, 2013
On Tuesday, 15 October 2013 at 13:14:46 UTC, Benjamin Thaut wrote:
> Your going way to complicated by actually passing the variadic arguments to the generator function. If you don't pass the variadic arguments to the generator function its way simpler and also works ;-)
>
> http://dpaste.dzfl.pl/59e2547b

Thank you for your responses!

The following is a modified version of my original post code that incorporates a bit from all the answers I received, and certainly puts me farther along than I was:

http://dpaste.dzfl.pl/f7508d25

Taking Benjamin Thaut's suggestion to move the alias's into the global scope, GrabBagT now has access to the types it needs to know about, and my witchcraft abomination of a magic class works as long as everything is available in the same file.

However.

My original goal, going back to how I want to use this in the project I'm working on, is to define GrabBagT, and the associated templates, in a different file, such that I need only import the file and call:

auto magicObject = new GrabBagT!("MagicClass", SomeTypeAlias, SomeOtherTypeAlias).MagicClass();

Which brings us back to the original problem, that passing in aliases to instantiations of templates doesn't work, because the type information is lost. I understand the fundamental issue you folks were bringing up in your posts: GrabBagT cannot possibly actually have access to the real types of the aliases it's receiving, as those types aren't available in its scope (which is why bringing the aliases originally defined within main() out into the global scope makes things work).

But then this raises another fundamental issue, as I'm doing this exact thing successfully (passing aliases of template instantiations to other templates), where the only difference is the receiving templates do not have variadic parameters, and I throw the actual template parameter into the mixin itself. That is to say:

If the template I am trying to instantiate IS NOT variadic, and I pass in an alias of an instantiated template, then the receiving template has all of the type information it needs. Example: dpaste.dzfl.pl/6d618af9

If the template I am trying to instantiate IS variadic, and I pass in a variadic list of aliases of instantiated templates, then the receiving template appears unable to retrieve all of the type information it needs out of each of the indexes of the variadic parameter. We get close with this next example, but the problem appears to be that it tries to create a static array of the tuple T of length i, instead of indexing into it to get the type (but if you provide an i greater than the actual length of the tuple, it complains about going out of bounds of the tuple length, meaning that it IS in fact aware that it's supposed to be indexing into a type tuple): dpaste.dzfl.pl/ff8a5b9d

Given that the compilation error messages in the last DPaste refer to the mixed in code after the class definition string is generated and returned, the issue has to be in the way the type tuple is treated, itself.

So, first, the template argument (variadic or otherwise) needs to be part of the STRING that is constructed and passed back to the mixin, so that it can then just naturally access GrabBagT's T type tuple parameter. This is how the non-variadic DPaste example works.

Second, the variadic version seems to fail because the type tuple is not indexed correctly, to retrieve the type at that index, because it instead appears to try to make a static array of the whole tuple (which is odd because if you try to index the tuple with an index beyond its length, it suddenly knows it's a type tuple again).

And to be absolutely clear, the underlying goal is to generate a class definition at runtime, which I can mix in and then instantiate, that can contain an arbitrary list of data members that are themselves generated at compile time by their own templates. I have demonstrated that it is possible to do this with a single arbitrary template instantiation in dpaste.dzfl.pl/6d618af9 , but as soon as we try to do it with type tuples, it chokes. I am not sure if this is a compiler bug or I'm just out of my mind, but again, for the sake of academic advancement, lets try to solve the problem in complete disregard of whether we should.

If any part of my explanation of our current status on this problem is unclear, I would be happy to explain in an alternate way.

Thank you again!
October 15, 2013
Fixing links:

> If the template I am trying to instantiate IS NOT variadic, and I pass in an alias of an instantiated template, then the receiving template has all of the type information it needs. Example: dpaste.dzfl.pl/6d618af9

http://dpaste.dzfl.pl/6d618af9

> If the template I am trying to instantiate IS variadic, and I pass in a variadic list of aliases of instantiated templates, then the receiving template appears unable to retrieve all of the type information it needs out of each of the indexes of the variadic parameter. We get close with this next example, but the problem appears to be that it tries to create a static array of the tuple T of length i, instead of indexing into it to get the type (but if you provide an i greater than the actual length of the tuple, it complains about going out of bounds of the tuple length, meaning that it IS in fact aware that it's supposed to be indexing into a type tuple): dpaste.dzfl.pl/ff8a5b9d

http://dpaste.dzfl.pl/ff8a5b9d

> And to be absolutely clear, the underlying goal is to generate a class definition at runtime, which I can mix in and then instantiate, that can contain an arbitrary list of data members that are themselves generated at compile time by their own templates. I have demonstrated that it is possible to do this with a single arbitrary template instantiation in dpaste.dzfl.pl/6d618af9 , but as soon as we try to do it with type tuples, it chokes. I am not sure if this is a compiler bug or I'm just out of my mind, but again, for the sake of academic advancement, lets try to solve the problem in complete disregard of whether we should.

http://dpaste.dzfl.pl/6d618af9
October 15, 2013
I missed an extremely critical point. The working example with the single arbitrary template instantiation as a data member of the generated class, http://dpaste.dzfl.pl/6d618af9 , has the template instantiation aliases inside of main, meaning the alias is NOT within the scope of GrabBagT, but it is able to get all of the type information it needs from the alias being passed in. Which reaffirms to me that the problem is not about whether GrabBagT needs to be able to see what the alias refers to (clearly it can figure it out), but that once these aliases are wrapped up into a tuple passed into the variadic version of the template, it stops being able to figure it out. Either the syntax I'm using is wrong, there is a bug in the compiler, or for some reason this extremely specific scenario isn't allowed.

In any case, example code that demonstrates the principle we are trying to achieve as working should be able to call magicObject.printSelf() and show that each of its arbitrary data members can call their own printSelf() methods successfully, as with the http://dpaste.dzfl.pl/6d618af9 example, but with an arbitrary list of instantiated templates, instead of just the one.

Brain buster, this one.
October 16, 2013
I've gotten extremely close. The DPaste link that follows demonstrates three different templates:

The first template is capable of generating the string for and mixing in the definition of a class that has a single arbitrary argument. An object of that class is instantiated, and its printSelf() method is invoked to demonstrate that the arbitrary data member it was generated with is indeed what you would expect it to be. The magic here is fairly plain.

The second template is capable of generating the string for the definition of a class that has some arbitrary number of arbitrary arguments at -compile- time, through the use of variadic template parameters. The issue with this string is that the type at T[n], where T is the variadic template parameter, is mangled at compile-time. The data-member-generating foreach loop shows the three potential ways I attempted to get at the full type information. All three have some problem with it, with typeid giving a fully mangled type, fullyQualifiedName giving a mostly mangled type, and __traits(identifier) giving just whatever the alias was that was passed in. The two other commented-out code sections in this template was an attempt to resolve the type information at the time of mixin, rather than within the string generation function, but this doesn't work.

The third template demonstrates that D actually can resolve the individual types of the variadic template parameter correctly, so long as it's allowed to do this at runtime. The string printed as a result of instantiating this template shows exactly the class definition we want to be able to mix in at compile time, but this type information eludes us at compile time even though it's clearly readily available at runtime.

The code referenced above is here: http://dpaste.dzfl.pl/a6feafc8

I'm not sure why DPaste is failing to compile the code, but I am compiling it with DMD v2.063.2. Also included at the bottom of the DPaste listing is the output I get when running that program, exactly as listed.

With all of that said, there is a fundamental difference between how the first template and the second two templates are written. The first one, which works, resolves the T parameter during the mixin. The second two try to resolve the variadic types during class definition string generation. I am pretty convinced at this point that if this is ever going to work, the variadic template parameter type tuple needs to be resolved during the mixin, like with the first example. The how is the question. Again, I attempted to have the variadic template parameter types deduced during execution of the mixin with the two blocks of commented-out code in the second template, but I had no luck there, as I got the same errors as I did in my previous big post. So.

By the first template, we know that we can generate class definitions with arbitrary data members and mix them in at compile time using aliases for templated, compile-time-mixin-generated classes, but for each new arbitrary type we want the generated class to have, we need to have a distinct template parameter for the type.

By the third template, we know that we should have access to the fully qualified types in the variadic template parameter, but it at least appears to only be fully resolved at runtime (which I feel like is me misunderstanding something, but then that's also the root of our problem).

By the second template, we show that trying to deduce the types within the type tuple (the variadic template parameter) during class definition string generation does not work, which leads us to believe it must be resolved while mixing in the class definition using the templated types, but that also doesn't seem to work (as noted by the failed attempts in the two commented out blocks of the second template).

I feel like we're so very close to the answer, whether it's "Oh, you just have to do this" or "You're crazy, this is impossible."

If only it was possible to summon Andrei. He'd know! Maybe it's some sort of a Bloody Mary thing?

Andrei, Andrei, An-
October 16, 2013
Am 16.10.2013 03:17, schrieb DoctorCaptain:
> I've gotten extremely close. The DPaste link that follows demonstrates
> three different templates:
>
> ...

So is there any reason why you still pass the variadic arguments to the generator function and not do it the way I proposed in my last dpaste snippet? Even if you need the variadic arguments inside the generator for some logic you could still reference them by using the variadic arguments to the actual template.
October 16, 2013
On Wednesday, 16 October 2013 at 06:09:48 UTC, Benjamin Thaut wrote:
> Am 16.10.2013 03:17, schrieb DoctorCaptain:
>> I've gotten extremely close. The DPaste link that follows demonstrates
>> three different templates:
>>
>> ...
>
> So is there any reason why you still pass the variadic arguments to the generator function and not do it the way I proposed in my last dpaste snippet? Even if you need the variadic arguments inside the generator for some logic you could still reference them by using the variadic arguments to the actual template.

I suppose I was trying to give the class individual data members, such that passing a tuple of (WorstChild, MiddleChild, BestChild) would result in a class definition of:

class MagicClass {
    WorstClass t1;
    MiddleClass t2;
    BestClass t3;
}

However, if that is impossible (and frankly it'd be more difficult to work with than your way even if it was achieved), then I'll use your approach (actually, I'm just going to use your approach anyway. It's significantly cleaner than my horrid mess of a goal). That said, what is actually happening in your example?

I reworked it a bit to demonstrate that the class has accessible members within T, that can be instantiated and accessed and whatnot.

http://dpaste.dzfl.pl/07b20d75

Note the use of typeof() to get the type of the elements at each index of members, to generate a type on which a constructor can be called to instantiate the elements at each index of members. Magic.

What is T within the generated class definition? Is this just how tuples work? T is an "array" of three arbitrary pointers, initially null, that can be instantiated with new to create valid pointers to objects of each type at T's indexes? Like, T in the DPaste example is an array of pointers, such that:
[WorstChild*, MiddleChild*, BestChild*]? Is it literally just magic like that?

Actually, let me formally present a couple of ending thoughts/questions:

First, allow me to apologize for trying to force a different, messy horrid mess of a goal on you, when your initial solution was majestic to begin with.

Second, as I was trying to figure out just a moment ago, what -exactly- is T in the generated class definition, and why does it allow me to use it as an arbitrary container for objects of the arbitrary types I want it to contain (Read: why is it able to do exactly what I want it to be able to do? What's going on behind the scenes?)?

Third, given that I am going to go with your solution (it works, it works well, and I can't seem to force my original goal to work, whether that was even a good idea to begin with at all (it wasn't)), can you think of a way to actually produce my original goal? That is, instead of a container T which I can use to access my arbitrary data members once the generated class is instantiated, is it actually even possible to generate individual data members, a la:

class MagicClass {
  T[0] t0;
  T[1] t1;
  // ... etc
} // ?

You've been wildly helpful, and admirably concise. I am -extremely- interested in the answer to the second thought, and while I'm sure the answer is simple, it also seems -too- magic to actually work, and yet it does.

Again, thank you to everyone who responded, and thank you Benjamin for your continued help.
« First   ‹ Prev
1 2