Is there a way to use Object.factory with templated classes? Or some way to construct templated classes given RTTI of an instance?

Chad Joan chadjoan at gmail.com
Thu Sep 27 05:04:09 UTC 2018


On Wednesday, 26 September 2018 at 21:24:07 UTC, Adam D. Ruppe 
wrote:
> On Wednesday, 26 September 2018 at 20:41:38 UTC, Chad Joan 
> wrote:
>> I'm implementing a deep-copy method for a tree of templated 
>> class instances.  As part of this, I need some way to copy 
>> each node.
>> [...]
>> that isn't already handled by their deepCopy method.
>
> I would strongly suggest just using that virtual method and 
> having the child classes override it, then you call it from any 
> of them and get the right result.
>

The tree nodes are potentially very diverse, but the tree 
structure itself will be very homogeneous.  I'm writing a parser 
generator backend and the tree is expressions of various 
operators (Sequence, OrderedChoice, UnorderedChoice, Repetition, 
etc).  I'm trying to keep it simple: everything is an expression, 
and expressions can contain other expressions (though some are 
always leaves in the tree).  At some level, if I let things 
implement their own deepCopy, then it means there are potentially 
other classes and state out there to iterate that the rest of the 
code doesn't know about.  That could be bad, and expressions 
shouldn't contain anything besides expressions!

This probably contrasts a lot with other use-cases, like 
serialization.  And I wouldn't be surprised if things change 
later on and I end up with some kind of auxiliary virtual copy 
function that does what you suggest, but is specifically for 
handling special out-of-band mutable reference data that the 
expressions might need to carry someday.

I suppose I've never considered just how hard/impossible it is to 
have a generic way to copy things.  Well, maybe a little bit at 
various points, but not this bad ;)  There are so many dimensions 
to the problem and it seems like the context and requirements 
will always be really important.  So it can be made simple under 
the right constraints (ex: everything is immutable!), but the 
constraints are always different depending on the requirements 
(ex: ... but in this hypothetical, we need mutability, so then 
it's gotta happen a different way).

> Object.factory kinda sux and I'd actually like to remove it 
> (among other people). There's no plan to actually do that, but 
> still, just on principle I want to turn people away.
>
> But even as you can see, the implementation is lacking and it 
> isn't great design anyway - the interface with virtual methods 
> does better work. It also wouldn't work in ctfe anyway, 
> object.factory relies on runtime stuff.
>

Good to know!

I don't think I've even used it much, if at all.  I suppose I 
won't miss it if it goes ;)

>> If Object.factory is incapable of this, is there some other 
>> CTFE-friendly way to copy templated class instances?
>
> I think you can copy typeinfo().init and then call 
> typeinfo().defaultConstructor - this is iirc what 
> Object.factory does, but once you already have the typeinfo you 
> can use it directly and bypass the string lookup.
>

I'm having trouble looking this up.  Could you link me to the 
docs for this?

> But you'd really be better off with a virtual copy method. I 
> say those string factory things should only be used if you are 
> starting with a string, like deserialization.
>
>
> interface Copyable {
>    Copyable copy();
> }
>
> class Whatever(T) : Copyable {
>    Whatever!T copy() {
>        auto c = new Whatever!T();
>        c.tupleof = this.tupleof;
>        return c;
>    }
> }
>
>
> that kind of method. the template implements the interface so 
> little boilerplate and it works and can be customized etc and 
> fits in well. If you call it from the interface, you get an 
> instance of the interface (tho note since it is virtual, the 
> underlying type is still what you need). If you call from the 
> child static type, you get it right back. Yay, fits liskov and 
> works!
>

As above, I think this might be a very clean and effective 
solution for a different class of use-cases :)  I'll keep it in 
mind though.

>> If I have to, I can probably make these things register 
>> themselves in some list of delegates that can be used to 
>> instantiate the correct class.  Or something like that.  But I 
>> am hoping that there is a better way that involves less 
>> boilerplate.
>
> that's not a terrible idea if you need delegates keyed to 
> strings...

Right.  At some level I just need a function that I can call like 
this:

auto newThing = makeAnother(originalThing);

and perhaps makeAnother(...) can just lookup originalThing's 
classname in an associative array of delegates.  Or maybe I can 
just hash some part of originalThing's type information.  I can 
put all of the ugly registration boilerplate into a mixin 
template and somehow force that to always be mixed-into any 
descendant classes.  OK, it's probably getting too far into the 
weeds now, but it seems doable and I'll reach for that if I need 
to.

...

Things at least seem much more clear already.  Thanks a bunch!


More information about the Digitalmars-d-learn mailing list