Here is my Matrix.cpp file. (there's a separate Matrix.h file)
#include <iostream>
#include <stdexcept>
#include "Matrix.h"
using namespace std;
Matrix::Matrix<T>(int r, int c, T fill = 1)
{
if (r > maxLength || c > maxLength) {
cerr << "Number of rows and columns should not exceed " << maxLen << endl;
throw 1;
}
if (r < 0 || c < 0) {
cerr << "The values for the number of rows and columns should be positive" << endl;
throw 2;
}
rows = r;
cols = c;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = fill;
}
This gives the following
error: invalid use of template-name ‘Matrix’ without an argument list
What's the problem in my code?
EDIT: The class Matrix is defined with a template<class T>
EDIT:
Here's my Matrix.h file:
#include <iostream>
#include <math.h>
#define maxLength 10;
using namespace std;
template <class T>
class Matrix
{
public:
Matrix(int r, int c, T fill = 1);
private:
int rows, cols;
T mat[10][10];
};
And here's the Matrix.cpp file:
#include <iostream>
#include <stdexcept>
#include "Matrix.h"
using namespace std;
template<class T>
Matrix<T>::Matrix(int r, int c, T fill = 1)
{
}
This gives the following error:
Matrix.cpp:12:43: error: default argument given for parameter 3 of
‘Matrix::Matrix(int, int, T)’ Matrix.h:16:3: error: after previous
specification in ‘Matrix::Matrix(int, int, T)’
What is wrong in my code?
If your class is template then correct definition should be,
template<class T>
Matrix<T>::Matrix(int r, int c, T fill) // don't give default argument
...
Also, don't forget to include this Cpp file where you use this class. Because in the case of templates, full body should be visible to all translation units.
Edit: After your edited question, I noticed that the error says it all.
You are not suppose to give the default argument inside the definition of the method. It's adequate to give in the declaration(which you already gave). Make your template definition as shown above and the error shall disappear.
You should write as:
template<class T>
Matrix<T>::Matrix(int r, int c, T fill = 1)
{
..
}
Yes, it's tedious. And it might not be a good idea to put
the template definitions in the source file, refer to
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
So the easiest way is to put the definitions of the template members
inside the class template definition in header file.
Related
I am working on my own library and I want to create function max(). I know that function like this exists in C++ and it isn't in namespace std, so erasing using namespace std; won't help. I am creating this function in my namespace like this:
namespace ml
{
template<typename T>T max(T cntr, int size)//I'm getting errors here
{
sort(cntr,0,size-1);//my function which just sorts elements, it's working fine
return cntr[size-1];
}
}
Here is my main function:
#include <iostream>
#include <ctime>
#include "mylib.hpp"
int main()
{
srand(time(NULL));
int* arr, n;
std::cin>>n;
arr = new int [n];
for(int i = 0; i < n; i++)
{
arr[i] = rand()%100;
}
int maximum = ml::max(arr,n);//I'm getting errors here
std::cout<<maximum<<'\n';
return 0;
}
Sorry for grammatical mistakes if i've done so.
If the purpose of the function is to search a C-style array, the signature should be template <typename T> T max(T* cntr, int size). (note the T* as the type of cntr) That way, when it's called with an int*, T is deduced as int, and that's the correct return type.
I keep getting 3 errors. They're all related to the way I'm aggregating templates I'm assuming but i can't find anything to help me figure this out. My teacher wasn't super clear on how we're supposed to get the output he wants us to get.
In file included from main.cpp:10:
./Table.h:15:9: error: use of class template 'RowAray' requires template arguments
Here is what i wrote
RowAray.cpp
#ifndef ROWARAY_H // if constant ROWARAY_H not defined do not execute
#define ROWARAY_H // defines constant ROWARAY_H
#include <iostream>
#include <new> // Needed for bad_alloc exception
#include <cstdlib> // Needed for the exit function
template <class T>
class RowAray{
private:
int size;
T *rowData;
void memError(); // Handles memory allocation errors
void subError(); // Handles subscripts out of range
public:
RowAray(T); //used to construct row Array object
~RowAray(){delete [] rowData;} //used to deallocate dynamically allocated memory from Row array
int getSize(){return size;} //inline accessor member function used to return length of Row array
T getData(int i){return (( i >=0&& i < size)?rowData[i]:0);} //
T &operator[](const int &);
};
template <class T>
RowAray<T>::RowAray(T colSize){
size =colSize>1?colSize:1;
// Allocate memory for the array.
try
{
rowData = new T [size];
}
catch (bad_alloc)
{
memError();
}
// Initialize the array.
for (int count = 0; count < size; count++)
*(rowData + count) = rand()%90+10;
}
template <class T>
void RowAray<T>::memError()
{
cout << "ERROR:Cannot allocate memory.\n";
exit(EXIT_FAILURE);
}
template <class T>
void RowAray<T>::subError()
{
cout << "ERROR: Subscript out of range.\n";
exit(EXIT_FAILURE);
}
template <class T>
T &RowAray<T>::operator[](const int &sub)
{
if (sub < 0 || sub >= size)
subError();
else
return rowData[sub];
}
#endif /* ROWARAY_H */
Table.cpp
#ifndef TABLE_H
#define TABLE_H
#include "RowAray.h"
template <class T>
class Table{
private:
int szRow;
RowAray **records;
public:
Table(int,int); //used to construct Table object
~Table(); //used to deallocate dynamically allocated memory from Table object
int getSzRow(){return szRow;} //used to return row size
int getSize(int row){return records[row>=0?row:0]->getSize();} //used to return column size
T getRec(int, int); //used to return inserted random numbers of 2d arrays
};
template <class T>
Table<T>::Table(int r, int c ){
//Set the row size
this->szRow = r;
//Declare the record array
records = new RowAray*[this->szRow];
//Size each row
int allCol = c;
//Create the record arrays
for(int i=0;i<this->szRow;i++){
records[i]=new RowAray(allCol);
}
}
template <class T>
T Table<T>::getRec(int row, int col){
//if else statement used to return randomly generated numbers of array
if(row >= 0 && row < this->szRow && col >= 0 && col < records[row]->getSize()){
return records[row]->getData(col);
}else{
return 0;
}
}
template <class T>
Table<T>::~Table(){
//Delete each record
for(int i=0;i<this->szRow;i++){
delete records[i];
}
delete []records;
}
#endif /* TABLE_H */
main.cpp
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;
//User Libraries
#include "RowAray.h"
#include "Table.h"
//Global Constants
//Function Prototype
template<class T>
void prntRow(T *,int);
template<class T>
void prntTab(const Table<T> &);
//Execution Begins Here!
int main(int argc, char** argv) {
//Initialize the random seed
srand(static_cast<unsigned int>(time(0)));
//Declare Variables
int rows=3,cols=4;
//Test out the Row with integers and floats
RowAray<int> a(3);
RowAray<float> b(4);
cout<<"Test the Integer Row "<<endl;
prntRow(&a,3);
cout<<"Test the Float Row "<<endl;
prntRow(&b,4);
//Test out the Table with a float
Table<float> tab1(rows,cols);
Table<float> tab2(tab1);
//Table<float> tab3=tab1+tab2;
cout<<"Float Table 3 size is [row,col] = Table 1 + Table 2 ["
<<rows<<","<<cols<<"]";
//prntTab(tab3);
//Exit Stage Right
return 0;
}
template<class T>
void prntRow(T *a,int perLine){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int i=0;i<a->getSize();i++){
cout<<a->getData(i)<<" ";
if(i%perLine==(perLine-1))cout<<endl;
}
cout<<endl;
}
template<class T>
void prntTab(const Table<T> &a){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int row=0;row<a.getSzRow();row++){
for(int col=0;col<a.getSize();col++){
cout<<setw(8)<<a.getRec(row,col);
}
cout<<endl;
}
cout<<endl;
}
"RowAray" is a template, with one template parameter:
template <class T>
class RowAray
See there? It's a template, one template parameter.
Now, over here:
template <class T>
class Table{
private:
int szRow;
RowAray **records;
See there? No template parameter when referring to the RowAray template, here. When using a template, its parameters must also be specified (unless they have a default, which is irrelevant here).
The fact that, here, you are defining a new template, Table, with one template parameter -- that's irrelevant.
You probably intended to use
RowAray<T> **records;
here; but that's just based on a cursory look at this pile of code so don't automatically take my word for it. You need to figure out what you intended to do here, and specify the correct template parameter.
This is not the only parameter-less reference in the shown code. You need to find, and fix all of them.
Furthermore, you also dumped:
using namespace std;
before proceeding and #includeing a bunch of header files, including standard library header files. This is a bad programming practice, and often creates subtle, and difficult to figure out compilation errors, if not outright wrong code. You must get rid of using namespace std; as well, especially when a bunch of #includes are involved.
I've got header file with template class:
#ifndef BUBBLE_H
#define BUBBLE_H
#include "algorithm.h"
template <typename T>
class Bubble : public Algorithm <T> {
public:
Bubble(T* in, int inSize) : Algorithm<T>(in, inSize){}
void compute();
};
#endif // BUBBLE_H
if I put whole body of compute() class here everything works fine. But I would like to have it in cpp file. I wrote:
#include "bubbleSort.h" using namespace std;
template <typename T>
void BubbleSort<T>::compute(){ //(*)
for (int i = 1; i<this->dataSize; i++){
for (int j = this->dataSize-1; j>=i; j--){
if(this->data[j] < this->data[j-1]) swap(this->data[j-1], this->data[j]);
}
} }
But I received error in line (*):
error: expected initializer before '<' token void
BubbleSort::compute(){
^
How I should fix it?
It's because you're mixing up Bubble and BubbleSort, probably also the headers bubble.h and bubbleSort.h.
in an attempt to understand templates better (and thus be able to read basic documentation on c++), I am trying to perform basic operations on arrays as templates. Below is code that defines a function template for averaging an array:
#include <iostream>
#include <array>
using namespace std;
template<class T>
double GetAverage(T tArray[])
{
T tSum = T(); // tSum = 0
int n=tArray.size();
for (int nIndex = 0; nIndex < n; ++nIndex)
{
tSum += tArray[nIndex];
}
// Whatever type of T is, convert to double
return double(tSum) / n;
}
int main ()
{
array<int,5> data={0,1,2,3,4};
cout << GetAverage(data);
cin.get();
return 0;
}
For some reason, as you will see, the compiler runs into issues when dealing with properties of the array, such as array.size(), all within the defining code of a function. I get the following error:
error: no matching function for call to 'GetAverage'
cout << GetAverage(data);
^~~~~~~~~~
note: candidate template ignored: could not match 'T *' against 'array<int, 5>'
double GetAverage(T tArray[])
^
How can I refer to the properties of an object when defining a function which takes in said object as input (all the while using the language of templates)?
C++11 array is a STL container, not a C array thus the following is incorrect:
T tArray[]
A correct version of the above could be
#include <iostream>
#include <array>
#include <numeric>
using namespace std;
template<class T>
double GetAverage(T tArray)
{
// More compact version as suggested by juanchopanza
auto avg = std::accumulate(begin(tArray), end(tArray), 0.0)/tArray.size();
return avg;
}
int main ()
{
array<int,5> data={0,1,2,3,4};
cout << GetAverage(data);
cin.get();
return 0;
}
http://ideone.com/RyPqOr
if you intend to use something more sophisticated you might have to use a struct or a class since functions don't have partial specialization.
I have searched and searched for a solution to my problem but I cannot seem to find one. I am using Code::Blocks and I am getting a redefinition error of a template class.
Here is my "vectorAux.h" file:
#ifndef vectoraux_h
#define vectoraux_h
#include <vector>
#include <algorithm>
#include <iostream>
template <typename T>
void removeDup(std::vector<T> & v);
template <typename T>
unsigned seqVectSearch(const std::vector<T> & v, unsigned first,
unsigned last, const T& target);
template <typename T>
void writeVector(const std::vector<T> & v);
#include "vectorAux.cpp"
#endif
and here is my "vectorAux.cpp" file:
#include "vectorAux.h"
#include <vector>
#include <algorithm>
#include <iostream>
template <typename T>
void removeDup(std::vector<T> & v)
{
std::vector<int> vector1;
unsigned i, last = v.size();
for(int j = 0; j <= v.size(); j++)
{
std::cout << seqVectSearch(v, j, last, j);
if(seqVectSearch(v, j, last, j) != v[i])
vector1.push_back(seqVectSearch(v, j, last, j));
}
}
template <typename T>
unsigned seqVectSearch(const std::vector<T> & v, unsigned first,
unsigned last, const T& target)
{
unsigned i = first;
while((v[i] != target) && (v[i] <= last))
{
if(v[i] == target)
return i;
i++;
}
return last;
}
template <typename T>
void writeVector(const std::vector<T> & v)
{
unsigned i;
unsigned n = v.size();
for (i = 0; i < n; i++)
std::cout << v[i] << ' ';
std::cout << std::endl;
}
the final file for this program is "vectorDriver.cpp" but this one has no errors. This one just runs the program by calling the functions:
#include "vectorAux.h"
#include <vector>
#include <iostream>
void fillVector(std::vector<int> & vect);
int main()
{
using namespace std;
vector<int> vect;
fillVector(vect);
cout << "Testing removeDup" << endl;
cout << "Original vector is ";
writeVector(vect);
removeDup(vect);
cout << "Vector with duplicates removed is ";
writeVector(vect);
cout << endl;
writeVector(vect);
return 0;
}
void fillVector(std::vector<int> & vect)
{
int arr[] = {1,7,2,7,9,1,2,8,9};
unsigned arrsize = sizeof(arr)/sizeof(int);
vect = std::vector<int>(arr, arr+arrsize);
}
I would really appreciate any and all help/advice that is given! I have looked around for a while and each source that I have found has said to guard the header file, but I have already done that and my problem still ensues.
You include vectorAux.cpp in vectorAux.h. I would guess that you are also compiling vectorAux.cpp separately. So you end up compiling the code in vectorAux.cpp twice.
Answer is simple, move the code from vectorAux.cpp to vectorAux.h, delete vectorAux.cpp, you don't need it.
Template code almost always goes in header files.
The contents of your "VectorAux.cpp" should be inside the "VectorAux.h" because you define a template class.
The simple answer is: Templates should not be split into source and header files. Keep it all in the header file when using templates.
Remove your .cpp of your templated class from your project source files. You are currently compiling the .cpp file twice; once because it is in your project and secondly because your .h is including it. Also, remove the .h inclusion from your .cpp, you don't need it since the header is including the .cpp at the bottom. This is one of the unfortunate problems of separating out templated classes.
The error happens during the compilation of the vectorAux.cpp file, because you are including the header file, which in turn includes the implementation file. This way, you end up with the content of the cpp file being duplicated.
If you really do want to split the implementation and declaration of the template functions into two separate files, there are two things you should do:
Don't include the headerfile in the implementation file.
Don't add the cpp file to the files being translated by the compiler.
Any one of those two options will get rid of your compiler error, but you really should do both.