tags:

views:

394

answers:

10

right now i am learning C++, and now I know the basic concept of template, which act just like a generic type, and i found almost every c++ program used template, So i really want to know when are we supposed to use template ? Can someone conclude your experience for me about c++ template ? When will you consider to use template ?

Supplement: if we defined such function

template <class myType>
myType GetMax (myType a, myType b) {
 return (a>b?a:b);
}

but we want to pass a object(self-defined class) for comparison, how can we implement ?

Supplement2: in the answer below, someone have wrote this sample code

template <class myType>
const myType& GetMax (const myType& a, const myType& b) {
    return (a<b?b:a);
}

template <class myType, class Compare>
const myType& GetMax (const myType& a, const myType& b, Compare compare) {
    return (compare(a,b)?b:a);
}

is this correct ? can we just pass a function name as a parameter of class myType ?

A: 

if you dont know the type of your variable or you want to do same thing for many types of variables, you can use template...

if you want to add 2 int, you want to get an int for return if you want to add 2 double, you want to get an double for return

so you use template for this..

ufukgun
+3  A: 

Basically when you want to create a generic class that can handle the solution for multiple types of classes, without having to have a parent-class for all the classes you want to support.

You can just give the class along with which you want to work with (best example would be a container, which can store any type that you pass along with the creation)

//----- the container
template <class T>
class Stack
{
public:
    T* stackPtr;
}

//----- example
void main()
{
    typedef Stack<float> FloatStack;
    typedef Stack<int> IntStack;
}

Now you can store floats and ints with the same class without having to write a specific class for each type.

Evil Activity
Templates also tend to be a lot more type-safe than class hierarchies. In the given example, a FloatStack deals with floats only, and you can't use it to subvert the type system. A comparable implementation with a base class of Stack and subclasses of FloatStack and IntStack would be much harder to make type-safe, particularly if the base class had implementation details so they didn't have to be repeated in each subclass.
David Thornley
+2  A: 

Short answer: if there is no use for it: don't. If it seems to solve a problem (code reuse on different types,...), first implement and debug without templates and then add template parameters.

Before STL/boost, they were nice to make containers.

stefaanv
Before STL/boost, they were nice to make containers.what's this ?
MemoryLeak
Now there are already containers made, of course. And it's better to instantiate a well-debugged template than write your own.
MSalters
I think this is good advice for a beginner, although a more experienced C++ developer might well go for the templates immediately.
David Thornley
The question is: when is it better to use templates. My answer is not, unless it solves a problem for you. Traits can be a good solution, so use them with templates, not just because you can.
stefaanv
+1  A: 

When you need to parameterize concept represented by a class.

For example, if you have a class that represent a way to manage a type of object

class MyThingManager
{
  void add( MyThing& mything ); 
  //...
};

...maybe you need later to use exactly the same behaviour in a new type but managing a different type. Then you have the choice to use copy/paste/replace --that would lead hell opening under your feet immediately-- or make your class have a type to manage as parametter :

template< class ThingType >
 class ThingManager
    {
      void add( ThingType& thing ); 
      //...
    };

That way you don't duplicate code.

Another concern is when you want some function call to be compatible with any parameter that have the required semantic :

template< class MyType >
void addPi( MyType& value )
{
    value += PI;
}

That way you (again) don't have to duplicate code for each types possible in parametters.

It's not called "generic programming" for nothing.

Those are simple cases, but more complex cases exists, when you want to do some meta-programming. If you want to go there, please read at least one book before writing hell code. I recommand "C++ Template Meta-Programming" for that and the excellent "Modern C++ Design" book for more advanced template usage like Policy pattern ans other well known.

Klaim
+8  A: 

G'day,

Simple answer is when you want the behaviour to remain the same independent of the type being used to instantiate the class.

So a stack of ints will behave in the same way as a stack of floats will behave as a stack of MyClass objects.

Inheritance and base classes are used when you want to allow specialisation of the behaviour.

So say you have a base class called Animal and it has a member function called makeSound(). You have no idea which sound every animal will make so you make the makeSound member function a virtual function. In fact, because there is no default sound for all animals you have no idea what to have as default behaviour so you would declare this member function as a pure virtual function.

This then tells anyone making an instance of a derived class, for example a Lion class, that they must provide an implementation the makeSound member function which will provide a roar in some way.

Edit: I forgot to add that this is one of the articles in Scott Meyers's excellent book "Effective C++" (sanitised Amazon link) which I highly recommend.

HTH

cheers,

Rob Wells
+1  A: 

Answering the second question( but we want to pass a object(self-defined class) for comparison, how can we implement?)

If you want to use your own class in a template function using the operator >. Your class need only to define this operator or function.

The important part is that your class need to define the same the operator or function the template uses.

/Tobias

Tobias
A: 

Template provide the way to parametrize on KNOWN AT COMPILE TIME quantities. Note that it can be a type (std::vector will contain only integers) but they can also be values:

template <int N, typename T > class MyType

is templatized both on an integer and a type, and MyType<2, int> will be a different type from MyType<3, int>.

Furthermore, templates allow for Template Metaprogramming: that is the compiler executes a program at compile time. There is a fascinating example by Erwin Unruh for computing primes at compile time.

Look at http://ubiety.uwaterloo.ca/~tveldhui/papers/priority.html for a small bit of history.

Francesco
+1  A: 

Re: supplement. If you want to pass a comparison function, you could provide another overload:

template <class myType>
const myType& GetMax (const myType& a, const myType& b) {
    return (a<b?b:a);
}

template <class myType, class Compare>
const myType& GetMax (const myType& a, const myType& b, Compare compare) {
    return (compare(a,b)?b:a);
}

Samle usage: to compare C-style strings:

bool c_strings_less(const char* a, const char* b)
{
    return std::strcmp(a, b) < 0; //is a less than b
}

const char* greater = GetMax("hello", "world", c_strings_less);

This is how the std::max algorithm works. (I also made a few modifications, e.g it is customary in C++ that predicates define "less-than" comparison.)

Or if you asked, how GetMax would work for arbitrary user-defined types, then those must overload operator> or your function would result in a compile error.

UncleBens
compare(a,b)?b:ais this right ?can here just pass a function as a parameter ?
MemoryLeak
Edited to provide usage sample.
UncleBens
+2  A: 

In the example you provided, everything is OK as long as operator > is defined for the data type whose instances you're comparing.

For example, if you define the following class:

class fraction
{
private:
    int _num, _den;

public:
    fraction(int num, int den)
    {
        if (den >= 0)
        {
            _num = num;
            _den = den;
        }
        else
        {
            _num = -num;
            _den = -den;
        }
    }

    fraction(const fraction &f)
    {
        _num = f._num;
        _den = f._den;
    }

    bool operator > (const fraction &f) const
    {
        return (_num * f._den) > (f._num * _den);
    }

    bool operator == (const fraction &f) const
    {
        return (_num * f._den) == (f._num * _den);
    }
};

Then you can use your template function with instances of this class.

int main(int argc, char* argv[])
{
    fraction a(1,2); // 0.5
    fraction b(3,4); // 0.75
    assert(GetMax/*<fraction>*/(a,b) == a);
    return 0;
}
Eduardo León
A: 

It's important to note that it's perfectly alright to not write your own templates. If you're not sure why you might need them, then you probably don't need them. Templates are a very powerful tool, but they are not always the best solution.

On any common development platform, the standard library provides a high-quality implementation of many of the old-school, traditional uses of templates. Using the standard library classes and functions doesn't require writing new templates. For instance, it provides std::max(), which is the same as your example.

Alan