Conversion to template -> linker errors?

Hello! I have written a pretty simple program that takes a vector of class objects and performs a quicksort on them. I had the program working perfect before I tried converting the student class into a template. IThere is a member in the student class that is a pointer that points to an array of test scores and I am hoping to allow the array to have multiple datatypes put in-- ints or doubles
I am getting TONS of errors and I cant figure out why? The only thing I could think of was to add in the <T> into the vector and quicksort/swap/partition functions but that just caused a whole new bunch of errors. Can anyone help? Thanks!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <cstdlib>
#include <iostream>
#include <vector>
#include "Student.h"

using namespace std;
void displayVector(vector<Student>);
void quickSort(vector<Student> &, int, int);
void swap(Student &, Student &);
int partition(vector<Student> &, int, int);

int main(int argc, char *argv[])
{      
    float janeDoeTests[] = { 85, 89.5, 90, 75, 56, 79, 100, 45, 67, 88  };
    float elvisPresleyTests[] = { 50, 34, 23, 26, 46, 56, 67, 89, 90, 22 };
    float mickJaggerTests[] = { 100, 24, 46, 56, 35, 46, 78, 90, 78, 90 };
    float cherTests[] = { 97, 98, 45, 67, 36, 67, 47, 89, 25, 46};

    // code left out for space, similar to above

    
    Student student1(1, "Jane Doe", janeDoeTests);
    Student student2(2, "Elvis Presley", elvisPresleyTests);    
    Student student3(3, "Mick Jagger", mickJaggerTests); 
    Student student4(4, "Cher", cherTests);
    Student student5(5, "Beethoven", beethovenTests);
    Student student6(6, "John Lennon", johnLennonTests);
    Student student7(7, "Roseanne", roseanneTests);
    Student student8(8, "Paris Hilton", parisHiltonTests);    
    Student student9(9, "Sean Connery", seanConneryTests); 
    Student student10(10, "Mozart", mozartTests);
    Student student11(11, "Penny Lane", pennyLaneTests);
    Student student12(12, "Kelly Ripa", kellyRipaTests);
    Student student13(13, "Newton Perry", newtonPerryTests);
    Student student14(14, "Sarah Parker", sarahParkerTests);    
    Student student15(15, "Joan Rivers", joanRiversTests); 
    Student student16(16, "Barry White", barryWhiteTests);
    Student student17(17, "Cary Grant", caryGrantTests);
    Student student18(18, "Star Jenkins", starJenkinsTests);


    const int numStudents = 20;
    vector<Student> studentVector;
    
    studentVector.push_back(student17);
    studentVector.push_back(student18);
    studentVector.push_back(student6);   
    studentVector.push_back(student19);
    studentVector.push_back(student20);    
    studentVector.push_back(student5);
    studentVector.push_back(student1);
    studentVector.push_back(student2);   
    studentVector.push_back(student4);
    studentVector.push_back(student15);   
    studentVector.push_back(student16);
    studentVector.push_back(student3);
    studentVector.push_back(student8);   
    studentVector.push_back(student7);
    studentVector.push_back(student13);   
    studentVector.push_back(student14);
    studentVector.push_back(student9);
    studentVector.push_back(student10);   
    studentVector.push_back(student11);
    studentVector.push_back(student12);   
    
    cout << "Here is your unsorted vector: " << endl;
    cout << "--------------------------------------------------------------------------" << endl;
    cout << endl;
    
    displayVector(studentVector);
    
    quickSort(studentVector, 0, numStudents-1);
    
    cout << "Here is your vector sorted by student IDs: " << endl;
    cout << "--------------------------------------------------------------------------" << endl;
    cout << endl;
    
    displayVector(studentVector);

    
    
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

void displayVector(vector<Student> vect)
{
    for(int count = 0; count < vect.size(); count++)
    {
         cout << "Student ID: " << vect[count].getID() << endl;
         cout << "Student Name: " << vect[count].getName() << endl;
         cout << "Student Average: " << vect[count].getAverage() << endl;
         vect[count].displayTests();        
         cout << endl;
         cout << endl;
    }
}

int partition(vector<Student> & vect, int start, int end)
{
    int pivotValue, pivotIdx, mid;
    
    mid = (start + end)/2;
    swap(vect[start], vect[mid]);
    pivotIdx = start;
    pivotValue = vect[start].getID();
    
    for(int i = start + 1; i <= end; i++)
    {
        if(vect[i].getID() < pivotValue)
        {
            pivotIdx++;
            swap(vect[pivotIdx], vect[i]);
        }
    }
    swap(vect[start], vect[pivotIdx]);
    return pivotIdx;
}

void quickSort(vector<Student> & vect, int start, int end)
{
    int pivotPoint;    
    
    if(start < end)
    {
        pivotPoint = partition(vect, start, end);
        quickSort(vect, start, pivotPoint-1);
        quickSort(vect, pivotPoint + 1, end);
    }
}

void swap(Student &student1, Student &student2)
{
    Student tempStudent = student1;
    student1 = student2;
    student2 = tempStudent;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<cstring>
#include <string>

#ifndef STUDENT
#define STUDENT

using namespace std;

template<typename T>

class Student
{
      private:
             int studentID;
             string studentName;
             float studentAvg;
             T * testScores;
              
      public:
             Student();
             Student(int, string, T *);
             Student(const Student<T> &);
             ~Student();
             int getID(){ return studentID; };
             string getName() { return studentName; };
             void displayTests();  
             float getAverage();        
             float getAverage(T []);   
			 Student<T> & operator=(const Student<T> &);
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "Student.h"
#include <iostream>
#include <string>


using namespace std;


template<typename T>
Student<T>::Student()
{
     studentID = 0;
     studentName = " ";
     studentAvg = 0.0;
     testScores = new T [10];
}

template<typename T>
Student<T>::Student(int id, string name, T * tests)    //student class constructor
{
     studentID = id;
     studentName = name;
     testScores = new T [10];
         
     for(int i = 0; i < 10; i++)
     {
          testScores[i] = tests[i];
     }
     
     studentAvg = getAverage(testScores);
}

template<typename T>
Student<T>& Student<T>::operator=(const Student<T> & thatStudent)
{
	if(this != &thatStudent)
	{
		studentID = thatStudent.studentID;
		studentName = thatStudent.studentName;
		testScores = new T [10];
		for(int i = 0; i < 10; i++)
		{
			testScores[i] = thatStudent.testScores[i];
		}
     
		studentAvg = getAverage(testScores);
	}
	return *this;
}

template<typename T>
Student<T>::~Student()
{
     delete [] testScores;
}

template<typename T>
Student<T>::Student(const Student & student)  
{
     studentID = student.studentID;
     studentName = student.studentName;
     testScores = new T [10];

     for(int i = 0; i < 10; i++)
     {
          testScores[i] = student.testScores[i];
     }
     
     studentAvg = getAverage(testScores);

}

template<typename T>
void Student<T>::displayTests()
{          
     cout << "Test Scores: ";
     
     for (int i = 0; i < 10; i++)
     {
         cout << testScores[i] << " " ;
     }
}

template<typename T>
float Student<T>::getAverage()
{
      float sum = 0.0; 
      float average = 0.0; 
      
      for(int i = 0; i < 10; i++)
      {
           sum += testScores[i];
      }
      
      average = sum/10;
      return average;
}

template<typename T>
float Student<T>::getAverage(T tests[])
{
      float sum = 0.0; 
      float average = 0.0; 
      
      for(int i = 0; i < 10; i++)
      {
           sum += tests[i];
      }
      
      average = sum/10;
      return average;
}
           
Last edited on
closed account (zb0S216C)
All occurrences of Student must be accompanied with <T>, even inside the class. Here are a few examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <typename T>
class Student { /*...*/ };

// Constructor definition:
template <typename T>
Student<T>::Student() { /*...*/ }

// As a parameter:
template <typename T>
void SomeFunction(const Student<T> &Inst)
{ /*...*/ }

// Instantiation:
Student<int> NewStudent;


Wazzak
Last edited on
Thanks for the quick reply..I have tried that..still got errors...I then included it in my function prototypes and definitions that are in the main program (for vector and quicksort) and it still won't compile...here are the errors..

thanks again for any help!


1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(117): error C2955: 'Student' : use of class template requires template argument list
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(124): error C2228: left of '.getID' must have class/struct/union
1> type is 'int'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(128): error C2228: left of '.getID' must have class/struct/union
1> type is 'int'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(138): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(138): error C3203: 'Student' : unspecialized class template can't be used as a template argument for template parameter '_Ty', expected a real type
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(138): error C2955: 'Student' : use of class template requires template argument list
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(150): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(150): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(152): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(153): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'Student' (or there is no acceptable conversion)
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(29): could be 'Student<T> &Student<T>::operator =(const Student<T> &)'
1> while trying to match the argument list '(Student, Student)'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(153): error C2582: 'operator =' function is unavailable in 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(154): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'Student' (or there is no acceptable conversion)
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(29): could be 'Student<T> &Student<T>::operator =(const Student<T> &)'
1> while trying to match the argument list '(Student, Student)'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(154): error C2582: 'operator =' function is unavailable in 'Student'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
closed account (zb0S216C)
It's not a good idea to define template classes/functions inside a separate file. It's best to place the corresponding definitions inside the same file. That way, the linker can find the definition. However, there's a workaround. It's restrictive, but it works. The solution is called Explicit Template Instantiation. This tells the compiler to instantiate Student with T as a specific type. For instance:

Header:
1
2
3
4
5
template <typename T>
class Student
{
    public: Student();
};

Source:
1
2
3
4
5
6
7
#include "Student.h"

template class Student<int>; // Explicit Template Instantiation

template<>
Student<int>::Student()
{ /*...*/ }

Wazzak
Last edited on
Your error is saying you need to do this...
Student<float [10]> student1(1, "Jane Doe", janeDoeTests);

It's going to be harry handling member functions that return objects of type T in this case <float [10]>, I think what you really want is to use <float>. (This is taken straight from your implementation that is)
Hey guys! So I have attempted all of the above fixes and I am still getting errors. I get an error everytime that I try to push onto the vector and I don't understand why??

here are the errors..they just continue repeated on different lines....

1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(50): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(51): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(51): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(52): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(52): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(53): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(53): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(54): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(54): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(55): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(55): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(56): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(56): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(57): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(57): error C2514: 'Student' : class has no constructors
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(60): error C2065: 'T' : undeclared identifier
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(60): error C3203: 'Student' : unspecialized class template can't be used as a template argument for template parameter '_Ty', expected a real type
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(60): error C2955: 'Student' : use of class template requires template argument list
1> c:\claudia\datastructuresii\alvarado_lab8\student.h(12) : see declaration of 'Student'
1>c:\claudia\datastructuresii\alvarado_lab8\main.cpp(62): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'Student' to 'int &&'
1> with
1> [
1> _Ty=int
1> ]
1> Reason: cannot convert from 'Student' to 'int'
Topic archived. No new replies allowed.