Extending a class template

M

Michal Nazarewicz

Let say I have a class template Pair representing an ordered pair, ie:

#v+
template<class T1, class T2>
class Pair {
T1 a;
T2 b;
public:
Pair() : a(), b() { }
Pair(const Pair<T1, T2> &p) : a(p.a), b(p.b) { }
Pair(const T1 &A, const T2 &B) : a(A), b(B) { }

const T1 &left () { return a; }
const T2 &right() { return b; }
};
#v-

Now, if both types are the same I'd like to "add" another method (say)
areEqual() which compares both members (a and b). I could make a
specialization but it would require repeating all common members, ie:

#v+
template<class T>
class Pair<T, T> {
T a, b;
public:
Pair() : a(), b() { }
Pair(const Pair<T> &p) : a(p.a), b(p.b) { }
Pair(const T &A, const T &B) : a(A), b(B) { }

const T &left () { return a; }
const T &right() { return b; }
bool areEqual() { return a == b; }
};
#v-

Is it possible to some how "extend" a class template with new members
if some condition on template parameters is met?
 
P

Pete Becker

Michal said:
Is it possible to some how "extend" a class template with new members
if some condition on template parameters is met?

The simplest way to add that areEqual function is to make it a free
function:

template <class Ty>
bool areEqual(const Pair<Ty, Ty>&p)
{
return p.left() == p.right();
}

Of course, that approach might not work for other function. In general,
when you need two classes or templates to share capabilities, you
refactor the design: split the original one into two pieces, one derived
from the other, and reuse the base for your new one. For example:

template <class T1, class T2>
class Pair_base
{
private:
T1 a;
T2 b;
public:
Pair_base() : a(), b() {}
Pair_base(const Pair_base& other) : a(other.a), b(other.b) {}
Pair_base(const T1& a0, const T2& b0) : a(a0, b(b0) {}
const T1& left() const { return a; }
const T1& right() const { return b; }
};

template <class T1, class T2>
class Pair : public Pair_base<T1, T2>
{
typedef Pair_base<T1, T2> MyBase;
public:
Pair() : MyBase() {}
Pair(const Pair& other) : MyBase(other) {}
Pair_base(const T1& a0, const T2& b0) : MyBase(a0, b0) {}
};

template <class Ty>
class Pair : public Pair_base<Ty, Ty>
{
typedef Pair_base<Ty, Ty> MyBase;
public:
Pair() : MyBase() {}
Pair(const Pair& other) : MyBase(other) {}
Pair_base(const T1& a0, const T2& b0) : MyBase(a0, b0) {}
bool areEqual() const { return left() == right(); }
};

--

-- 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.
 
N

Nindi73

Michal said:
Let say I have a class template Pair representing an ordered pair, ie:

#v+
template<class T1, class T2>
class Pair {
T1 a;
T2 b;
public:
Pair() : a(), b() { }
Pair(const Pair<T1, T2> &p) : a(p.a), b(p.b) { }
Pair(const T1 &A, const T2 &B) : a(A), b(B) { }

const T1 &left () { return a; }
const T2 &right() { return b; }
};
#v-

Now, if both types are the same I'd like to "add" another method (say)
areEqual() which compares both members (a and b). I could make a
specialization but it would require repeating all common members, ie:

#v+
template<class T>
class Pair<T, T> {
T a, b;
public:
Pair() : a(), b() { }
Pair(const Pair<T> &p) : a(p.a), b(p.b) { }
Pair(const T &A, const T &B) : a(A), b(B) { }

const T &left () { return a; }
const T &right() { return b; }
bool areEqual() { return a == b; }
};
#v-

Is it possible to some how "extend" a class template with new members
if some condition on template parameters is met?

Have u seen the Boost MPL library, in particular the template 'is_same'
I think something like this could work

enable_if_c<is_same<T1,T2>,bool>::type areEqual() { return a == b; }

so that this function only comes into play if T1 and T2 are the same,
even if the line I have written above is incorrect I am sure it is very
close what will work.


Boost has some funcky stuff like that, for example is_base is another
very useful one.
 
D

dasjotre

this is one way:

template<class T, bool b>
struct pair_bs {};

template<class T>
struct pair_bs<T, true>
{
bool areEqual()
{
T * pT = static_cast<T*>(this);
return pT->left() == pT->right();
}
};

use type trait (boost for example)

template<class T1, class T2>
 

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

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top