I made a typo again. In the post I just made I wrote create() in one place
an instantiate() in another place, but I meant the same function. Below you
will find a corrected version of the post.
/ Johan
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:ywhNb.66727$xy6.124703@attbi_s02...
"Johan Bergman" <us**@inter.net> wrote... Maybe someone can help me with this one. The following describes a
somewhat simplified version of my problem, but I think it will be
sufficient.
I want to use class factories (virtual constructors) which have this
base class:
template<class T>
class Factory_Base {
public:
virtual ~Factory_Base() {} // (could be pure virtual)
virtual T* create(int n) {return new T[n];} // (could be pure
virtual) };
I also have a container class, Array<T>, which has a constructor that
takes a factory as a parameter:
template<class T>
Array<T>::Array(Factory_Base<T> &f)
{
factory = &f; // Array<T> has a member Factory_Base<T> *factory
}
This works fine as long as I only want to do this:
My_Factory my_factory; // My_Factory creates My_T instances
Array<My_T> my_variable(my_factory);
However, sometimes I want to write like this:
My_Factory my_factory; // My_Factory still creates My_T instances
Array<Array<My_T> > my_variable(my_factory);
The most straightforward solution would be to create a factory that can
create Array<My_T>, but I don't want to do that.
Please tell me that there is another way!
You haven't shown how 'Array<>' uses the factory.
Oops, you're right! My intention was to let Array<> call factory->create()
whenever it is supposed to create new (non-container) elements, i.e. when
the Array<> is initialized or resized.
For all we know,
the way it uses it should allow for "de-Array-fication". You could
write some kind of recursive template to "de-Array-fy" the template
argument until it reaches non-Array-derived type.
template<class T> class Array;
template<class T> class NonArray {
typedef T original;
};
// specialisation for 'Array<T>'
template<class T> class NonArray<Array<T> > {
typedef NonArray<T>::original original; // recursive
};
template<class T> class Array {
typedef Factory_Base< NonArray<T>::original > Real_Factory;
// use Real_Factory somehow
};
This is just a quick sketch, a nudge so to speak. Perhaps you can
dig something useful from it...
Yes, I think this helps a lot, thanks! (Perhaps you can recommend some good
books where I can learn more about this kind of C++ idioms?)
But now I have another problem. The Array<T> method that creates new
(container or non-container) elements should look something like this:
if (factory == 0)
// No factory was specified by the user
data = new T[n]; // line 3
else if (typeid(T) == typeid(Original))
// Time to use Real_Factory
data = factory->create(n);
else
// T must be an Array of something
data = new T[n](*factory); // line 9
The library I am working on contains some Array<T> instantiations for types
T that don't have constructors that take a factory as a parameter. This
means that the compiler won't accept line 9 (although this line will never
be executed for such types because they will in practice be taken care of by
line 3). Is there any legal way to do this?
/ Johan