I dont know what im doing wrong this is my first time seperating .cpp files and using templates and vectors. I keep getting these two errors: error C2143: syntax error : missing ',' before '<' and error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
main.cpp
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
void write_vector(const vector<T>& V);
int main()
{
int n;
int value;
vector<int> V;
cout << "Enter n: ";
cin >> n;
cout << "Enter " << n << " integer values: ";
while(V.size() < n && cin >> value){
V.push_back(value);
}
write_vector(V);
return 0;
}
writeVector.cpp
template <typename T>
void write_vector(const vector<T> &V)
{
for(int i=0; i < V.size(); i++)
cout << V[i] << " ";
}
You need explicit instantiation to do this because the compiler doesn't know what types the template needs to be compiled for when compiling the .cpp. See Explicit instantiation - when is it used?.
Your template function must be defined in advance so that the compiler can use it. Either define it before main() in the single file or #include it in a header file.
In summary, template functions should be defined in header files. See the answer to Why can templates only be implemented in the header file?
As far as I remember you cannot separate the declaration and implementation of a template.
You need the includes and using in both files. At that point, you might need the explicit instantiation mentioned in other answers, but those will show up as linker issues.
write_vector needs to be in a header file (writeVector.h) rather than a .cpp file if you want to share it between different modules. For more information about why you need to do this see the C++ FAQ.
I presume that your syntax error is because you have a missing using namespace std; in writeVector.cpp? When you move it to a header file you should not put this using directive there because that will needlessly pollute the global namespace whenever this file is included. Instead you should explicitly qualify all references to vector as std::vector.
On the top of you main.cpp add :
#include "Vector.cpp" // since you are learning, this is really strange and should be avoided, but for your example we leave it as is.
In your Vector.cpp
#include <vector>
#include <iostream>
template<class T>
void write_vector(const std::vector<T>& V)
{
for(int i=0; i < V.size(); i++)
std::cout << V[i] << " ";
}
Do not use using statements. Bad habit. You don't need explicit instantiation or other stuff. Your compiler can deduct the correct template.
Altough this works, it's bad code. When using template always write everything in the .h file. So change your Vector.cpp to Vector.h. Remove the forward declaration from your main.cpp and #include "Vector.cpp"
Your code will work fine without any other changes.
Finally the C++ way of doing things would be e.g. :
#include <vector>
#include <iostream>
#include <algorithm>
template<class T>
void write_vector(const std::vector<T>& V)
{
std::copy(V.begin(), V.end(), std::ostream_iterator<T>(std::cout, " ")); // you don't even need this function right?
//for(int i=0; i < V.size(); i++)
// std::cout << V[i] << " ";
}
You can do similar things for the cin.
Related
#include <iostream>
#include <array>
using namespace std;
template <size_t s>
void print_elements(const array<int, s> &a)
{
for (size_t i = 0; i < s; i++)
cout << i << ": " << a[i] << '\n';
cout << '\n';
}
int main()
{
print_elements<3>({0,5,2});
print_elements(std::array{0,5,2});
// print_elements({0,5,2}); - does not work
}
I am currently working with code like this. I have to call print_elements very often, and all the std::array make my code hard to read by now. I was wondering if there is some syntax that would allow me to use just print_elements({0,5,2}), and still deduce the number 3 correctly in the template.
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.
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.
Here is the header for a class I started:
#ifndef CANVAS_
#define CANVAS_
#include <iostream>
#include <iomanip>
#include <string>
#include <stack>
class Canvas
{
public:
Canvas();
void Paint(int R, int C, char Color);
const int Nrow;
const int Ncol;
string Title;
int image[][100];
stack<int> path;
struct PixelCoordinates
{
unsigned int r;
unsigned int c;
} position;
Canvas operator<< (const Canvas& One );
Canvas operator>>( Canvas& One );
};
/*-----------------------------------------------------------------------------
Name: operator<<
Purpose: Put a Canvas into an output stream
-----------------------------------------------------------------------------*/
ostream& operator<<( ostream& Out, const Canvas& One )
{
Out << One.Title << endl;
Out << "Rows: " << One.Nrow << " Columns: " << One.Ncol << endl;
int i,j;
for( i=0; i<One.Nrow; i++)
{
cout<<"\n\n\n";
cout<< " COLUMN\n";
cout<< " 1 2 3";
for(i=0;i<One.Nrow;i++)
{
cout<<"\nROW "<<i+1;
for(j=0;j<One.Ncol;j++) cout<< One.image[i][j];
}
}
return Out;
}
/*-----------------------------------------------------------------------------
Name: operator>>
Purpose: Get a Canvas from an input stream
-----------------------------------------------------------------------------*/
istream& operator>>( istream& In, Canvas& One )
{
// string Line;
// int Place = 0;
// {
// In >> Line;
// if (In.good())
// {
// One.image[Place][0] = Line;
// Place++;
// }
// return In;
#endif
Here is my implementation file for class Canvas:
using namespace std;
#include <iostream>
#include <iomanip>
#include <string>
#include <stack>
#include "proj05.canvas.h"
//----------------Constructor----------------//
Canvas::Canvas()
{
Title = "";
Nrow = 0;
Ncol = 0;
image[][100] = {};
position.r = 0;
position.c = 0;
}
//-------------------Paint------------------//
void Canvas::Paint(int R, int C, char Color)
{
cout << "Paint to be implemented" << endl;
}
And the errors I'm getting are these:
proj05.canvas.cpp: In function 'std::istream& operator>>(std::istream&, Canvas&)':
proj05.canvas.cpp:11: error: expected `;' before '{' token
proj05.canvas.cpp:24: error: expected `}' at end of input
From my limited experience, they look like simple syntax errors but for the life of me, I cannot see what I am missing. I know putting a ; at the end of Canvas::Canvas() is wrong but that seems to be what it expects. Could someone please clarify for me?
(Also, I know much of the code for the << and >> operator definitions look terrible, but unless that is the specific reason for the error please do not address it. This is a draft :) )
You're missing a } for istream& operator>>( istream& In, Canvas& One ) in the header.
The data member int image[][100]; is also invalid, as is image[][100] = {}; in the ctor.
Your implementation (.cpp) files should #include their corresponding header first. This is a simple way to ensure the header is self-contained. In this case, it would lead to syntax errors in standard library headers, which quickly points out to you the problem is in the header (since that is what will be before the stdlib #includes).
You are missing a closing } for your operator>> body. Also, this is not correct:
using namespace std;
#include <iostream>
The order has to be the other way around. GCC's behavior isn't conforming: std must not be visible if no standard header is included yet. So on the next more conformant compiler, it may fail hard.
Also, in the header you should write std::istream instead of just istream (same for ostream, etc). In your current code, your header relies on its users to have typen using namespace std; before including it, which is pretty ugly from a design point of view, since it makes the headers dependent on its users in a non-obvious way (normally, it should be the other way around).
You do not have a closing } at the end of operator >>
Others have answered your question, but here are a couple of extra points:
If your definitions of the insertion and extraction operators aren't templated then you should move them to your implementation file and merely declare them in the header file. This will allow you to replace the line
#include <iostream>
with the line
#include <iosfwd>
The latter will only include declarations of the IO streams, not the entire definitions. This in turn will translate to a faster compilation time of every compilation unit that includes that header.
On the other hand, you could as well choose to leave those functions in the header file but template them.
template <typename Ch,typename Tr>
std::basic_istream<Ch,Tr>& std::operator>>(std::basic_istream<Ch,Tr>& in,
Canvas& o)
{
// ...
}
This will give you the extra flexibility of supporting any stream at the cost of the same increased compilation time you have now.
There is also an error in the way You initialize constant members of Your class.
You have to use an initialization list
Canvas::Canvas()
: Nrow(0), Ncol(0)
{
Title = "";
//Nrow = 0; - this is an attempt to change the value of a const, which was already constructed.
//Ncol = 0; - same as above
//image[][100] = {};
position.r = 0;
position.c = 0;
}