Inheritance & Template parameters

T

Thomas Matthews

Hi,

I would like to apply inheritance to a template parameter, but my design
fails to compile: cannot initialize one template class with child
child parameterized class. I'll explain...

Given:
#include <string>

// Parent class
class Name_Id
{
public:
Name_Id(const string& new_name,
int new_id = 0)
: name(new_name), id(new_id)
{}
virtual size_t max_width(void) const = 0;
// Other methods here...
private:
string name;
int id;
};

// Child classes
class Category
: public Name_Id
{
public:
Category(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 32};
};

class Title
: public Name_Id
{
public:
Title(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 128};
};

template <typename AnyType>
struct Iterator_Functor
{
virtual void operator()(AnyType& a) = 0;
}

I have a Name_Id database table class which
contains Name_Id records. This is a base class
for other tables of this kind.
class Name_Table
{
public:
void for_each(Iterator_Functor<AnyType>& functor);
}
The for_each method applies the functor to each record
in the table.

I have a Category_Table class which represents
a database table containing Category objects:
class Singleton;

class Category_Table
: public Name_Table, public Singleton
{
public:
static Category_Table& ref(); //The singleton method.
};

I want to pass an Iterator_Functor<Category> to the
"for_each" method of the Category_Table:
Iterator_Functor<Category> functor;
Category_Table::ref().for_each(functor);

The compiler is complaining that a
Iterator_Functor<Category>
cannot be substituted for a
Iterator_Functor<Name_Id>
even though Category is-a Name_Id.

I know the compiler is correct, but is there any
work-around for this?




--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
V

Victor Bazarov

Thomas said:
I would like to apply inheritance to a template parameter, but my design
fails to compile: cannot initialize one template class with child
child parameterized class. I'll explain...

Given:
#include <string>

// Parent class
class Name_Id
{
public:
Name_Id(const string& new_name,
int new_id = 0)
: name(new_name), id(new_id)
{}
virtual size_t max_width(void) const = 0;
// Other methods here...
private:
string name;
int id;
};

// Child classes
class Category
: public Name_Id
{
public:
Category(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 32};
};

class Title
: public Name_Id
{
public:
Title(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 128};
};

template <typename AnyType>
struct Iterator_Functor
{
virtual void operator()(AnyType& a) = 0;
}

I have a Name_Id database table class which
contains Name_Id records. This is a base class
for other tables of this kind.
class Name_Table
{
public:
void for_each(Iterator_Functor<AnyType>& functor);

How is this going to compile? 'AnyType' is not defined here. Did
you forget to specify that 'for_each' is a template or that the
whole class (Name_Table) is in fact a template? Or is this the case
of "copy-paste in haste" error, and it has to be

public:
void for_each(Iterator_Functor<Name_Table>&);

???
}
The for_each method applies the functor to each record
in the table.

Uh... Whatever...
I have a Category_Table class which represents
a database table containing Category objects:
class Singleton;

class Category_Table
: public Name_Table, public Singleton

Are you deriving from an incomplete type here?
{
public:
static Category_Table& ref(); //The singleton method.
};

I want to pass an Iterator_Functor<Category> to the
"for_each" method of the Category_Table:
Iterator_Functor<Category> functor;
Category_Table::ref().for_each(functor);

The compiler is complaining that a
Iterator_Functor<Category>
cannot be substituted for a
Iterator_Functor<Name_Id>
even though Category is-a Name_Id.

I know the compiler is correct, but is there any
work-around for this?

Why not declare your Category_Table::functor as

Iterator_Functor<Name_Table> functor;

?? What's so bad if it's a functor of the base class and not
the derived one?

V
 
D

David Hilsee

Thomas Matthews said:
Hi,

I would like to apply inheritance to a template parameter, but my design
fails to compile: cannot initialize one template class with child
child parameterized class. I'll explain...

Given:
#include <string>

// Parent class
class Name_Id
{
public:
Name_Id(const string& new_name,
int new_id = 0)
: name(new_name), id(new_id)
{}
virtual size_t max_width(void) const = 0;
// Other methods here...
private:
string name;
int id;
};

// Child classes
class Category
: public Name_Id
{
public:
Category(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 32};
};

class Title
: public Name_Id
{
public:
Title(const string& new_name)
: Name_Id(new_name)
{ };
size_t max_width(void) const
{ return 128};
};

template <typename AnyType>
struct Iterator_Functor
{
virtual void operator()(AnyType& a) = 0;
}

I have a Name_Id database table class which
contains Name_Id records. This is a base class
for other tables of this kind.
class Name_Table
{
public:
void for_each(Iterator_Functor<AnyType>& functor);
}
The for_each method applies the functor to each record
in the table.

I have a Category_Table class which represents
a database table containing Category objects:
class Singleton;

class Category_Table
: public Name_Table, public Singleton
{
public:
static Category_Table& ref(); //The singleton method.
};

I want to pass an Iterator_Functor<Category> to the
"for_each" method of the Category_Table:
Iterator_Functor<Category> functor;
Category_Table::ref().for_each(functor);

The compiler is complaining that a
Iterator_Functor<Category>
cannot be substituted for a
Iterator_Functor<Name_Id>
even though Category is-a Name_Id.

I know the compiler is correct, but is there any
work-around for this?

There are lots of options.

a) Define a for_each for Category_Table that takes an
Iterator_Functor<Category>.
b) Make for_each a template, so it can be used with many different functors,
not just those that derive from Iterator_Functor<Name_Id> (template <class
Func> void for_each(Func f)). What is the point of Iterator_Functor,
anyway?
c) Remove the inheritance relationship from Category_Table and Name_Table.
Instead, provide a class template for holding objects (template <class T>
Table { /* ... */ }; Table<Category> tab;). The current relationship looks
suspicious, but I'd have to see more of their implementation to know if it's
truly questionable.
 
T

Thomas Matthews

David said:
message

There are lots of options.

a) Define a for_each for Category_Table that takes an
Iterator_Functor<Category>.
b) Make for_each a template, so it can be used with many different functors,
not just those that derive from Iterator_Functor<Name_Id> (template <class
Func> void for_each(Func f)). What is the point of Iterator_Functor,
anyway?
Iterator_Functor is similar to a Visitor pattern. It allows me to pass
a record to a functor derived from Iterator_Functor.
struct Category_Displayer
: Iterator_Functor<Category>
{
void operator()(Category& cat)
{
cout << cat << endl;
}
}

The functor is basically imposing an interface requirement.

c) Remove the inheritance relationship from Category_Table and Name_Table.
Instead, provide a class template for holding objects (template <class T>
Table { /* ... */ }; Table<Category> tab;). The current relationship looks
suspicious, but I'd have to see more of their implementation to know if it's
truly questionable.

I'm working with the Borland Database Engine (BDE) using the Paradox
table format.

Unfortunately, the BDE API does not treat the table as a container, but
as a wrapper around Delphi functionality.

I have many Name-ID tables that vary in the string length and theme.
For example, I have Titles, Authors and Publishers as singleton tables.
Each would be specialization of a Name-ID table.

I would like to hide the inheritance from the user of the table. Thus
the Titles table would be a collection of Title objects, not Name-ID
objects. This would prevent a user from appending Author objects
to a Title table (even though Author and Title are both descendants
of Name-ID).


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,279
Latest member
LaRoseDermaBottle

Latest Threads

Top