transparent factory product solution (static&auto-subscribing) (renamed topic)
EDIT: I renamed topic to better suit the outcome of the thread.
I'm so close to wrapping up a super-neat templated factory instantiatable system and there are a few tails I'm chasing which if I catch up with one it'll all work.
one way would be if I could in some way (with or without RTTI) in a constructor know if it's at the end of the constructor chain or not (if more will come.. heh sounds rather impossible but really hope it's not :U).
also this all happens at static initialisation time. sort of like an "initializer"... static class instances that take care of registration with factory.
the problem lies in that all classes in the inheritence hierarchy inherit from a common template class appart from each class' base class in the main hierarchy.
and it's the constructor of this template class which I'd like to have perform it's main task only if it's of the derived type that's actually being created blatantly speaking.
any ideas?
I can post code but it's all dodgy templatry so the intention is clearer than the code atm..
[Edited by - nimnimnim on January 11, 2008 11:59:27 PM]
There's no way that I know of, and you really shouldn't need to know. I don't quite follow what you're trying to do, but if you need to know if a class is a derived class in the constructor, it sounds like there's something fishy.
#include <iostream>struct A { A(bool terminal = true) { std::cout << "A leaf? " << terminal << "\n"; }};struct B : A { B(bool terminal = true) : A(false) { std::cout << "B leaf? " << terminal << "\n"; }};int main(){ A a; std::cout << "\n"; B b;}
Gives
A leaf? 1A leaf? 0B leaf? 1
Depending on what you're attempting, you may be able to achieve the result with a virtual base class.
Quote:the problem lies in that all classes in the inheritence hierarchy inherit from a common template class appart from each class' base class in the main hierarchy.
and it's the constructor of this template class which I'd like to have perform it's main task only if it's of the derived type that's actually being created blatantly speaking.
Dreaded diamond much?
struct SomeDerived : public base Derived, public virtual FactoryBase
The FactoryBase will get instantiated precisely once, regardless of how many times it's inherited. Its constructor must also be explicitly invoked and completed before any other class is constructed.
and forum is back! :)
(excuse me renaming thread to better reflect what the topic now is really about :))
Thanks for the replies!
Zao: thanks for the idea! I'll keep it as a close to good solution as it still requires the end (factory) object type class to adapt it's constructor to fit this should-be transparent system.
Thanks SiCrane, Antheus: the problem was that the 'FactoryBase' was templated and can't do without a 'typename DerivedType' so I thought it can't be virtual:ed out down the inheritence line since they're all different types (setting virtual inheritence for 'FactoryBase' didn't help)...
But I just tried something for the heck of it now and put virtual before the inheritence of the parent base object class and now it seems it all works!! \:U/
I guess I failed to realise that even though a derived type will have both its own 'FactoryBase' and the one of its base, only one constructor can be used since a class can't use two members of the same name anyway :U\\.
So if I use RTTI now (typeid(DerivedType).name()) I have the last problem solved which was to somehow attach a static ID variable (string or something) to each object type without having all derived types use the same variable...
I'll post the whole thing with a console test app which illustrates its use:
http://nim.pansarvagn.net/pub/code/nim_transparent_factory_solution.zip (updated)
If you have an idea of how to not use typeid().name() for ID it'd be fantastic!
...Or what's your opinion on that? would RTTI be a totally negligable overhead in this case? If I'm using dynamic_cast somewhere else in the game it's already pointless to worry about typeid or not as long as I'm not ready to eliminate RTTI all together?
SomeDerived::ID would be way more neat than the macro ID(SomeDerived) I'm using now though... (tried SomeDerived::get_id() also but only sane place to declare that function is in the 'FactoryBase' class called 'DefaultInstantiative' and in there it'll get ambiguous...)
Still the way things are now the longer the inheritence line of factory product classes I have now the more bloated each further derived class will be right? they'll have as many DefaultInstantiative's as there are base classes in their inheritence line right?
Would be greatful for thoughts on this :) and if you know of a better factory solution of this sort please share! :)
edit: to sum it up so you won't have to figure out from the code:
it's an automated factory product subscription solution that has your object types subscribe themselves at static initialisation time.
* one factory for each base type is automatically created as a static instance.
* the creation of this factory instance and the subscription of every factory product type only happens once for each base class for factory and once for each derived type for subscription. (so at run-time none of this is repeated)
* the only code effort you need to do is to inherit through a macro in your derived type class declaration (in place for the regular statement to inherit from its base) and a one-parameter (the type) macro in the cpp (unavoidable since there are static members involved). so just one extra line of code...
* then you just use the macro CREATE_BY_ID("DeruvedX") or CREATE_BY_TYPE(DerivedX) which does DerivedX::OriginalBaseType::factory()->create(typeid(DerivedX).name()).
downsides seem to be this Instantiative class bloating and that you can't seem to dynamic_cast[fixed] a base pointer refering to a derived to a derived pointer.. works with reinterpret_cast and derived members can be accessed etc but that might be too risky... can dynamic_cast be overloaded? could check with RTTI... thoughts?
so I guess unless I can somehow avoid this Instantiative-inheritence bloating I won't use this for hierarchies like game entities but I'll definately use it for a case where I have a kind of Function object and will have loads of derivatives but only one level of inheritence to this one base class.
edit: but then you can use abstract interfaces and there won't be any instantiative bloating...
would be great if anyone would have thoughts on improvements!
[Edited by - nimnimnim on January 14, 2008 12:55:46 AM]
(excuse me renaming thread to better reflect what the topic now is really about :))
Thanks for the replies!
Zao: thanks for the idea! I'll keep it as a close to good solution as it still requires the end (factory) object type class to adapt it's constructor to fit this should-be transparent system.
Thanks SiCrane, Antheus: the problem was that the 'FactoryBase' was templated and can't do without a 'typename DerivedType' so I thought it can't be virtual:ed out down the inheritence line since they're all different types (setting virtual inheritence for 'FactoryBase' didn't help)...
But I just tried something for the heck of it now and put virtual before the inheritence of the parent base object class and now it seems it all works!! \:U/
I guess I failed to realise that even though a derived type will have both its own 'FactoryBase' and the one of its base, only one constructor can be used since a class can't use two members of the same name anyway :U\\.
So if I use RTTI now (typeid(DerivedType).name()) I have the last problem solved which was to somehow attach a static ID variable (string or something) to each object type without having all derived types use the same variable...
I'll post the whole thing with a console test app which illustrates its use:
http://nim.pansarvagn.net/pub/code/nim_transparent_factory_solution.zip (updated)
If you have an idea of how to not use typeid().name() for ID it'd be fantastic!
...Or what's your opinion on that? would RTTI be a totally negligable overhead in this case? If I'm using dynamic_cast somewhere else in the game it's already pointless to worry about typeid or not as long as I'm not ready to eliminate RTTI all together?
SomeDerived::ID would be way more neat than the macro ID(SomeDerived) I'm using now though... (tried SomeDerived::get_id() also but only sane place to declare that function is in the 'FactoryBase' class called 'DefaultInstantiative' and in there it'll get ambiguous...)
Still the way things are now the longer the inheritence line of factory product classes I have now the more bloated each further derived class will be right? they'll have as many DefaultInstantiative's as there are base classes in their inheritence line right?
Would be greatful for thoughts on this :) and if you know of a better factory solution of this sort please share! :)
edit: to sum it up so you won't have to figure out from the code:
it's an automated factory product subscription solution that has your object types subscribe themselves at static initialisation time.
* one factory for each base type is automatically created as a static instance.
* the creation of this factory instance and the subscription of every factory product type only happens once for each base class for factory and once for each derived type for subscription. (so at run-time none of this is repeated)
* the only code effort you need to do is to inherit through a macro in your derived type class declaration (in place for the regular statement to inherit from its base) and a one-parameter (the type) macro in the cpp (unavoidable since there are static members involved). so just one extra line of code...
* then you just use the macro CREATE_BY_ID("DeruvedX") or CREATE_BY_TYPE(DerivedX) which does DerivedX::OriginalBaseType::factory()->create(typeid(DerivedX).name()).
downsides seem to be this Instantiative class bloating and that you can't seem to dynamic_cast[fixed] a base pointer refering to a derived to a derived pointer.. works with reinterpret_cast and derived members can be accessed etc but that might be too risky... can dynamic_cast be overloaded? could check with RTTI... thoughts?
so I guess unless I can somehow avoid this Instantiative-inheritence bloating I won't use this for hierarchies like game entities but I'll definately use it for a case where I have a kind of Function object and will have loads of derivatives but only one level of inheritence to this one base class.
edit: but then you can use abstract interfaces and there won't be any instantiative bloating...
would be great if anyone would have thoughts on improvements!
[Edited by - nimnimnim on January 14, 2008 12:55:46 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement