Templating a typedef or aliasing a template

M

Michal Nazarewicz

Let say I have a class template Set which represent set of objects of
given type, and a struct template Pair representing an ordered pair,
ie:

#v+
template<class T>
class Set {
/* ... whatever ... */
public:
bool exists(const T &element) { /* ... */ }
Set<T> &add (const T &element) { /* ... */ return *this; }
Set<T> &remove(const T &element) { /* ... */ return *this; }
void union (const Set<T> &set) { /* ... */ }
};

template<class T>
struct Pair {
T left, right;
};
#v-

Now, I want to create an "alias template" Relation<T> (representing a
binary relation) to mean Set< Pair<T> >. Unfortunately,
`template<class T> typedef Set< Pair<T> > Relation<T>;' won't work, so
I had to define something like:

#v+
template<class T> class Relation : public Set< Pair<T> > { };
#v-

but then add() and remove() methods would return reference to
Set<Pair<T> > which is not the same type as Relation<T> so I'd have to
create class template like:

#v+
template<class T>
class Relation {
Set< Pair<T> > set;
public:
bool exists(const Pair<T> &pair) {
return set.exists(pair);
}
Relation<T> &add (const Pair<T> &pair) {
set.add(pair); return *this;
}
Relation<T> &remove(const Pair<T> &pair) {
set.remove(pair); return *this;
}
void union (const Relation<T> &rel) {
set.union(rel.set);
}
};
#v-

ie. for each method from Set class I'd have to create method in
Relation class. It seems to me like a lot of useless code plus still
Relation<T> and Set< Pair<T> > are two different types so I wouldn't
be able to do:

#v+
Set< Pair<T> > set;
Relation<T> rel;
set.union(rel);
#v-

unless I define an operator const Set< Pair<T> >() and that's just
another piece of useless code.

Is then any nice and easy way to create a nice alias so user wouldn't
have to type Set< Pair<T> > but rather Relation<T>?
 
N

Nindi73

Michal said:
Let say I have a class template Set which represent set of objects of
given type, and a struct template Pair representing an ordered pair,
ie:

#v+
template<class T>
class Set {
/* ... whatever ... */
public:
bool exists(const T &element) { /* ... */ }
Set<T> &add (const T &element) { /* ... */ return *this; }
Set<T> &remove(const T &element) { /* ... */ return *this; }
void union (const Set<T> &set) { /* ... */ }
};

template<class T>
struct Pair {
T left, right;
};
#v-

Now, I want to create an "alias template" Relation<T> (representing a
binary relation) to mean Set< Pair<T> >. Unfortunately,
`template<class T> typedef Set< Pair<T> > Relation<T>;' won't work, so
I had to define something like:

#v+
template<class T> class Relation : public Set< Pair<T> > { };
#v-

but then add() and remove() methods would return reference to
Set<Pair<T> > which is not the same type as Relation<T> so I'd have to
create class template like:

#v+
template<class T>
class Relation {
Set< Pair<T> > set;
public:
bool exists(const Pair<T> &pair) {
return set.exists(pair);
}
Relation<T> &add (const Pair<T> &pair) {
set.add(pair); return *this;
}
Relation<T> &remove(const Pair<T> &pair) {
set.remove(pair); return *this;
}
void union (const Relation<T> &rel) {
set.union(rel.set);
}
};
#v-

ie. for each method from Set class I'd have to create method in
Relation class. It seems to me like a lot of useless code plus still
Relation<T> and Set< Pair<T> > are two different types so I wouldn't
be able to do:

#v+
Set< Pair<T> > set;
Relation<T> rel;
set.union(rel);
#v-

unless I define an operator const Set< Pair<T> >() and that's just
another piece of useless code.

Is then any nice and easy way to create a nice alias so user wouldn't
have to type Set< Pair<T> > but rather Relation<T>?



Hi,
Maybe I am missing something, but I don't see anythin wrong woth your
first proposed method.

template<class T> class Relation : public Set< Pair<T> > { };

For all intent an purposes this derived class will act exactly like its
Base, theres no difference, well almost. The only time I think you will
have an issue is any function that takes by value or retuns by value
Set<Pair<T> >. I use this method for typedefing templates and never had
a problem with it. When referring by pointer or reference there is no
difference, well none that I can see.

N
 
N

Nindi73

Hi,
Maybe I am missing something, but I don't see anythin wrong woth your
first proposed method.

template<class T> class Relation : public Set< Pair<T> > { };

For all intent an purposes this derived class will act exactly like its
Base, theres no difference, well almost. The only time I think you will
have an issue is any function that takes by value or retuns by value
Set<Pair<T> >. I use this method for typedefing templates and never had
a problem with it. When referring by pointer or reference there is no
difference, well none that I can see.

PS ... what I will add, you didn't have anything but the compiler
provided default and copy constructors and the compiler provided
assignement operator in you Set class. If this was not the case you
would have to provide your derived class with the neccessary
constructors and the assignment operator is not inheritable.
 
D

dasjotre

Michal said:
Let say I have a class template Set which represent set of objects of
given type, and a struct template Pair representing an ordered pair,
ie:
you basically want a template typedef?

if so:

template<class T>
struct Relation_typedef
{
typedef Set< Pair<T> > Relation;
};

and use it as Relation_typedef<real type>::Relation
instead of Set<Pair<real type> >
 
M

Michal Nazarewicz

[...]

Maybe I am missing something, but I don't see anythin wrong woth your
first proposed method.

template<class T> class Relation : public Set< Pair<T> > { };

For all intent an purposes this derived class will act exactly like its
Base, theres no difference, well almost. The only time I think you will
have an issue is any function that takes by value or retuns by value
Set<Pair<T> >.

Ah, and that's my concern. For instance, operator+() returns
Set<Pair<T> > by value and I think that it could matter sometimes. Or
am I wrong and worry too much?
 
M

Michal Nazarewicz

dasjotre said:
you basically want a template typedef?

if so:

template<class T>
struct Relation_typedef
{
typedef Set< Pair<T> > Relation;
};

and use it as Relation_typedef<real type>::Relation
instead of Set<Pair<real type> >

The way I see it, idea of aliases is to make names shorter and easier
to read. ;)
 
P

Pete Becker

Michal said:
The way I see it, idea of aliases is to make names shorter and easier
to read. ;)

Well, sure. But not necessarily at this level of infrastructure. Once
you have a name for type you're dealing with you write a typedef:

typedef Relation_typedef<foo>::Relation foo_rel;

--

-- Pete
Roundhouse Consulting, Ltd. -- www.versatilecoding.com
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
D

dasjotre

Michal said:
The way I see it, idea of aliases is to make names shorter and easier
to read. ;)

If you like to know why, go to comp.std.c++ and search
for 'template typedefs'
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top