Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between choosing a subclass via a template parameter or instantiating a member variable

Tags:

c++

Say I have a class that can use different types of distance functions (Euclidean distance, etc) to do some comparisons. I have implemented these functions as subclasses of a class Distance:

class Distance;
class EuclideanDistance : public Distance;
class OtherDistance : public Distance;

It seems that to choose which type of distance to use, I could do:

template <typename TDistance>
class MyClass;

and instantiate it with:

MyClass<EuclideanDistance> instance;

or accomplish the same thing with:

class MyClass
{
public:
 Distance* myDistanceFunction;
}

and instantiating it with

MyClass instance;
instance.myDistanceFunction = new EuclideanDistance;

are there any advantages of one method over the other?

Thanks,

David

like image 740
David Doria Avatar asked Nov 07 '11 19:11

David Doria


4 Answers

Association (i.e. the solution without templates) is preferable since it offers you more flexibility, allows you to change distance implementation at runtime, generates cleaner error messages and cleaner object files (fewer symbols).

Also, classes generated from the template parametrized with different types (distance implementations) will be considered different types and will not be interchangeable: MyClass<EuclideanDistance> is a different type than MyClass<MinkowskiDistance>. This will force you to make all functions that operate on MyClass templates as well and will ultimately lead to greater complexity with no added benefits.

Templates should be used when you need to relax type-safety of the language, for example when you are writing a class which should operate on a number of unrelated types (not derived from a common base class/interface) which nonetheless behave in a similar manner (e.g. all have a kwak() member function). This is called duck-typing: types are formally unrelated but all exhibit similar properties.

In case you're prevented from ensuring that all distance implementations derive from a common base class/interface, you may need to use templates. Otherwise, prefer simple and flexible association.

like image 118
Adam Zalcman Avatar answered Oct 17 '22 09:10

Adam Zalcman


Well, aside from the compile time vs run time issue, the biggest difference has kind of been disallowed by your pre-existing code. Using a template would have allowed you to use any types that supported a common operation (i.e. getDistance) without them having to be from the same heirarchy. This would have meant that Euclidean distance and your other class could have been completely different, yet still useable in the template as long as they supported the subset of members the template made use of.

like image 36
John Humphreys Avatar answered Oct 17 '22 07:10

John Humphreys


The former fixes the distance metric for the class at compile-time, while the second does it at run-time. The former is likely more efficient because it allows the compiler to optimize parts of it away, while the second can be more flexible.

like image 37
Fred Foo Avatar answered Oct 17 '22 07:10

Fred Foo


Public inheritance means IS-A. Is a EuclideanDisatance interoperable with a "LorentzDistance" or "QuaternionDistance" (or whatever) in any meaningful way? Are they both "distances" in the sense that some code somewhere would be happy to use either one in a non-trivial way (that is, something other than printing the value, etc...)? My guess is no, it's not.

So you want generics, not inheritance. Templates are a simpler promise: two things "look like" each other syntactically.

like image 1
Andy Ross Avatar answered Oct 17 '22 08:10

Andy Ross