By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,631 Members | 1,144 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,631 IT Pros & Developers. It's quick & easy.

Use of class factory in a recursive container

P: n/a
Hi,

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() {} // (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<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!

/ Johan
Jul 22 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Hi,

I made a few typos in my first post so here it all comes again (corrected).

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!

/ Johan
Jul 22 '05 #2

P: n/a
"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. 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 nugde so to speak. Perhaps you can
dig something useful from it...

Victor
Jul 22 '05 #3

P: n/a
"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->instantiate(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
Jul 22 '05 #4

P: n/a
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
Jul 22 '05 #5

P: n/a
"Johan Bergman" <us**@inter.net> wrote...
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?)
I recommend both "Modern C++ Design" by Alexandrescu and "C++ Templates"
by Vandevoorde and Josuttis. Very good books. Try the reverse order,
though. MC++D can be a bit too much.

Also, see Boost library for tons of template tricks. And monitor this
newsgroup. I've seen many interesting posts on templates.
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?


I don't know. My ability to write template code is still far from
advanced. I would probably try to specialise the 'create' function
based on 'T', which suggest that it should be a member template...

Victor
Jul 22 '05 #6

P: n/a
Thanks, your answers helped me a lot!

BR,
Johan

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:3PFNb.77410$na.42900@attbi_s04...
"Johan Bergman" <us**@inter.net> wrote...
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?)


I recommend both "Modern C++ Design" by Alexandrescu and "C++ Templates"
by Vandevoorde and Josuttis. Very good books. Try the reverse order,
though. MC++D can be a bit too much.

Also, see Boost library for tons of template tricks. And monitor this
newsgroup. I've seen many interesting posts on templates.
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?


I don't know. My ability to write template code is still far from
advanced. I would probably try to specialise the 'create' function
based on 'T', which suggest that it should be a member template...

Victor

Jul 22 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.