Making a Class Generic
Here’s one way to attack incrementally turning a class into a generic, template version:
class PiecewiseSBasis {
public:
PiecewiseSBasis() {}
PiecewiseSBasis(SBasis const &sb) { /* ... */ }
PiecewiseSBasis &operator=(PiecewiseSBasis const &other) {
/* ... */
}
// ...
};
PiecewiseSBasis operator+(PiecewiseSBasis const &a,
PiecewiseSBasis const &b);
First, convert the class into a specialized template:
template <typename F> class Piecewise;
template <>
class Piecewise<SBasis> {
public:
Piecewise() {}
Piecewise(SBasis const &sb) { /* ... */ }
Piecewise &operator=(Piecewise const &other) {
/* ... */
}
// ...
};
typedef Piecewise<SBasis> PiecewiseSBasis;
PiecewiseSBasis operator+(PiecewiseSBasis const &a,
PiecewiseSBasis const &b);
Note how the class name inside the template has become Piecewise, the name
of the class template. Next, we move all the members into the main template
and discard the specialization:
template <typename F>
class Piecewise {
Piecewise() {}
Piecewise(F const &f) { /* ... */ }
Piecewise &operator=(Piecewise const &other) {
/* ... */
}
// ...
};
typedef Piecewise<SBasis> PiecewiseSBasis;
PiecewiseSBasis operator+(PiecewiseSBasis const &a,
PiecewiseSBasis const &b);
At this point we can begin incrementally replacing PiecewiseSBasis with
Piecewise<SBasis> in the remainder of the code, until we no longer
need the typedef. Finally, you can inline functions as needed:
inline Piecewise<SBasis>
operator+(Piecewise<SBasis> const &a,
Piecewise<SBasis> const &b)
{
// ...
}
...and then incrementally make them generic, too:
template <typename F>
inline Piecewise<F>
operator+(Piecewise<F> const &a, Piecewise<F> const &b)
{
// ...
}
This trick isn’t appropriate for every situation, but when it works it can get you over that initial refactoring hump real nicely.