I have written this code using templates which works very perfectly well. I am a beginner in using templates, so I really want someone to check if its written in a correct format. Because when I am deleting template<elemType> from the beginning of each function and main, the code is still working perfectly. So is it fine or is there something wrong? Please let me know since I have an exam related to it on Saturday.
Many Thanks

#include<iostream>
#include<string>
#include<conio.h>

using namespace std;

template<class elemType>
class revElement
{
public:
	void reverseInt();
	void reverseString();
};

template<class elemType>
void revElement::reverseInt()
{
	vector<int>intList;
	vector<int>::iterator i;

	intList.push_back(1);
	intList.push_back(2);
	intList.push_back(3);
	intList.push_back(4);
	intList.push_back(5);

	reverse(intList.begin(),intList.end());

	cout<<"The reversed integers are: "<<endl;

	for(i=intList.begin();i!=intList.end();++i)
	{
		cout<<" "<<*i;
	}
}

template<class elemType>
void revElement::reverseString()
{
	vector<string>stringList;
	vector<string>::iterator s;

	stringList.push_back("This");
	stringList.push_back("is");
	stringList.push_back("my");
	stringList.push_back("C++");
	stringList.push_back("Lab");

	reverse(stringList.begin(),stringList.end());

	cout<<"The reversed strings are: "<<endl;

	for(s=stringList.begin();s!=stringList.end();++s)
	{
		cout<<" "<<*s;
	}
}

template<class elemType>
int main()
{
	revElement r;
	r.reverseInt();
	cout<<endl;
	cout<<endl;
	r.reverseString();
	getch();
	return 0;
}

Recommended Answers

All 16 Replies

well, what you've written is a pure C++ class, without using templates. Unless you use the template type inside declaration/definition of the class it's not a template class.
In your case you're not using the tyep elemType anywhere. So it has no effect.

It's like an idiot wearing the wise-guys' blazer and calling himself wise. ;)

So should it be like this:

temp<class elemType>
void revElement<elemType>::reverseInt()
{
....
}

The point of a template is to remove the need to implement each of the reverseInt and reverseString functions and allow for a single function that operates properly depending on the type of the template.

Try working with the following example which builds a similar class and uses it to work with int values.

template< typename T >
class Reverser {
    std::vector< T > stuff;
public:
    void reverse () {
        std::reverse (stuff.begin (), stuff.end ());
    }
    void display () {
        typename std::vector< T >::iterator it = stuff.begin ();
        for (; it != stuff.end (); ++it)
            std::cout << *it << " ";
        std::cout << std::endl;
    }
    void add (const T& t) { stuff.push_back (t); }
};

You could use a class like that in the following way:

Reverser< int > ri;
ri.add(1); 
// add more things to the container
ri.display ();
ri.reverse ();
ri.display ();

The difference in this example is that you see only a single instance of a reverse function. That function is generated at compile time for as many types of Reverser classes are created.

I couldn't get this thing:

[class Reverser {
std::vector< T > stuff;

Could you please explain it more because I am a beinner in using templates and I sorry but I am not getting your point.

I couldn't get this thing:

Could you please explain it more because I am a beinner in using templates and I sorry but I am not getting your point.

Templates are a code generating facility (an over-simplification, of course - but enough for this exercise) Consider the steps necessary to determine what code must be generated when dealing with a templated class. Lets look at just a couple of parts of the Reverser class I provided:

template< typename T >
Reverser

The typename T is a placeholder for the eventual type you intend to use this class for. So when you say something like Reverser< int > you can think of it as replacing the typename T with what you provide in between the brackets (in this case, int ).

So, every place that uses a T in the class definition has this same property; it will get generated according to the type provided as above. In the Reverser example that means something like

template< typename T >
class Reverser {
   std::vector< T > stuff;

gets generated as

class Reverser {
   std::vector< int > stuff;

if we continue from the discussion above.

So you can see that by using a type such as Reverser< int > you get code generated according to the templated construct you provided. This is true for all parts of the templated class for all types you provide to it. So if, instead of Reverser< int > you used Reverser< std::string > you would get code something like

class Reverser {
   std::vector< std::string > stuff;

Once you understand those concepts you can start to design away redundant pieces of your less general solution. For instance, in your original class you have each of the following:

void reverseInt();
void reverseString();

Each of these presumably does the same thing over different types. If you are performing the same action and the only thing that is changing is the types you are operating over then templates make the implementation much easier.

As I mentioned above, the code is generated for you but there is another benefit. What if, in your example, you want to now support a new type? You would need to create an entirely new function within the class called reverseType and fill that in. You'd need to do that for each new type you want to support. The templated approach allows you to now just create a new Reverser< Type > and have all of that code generated for you for each new type.

It's the definition of a template class:

template <typename T>
class Reverser {
  std::vector<T> stuff;
  //other member declarations & definitions
};

This defines a class, called "Reverser", that contains a vector (called "stuff") whose complete type is template/instance dependent.
For example, a declaration such as Reverser<int> revInt; would cause Reverser::stuff to be a vector<int> and Reverser<double> revDub; would cause Reverser::stuff to be a vector<double>.

That's the idea behind, and the power of, templates. You can write a piece of code one time and have it work for any data type you need it to (when written properly).

Now I understand!! Thanks a ton for that!! I wrote the code and m getting an error which I don't understand: fatal error LNK1120: 1 unresolved externals.

Here's the code:

#include<iostream>
#include<string>
#include<vector>
#include<conio.h>

using namespace std;

template<class elemType>
class revElement
{
	vector<elemType>intList;
public:
	void rev();
	void display();
	void addItems(const elemType&);
};

template<class elemType>
void revElement<elemType>::rev()
{
	reverse(intList.begin(),intList.end());
}

template<class elemType>
void revElement<elemType>::display()
{
	elemType std::vector<elemType>::iterator i = intList.begin();
	for(;i!=i.end();++i)
		cout<<*i<<endl;
	cout<<endl;
}

template<class elemType>
void revElement<elemType>::addItems(const elemType& r)
{
	intList.push_back(r);
}

template<class elemType>
int main()
{
	revElement<int> r;
	r.addItems(4);
	r.addItems(5);
	r.addItems(6);
	r.display();
	r.rev();
	r.display();
	getch();
}

My guess (and this is only a guess) is that #include <conio.h> is introducing a problem.
Note that you do not need the template<class elemType> before main. main is not a generic function.

I am getting tons of error, particularly related to iterator i. I just have no idea what to do

elemType std::vector<elemType>::iterator i = intList.begin();

Remove the leading elemType . Replace it with typename .

I am getting two errors in this line,

template<class elemType>void revElement<elemType>::display(){	elemType std::vector<elemType>::iterator i = intList.begin();	for(;i!=i.end();++i)		cout<<*i<<endl;	cout<<endl;}

end() is not a member of'std::_Vector_iterator<_Ty,_Alloc>

Your code is currently

template<class elemType>void revElement<elemType>::display()
{
	elemType std::vector<elemType>::iterator i = intList.begin();
	for(;i!=i.end();++i)
	cout<<*i<<endl;	cout<<endl;
}

THE variable i, is an iterator of the vector.
therefore your compiler says that i(iterator) doesn't have any member function named end()
therefore the i.end() should be something else.

Oh now I found what was wrong. I was supposed to put intList.end() instead of i and now my program works!!
Thanks a heap for all the help!!!
God bless

elemType std::vector<elemType>::iterator i = intList.begin();	
for(;i!=intList.end();++i)		
cout<<*i<<endl;

I just want to know what is typename used for?

Also note, you might think about using std::stack because of its stack property, when you insert data in it, you will effectively have it in 'reverse'. Example :

#include <iostream>
#include <stack>

template<typename T>
class Reverser{
private:
 typedef std::stack<T> Container;
private:
  Container _cont;
public:
 template<typename Iterator>
 Reverser(Iterator begin, Iterator end){
    while(begin != end){ _cont.push(*begin++); }
 }
 void displayReverse(){
   Container c = _cont;
   while(!c.empty()){ cout << c.top() << " ";  c.pop(); }
 }
};

int main(){
 int A[5] = {1,2,3,4,5};
 Reverser<int> rev(A,A+5);
 rev.displayReverse();
}

its not the proper way of doing a reversal, especially when your only printing them, but its a different way about thinking it. You should examine all ways and pick the best one for your situation.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.