This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have this class in my .hpp file
template<class T = int>
class Matrix
{
public:
Matrix();
}
and I have this Matrix.cpp file
#include "Matrix.hpp"
template<class T>
Matrix<T>::Matrix()
{
vector<T> vecN(1, 0);
_matrix.resize(1, vecN);
_rows = 1;
_cols = 1;
}
but it won't work, when adding a main
#include "Matrix.hpp"
int main(int argc, char** argv)
{
Matrix<int> test();
return 0;
}
i get a very weird error saying
main.cpp:19: undefined reference to Matrix<int>::Matrix(unsigned int, unsigned int)'
main.cpp:19:(.text+0x2d): relocation truncated to fit: R_X86_64_PC32 against undefined symbol Matrix<int>::Matrix(unsigned int, unsigned int)
Template code must be in the header, unless it is for specialisations.
This is because the template is used to generate the actual class when you use it.
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 3 years ago.
I tried to make an Array template class but when I try to build the compiler fails to link the constructor and the method and I get :
undefined reference to `Array::Array()
undefined reference to `Array::getSize()
Here is the header file:
#pragma once
template<typename type, int length>
struct Array{
public:
Array();
int getSize();
private:
type data[length];
int m_length;
};
The Array.cpp file:
#include "Array.h"
template<typename t, int l>
Array<t, l>::Array()
{
m_length = l;
}
template<typename type, int length>
Array<type, length>::getSize()
{
return m_length;
}
And the main function:
#define LOG(x) cout<<x<<endl
int main()
{
Array<int, 10> array;
LOG(array.getSize());
}
If someone has any idea about why I am getting this, I would really appreciate.
You need to either put your implementation into the header files, or define the usage (instantiation of the template arguments) in the source file
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I'm trying to make a simple bounds checked array in C++. I have declared a class in a header file, and defined the class in a separate source file. The compile step runs fine, but when I try to link the objects, I get the following error:
$ g++.exe -o a.exe src\main.o src\array.o
src\main.o: In function `main':
../src/main.cpp:7: undefined reference to `Array<int>::Array(int)'
../src/main.cpp:9: undefined reference to `Array<int>::operator[](int)'
../src/main.cpp:10: undefined reference t o `Array<int>::operator[](int)'
../src/main.cpp:11: undefined reference t o `Array<int>::operator[](int)'
../src/main.cpp:13: undefined reference t o `Array<int>::operator[](int)'
../src/main.cpp:7: undefined reference to `Array<int>::~Array()'
../src/main.cpp:7: undefined reference to `Array<int>::~Array()'
collect2.exe: error: ld returned 1 exit status
main.cpp
#include <iostream>
#include "array.hpp"
using namespace std;
int main() {
Array<int> x(10); // compiler error
x[0] = 1; // compiler error
x[1] = 2; // compiler error
x[2] = 3; // compiler error
cout << x[1] << endl; // compiler error
return 0;
}
array.hpp
#ifndef ARRAY_HPP_
#define ARRAY_HPP_
template <class T>
class Array{
private:
T* array;
int length_;
public:
Array(int);
~Array();
int Length();
int& operator[](int);
};
#endif /* ARRAY_HPP_ */
array.cpp
#include "array.hpp"
template <class T>
Array<T>::Array(int size) {
length_ = size;
array = new T[size];
}
template <class T>
Array<T>::~Array() {
delete[] array;
}
template <class T>
int Array<T>::Length() {
return length_;
}
template <class T>
int& Array<T>::operator[](const int index) {
if (index < 0 || index >= length_) {
throw 100;
}
return array[index];
}
Definitions of members of a template class shall be in the same header where the template class is defined itself.
Template classes must have all their code in the header file or they can only be used for types you explicitly instantiated in the cpp file.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
I am having trouble compiling a function that returns a vector of template type. The code compiles if I remove the template and replace with double. Also, this problem only occurs if the function definition and prototype are not in the same file. I compile using:
g++ func.cpp main.cpp
main.cpp:
#include <vector>
#include "func.h"
int main(int argc, char** argv)
{
double x_min = 0.0;
double x_max = 1.0;
int N = 20;
std::vector<double> x = linspace(x_min,x_max,N);
return 0;
}
func.cpp:
#include "func.h"
template <class T>
std::vector<T> linspace(T x1, T x2, int N)
{
std::vector<T> x(N);
if(N == 1)
{
x[0] = x2;
return x;
}
T delta_x = (x2-x1)/(N-1);
for(int ii = 0; ii < N; ii++)
{
x[ii] = x1 + ii*delta_x;
}
x[N-1] = x2;
return x;
}
func.h:
#include <vector>
template <class T>
std::vector<T> linspace(T x1, T x2, int N);
The compiler produces the following output:
/tmp/cclptwq7.o: In function `main':
main.cpp:(.text+0x45): undefined reference to `std::vector<double, std::allocator<double> > linspace<double>(double, double, int)'
collect2: ld returned 1 exit status
Template classes should not be split up into .hpp and .cpp files.
The member function implementations must be also be included in a compilation unit (for example, your main.cpp), otherwise the compiler has no way of knowing how to build the template class with the types you provide as template arguments. You could also #include "func.cpp" in main.cpp, but that would be ugly.
As David suggested, https://stackoverflow.com/a/3040706/713961 gives you more information if you're curious.
Templates must be defined in the same file or else you get a linker error. See this answer for more info.
This question already has answers here:
"Undefined reference to" template class constructor [duplicate]
(3 answers)
Closed 6 years ago.
I have three files . The contents of main.cpp are
#include<iostream>
#include<QString>
#include "util.h"
int main()
{
using Util::convert2QString;
using namespace std;
int n =22;
QString tmp = convert2QString<int>(n);
return 0;
}
util.h
namespace Util
{
template<class T>
QString convert2QString(T type , int digits=0);
}
util.cpp
namespace Util
{
template<class T>
QString convert2QString(T type, int digits=0)
{
using std::string;
string temp = (boost::format("%1%") % type).str();
return QString::fromStdString(temp);
}
}
When I try to compile these files with following command I get undefined reference error
vickey#tb:~/work/trash/template$ g++ main.cpp util.cpp -lQtGui -lQtCore -I. -I/usr/local/Trolltech/Qt-4.8.0/include/QtCore -I/usr/local/Trolltech/Qt-4.8.0/include/QtGui -I/usr/local/Trolltech/Qt-4.8.0/include
/tmp/cca9oU6Q.o: In function `main':
main.cpp:(.text+0x22): undefined reference to `QString Util::convert2QString<int>(int, int)'
collect2: ld returned 1 exit status
Is there something wrong with the template declaration or implementation ? why M I getting these linking errors :?
The implementation of a non-specialized template must be visible to a translation unit that uses it.
The compiler must be able to see the implementation in order to generate code for all specializations in your code.
This can be achieved in two ways:
1) Move the implementation inside the header.
2) If you want to keep it separate, move it into a different header which you include in your original header:
util.h
namespace Util
{
template<class T>
QString convert2QString(T type , int digits=0);
}
#include "util_impl.h"
util_impl.h
namespace Util
{
template<class T>
QString convert2QString(T type, int digits=0)
{
using std::string;
string temp = (boost::format("%1") % type).str();
return QString::fromStdString(temp);
}
}
You have 2 ways:
Implement convert2QString in util.h.
Manually instantiate convert2QString with int in util.cpp and define this specialization as extern function in util.h
util.h
namespace Util
{
template<class T>
QString convert2QString(T type , int digits=0);
extern template <> QString convert2QString<int>(int type , int digits);
}
util.cpp
namespace Util {
template<class T>
QString convert2QString(T type, int digits)
{
using std::string;
string temp = (boost::format("%1") % type).str();
return QString::fromStdString(temp);
}
template <> QString convert2QString<int>(int type , int digits);
}
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 6 years ago.
This seems so simple, but I cannot figure out what's wrong. I'm implementing the C++ vector class (only for int, not a template), and functions with iterator templates or typedefs are giving me these errors on compile:
Undefined symbols:
"void vectorInt::assign<int>(int, int)", referenced from:
_main in ccNVdR23.o
"void vectorInt::assign<int*>(int*, int*)", referenced from:
_main in ccNVdR23.o
_main in ccNVdR23.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Important parts for the source files are:
vectorInt.h
#include <cstdlib>
#include <stdexcept>
typedef unsigned int size_type;
class vectorInt {
private:
int* array;
size_type current_size;
size_type current_capacity;
public:
.
.
.
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
void assign(size_type n, const int u);
};
#endif // VECTORINT_H
vectorInt.cpp
#include vectorInt.h
.
.
.
template <class InputIterator>
void vectorInt::assign(InputIterator first, InputIterator last) {
clear();
InputIterator it = first;
int count = 0;
while(it++ != last) {
count++;
}
reserve(count);
while(first != last) {
this->push_back(*first++);
}
}
void vectorInt::assign(size_type n, const int u) {
clear();
reserve(n);
for(int i=0; i<(int)n; i++)
push_back(u);
}
main.cpp
#include <cstdlib>
#include <stdexcept>
#include <iostream>
#include "vectorInt.h"
using namespace std;
int main(int argc, char** argv) {
vectorInt first;
vectorInt second;
vectorInt third;
first.assign(7, 100);
vectorInt::iterator it;
it = first.begin()+1;
second.assign(it, first.end()-1); // the 5 central values of first
int myints[] = {1776,7,4};
third.assign(myints, myints+3); // assigning from array.
return 0;
}
FYI: I know the main method uses the vectorInt::iterator, but that is not the problem and hence I didn't include it in the source code.
Template code gets two phase compilation. Phase one includes only basic syntax check. The second phase, which is dependent on type T, gets full compilation from the compiler. The class/function will get instantiated based on type T, and the second phase compilation will run against that type.
Since your code (implementation) is in .cpp file, it would get only first phase compilation, and thus it will not be included in the translation unit - No object file would be generated.
For templates, you must allow the compiler to compile the entire code. And for the same you need to put entire implementation in header file only. You may also #include respective .cpp file just after the class declaration.
Place the code for the assign functions in the header file (vectorint.h) and you should be fine. Code for templates needs to be visible when they are instanciated, in you case where you call the assign function.