Visual Studio error LINK1120 - c++

In VS 2013 , I declared a function in a header file named "util_serial.h" and defined it in the cpp file named "util_serial.cpp", like this:
util_serial.h :
#ifndef _UTIL_SERIAL_H_
#define _UTIL_SERIAL_H_
template<typename T> inline std::vector<T> slice_vec(std::vector<T>& vec, int _begin, int len);
#endif
util_serial.cpp :
#include "util_serial.h"
using namespace std;
template<typename T> inline std::vector<T> slice_vec(vector<T>& vec, int _begin, int len) {
if (_begin < 0) {
_begin = 0;
}
if (vec.size() < _begin) {
vector<T> v;
printf("slicing out of the vector range\n");
return v;
}
if (vec.size() < _begin + len) {
vector<T> v(vec.begin() + _begin, vec.end());
return v;
}
else {
vector<T> v(vec.begin() + _begin, vec.begin() + _begin + len);
return v;
}
}
Then I call this function in main function at another cpp file :
#include "util_serial.h"
using namespace std;
void main() {
vector<int> v3(4, 8);
vector<int> v4;
v4 = slice_vec(v3, 0, 2);
for (unsigned int i = 0; i < v4.size(); i++) {
cout << v4[i] << endl;
}
}
And then a LINK error occurred:
But when I define this function in the util_serial.h file right there after the declaration, this error disappeared.
This is what I used to do, declaring a function in a header file and putting its definition in another cpp file and it always works. But why this time it doesn't ?

That's how templates work. If you don't put the template function into the header file you need to explicitely instantiate the function for the type(s) that you need.
template std::vector<int> slice_vec<int>(std::vector<int>& vec, int _begin, int len);
See also How do I explicitly instantiate a template function?.

Related

Vector declared in header file isn't being recognized C++

I have been having a lot of issues with header files, and now it seems that the vector that is declared in my header file, Polynomial.hpp, is not being recognized in Polynomial.cpp. I have already included std:: which seems to be a common mistake, so I don't know where to go from here.
Header file:
#ifndef POLYNOMIAL_HPP
#define POLYNOMIAL_HPP
#include<vector>
#include"term.hpp"
class Polynomial {
private:
std::vector<Term> vect;
public:
Polynomial();
~Polynomial();
void add(Term t);
void print();
Polynomial combineLikeTerms();
};
#endif
cpp File:
#include "term.hpp"
#include "Polynomial.hpp"
#include<iostream>
#include<map>
using namespace std;
void add(Term t) {
vect.push_back(t);
}
void print() {
for(int i = 0; i < vect.size(); i++) {
cout << vect[i].toString();
}
}
Polynomial combineLikeTerms() {
Polynomial poly;
map<int, int> combinedPoly;
for(int j = 0; j < vect.size(); j++)
{
combinedPoly.insert(pair<int, int>(vect[j].getExponent(), vect[j].getCoefficient());
}
for(map<int,int>::iterator itr = combinedPoly.begin(); itr != combinedPoly.end(); itr++) {
Term newTerm(itr->second, "x", itr->first);
poly.add(newTerm);
}
return poly;
}
Error (1/6):
Polynomial.cpp:9:5: error: use of undeclared identifier 'vect'
vect.push_back(t);
In Polynomial.cpp you are defining new functions instead of member functions. Change the definitions to use the class name like
void Polynomial::add(Term t) {
vect.push_back(t);
}
Your void add(Term T) in Polynomial.cpp is not the member function of the Polynomial.
You must implement this function as member of Polynomial like this
void Polynomial::add(Term T){
...
}
I think this is a syntax error. First, you defined the add method in the Polynomial class of the header file, but the CPP file did not add the class scope, which caused this problem. So you should adjust your code like this:
void Polynomial::add(Term t) {
vect.push_back(t);
}
The root cause of this problem is that the methods of the class only work within the scope of the class, and if there is a function with the same name inside the class, it will lead to a naming conflict. Therefore, the root cause of this problem is not the reference error of the vector file.
The issue is that instead of defining the members add and print of the class Polynomial, you are defining functions in global scope completely unrelated to the class Polynomial
Make changes in the function definition of void add(Term) and void print() to void Polynomial::add(Term) and void Polynomial::print().
#include "term.hpp"
#include "Polynomial.hpp"
#include<iostream>
#include<map>
using namespace std;
void Polynomial::add(Term t) { // change here
vect.push_back(t);
}
void Polynomial::print() { //change here
for(int i = 0; i < vect.size(); i++) {
cout << vect[i].toString();
}
}
Polynomial combineLikeTerms() {
Polynomial poly;
map<int, int> combinedPoly;
for(int j = 0; j < vect.size(); j++)
{
combinedPoly.insert(pair<int, int>(vect[j].getExponent(), vect[j].getCoefficient());
}
for(map<int,int>::iterator itr = combinedPoly.begin(); itr != combinedPoly.end(); itr++) {
Term newTerm(itr->second, "x", itr->first);
poly.add(newTerm);
}
return poly;
}

Why am I getting the error 'undefined reference to `MinHeap<char>::insert(char, int)`' [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 2 years ago.
I am currently trying to implement a min heap, however, I am running into an issue.
I am having difficulty determining why my code is not linking properly when I compile it. The files, commands, and error are as follows:
min_heap.h
#ifndef MIN_HEAP_H
#define MIN_HEAP_H
#include <vector>
#include <algorithm>
using namespace std;
template <typename T>
struct HeapNode {
HeapNode(const T data, const int key) : data(data), key(key) {}
bool operator<(const HeapNode<T>& rhs) {return this->key < rhs.key;}
bool operator<=(const HeapNode<T>& rhs) {return this->key <= rhs.key;}
T data;
int key;
};
template <typename T>
class MinHeap {
public:
MinHeap() {};
~MinHeap() {};
void insert(const T data, const int key);
T extract_min();
T peek() const;
int size() const;
private:
vector<HeapNode<T>> heap;
};
#endif
min_heap.cpp
#include <iostream>
#include "min_heap.h"
using namespace std;
template <typename T>
void MinHeap<T>::insert(const T data, const int key){
cout << "Insertion." << endl;
if(this->heap.size() == 0){
cout << "adding first node" << endl;
this->heap.push_back(new HeapNode<T>(data, key));
}else{
cout << "not first node." << endl;
this->heap.push_back(new HeapNode<T>(data, key));
int currentIndex = this->heap.size() - 1;
while(((currentIndex - 1) / 2) >= 0){
if(this->heap[(currentIndex - 1) / 2] > this->heap[currentIndex]){
swap(this->heap[currentIndex], this->heap[(currentIndex - 1) / 2]);
currentIndex = ((currentIndex - 1) / 2);
}else{
break;
}
}
}
}
template <typename T>
T MinHeap<T>::extract_min(){
T data;
data = NULL;
return data;
}
template<typename T>
T MinHeap<T>::peek() const{
T data;
if(this->heap.size() == 0){
cout << "size: 0" << endl;
data = NULL;
}else{
cout << "something in there" << endl;
data = this->heap[0];
}
return data;
}
template<typename T>
int MinHeap<T>::size() const {
return this->heap.size();
};
customMain.cpp
#include <iostream>
#include "min_heap.h"
using namespace std;
int main(){
MinHeap<char> heap = MinHeap<char>();
const char data = 'a';
const int key = 7;
heap.insert(data, key);
return 0;
}
I am compiling the files above with the following
g++ -c min_heap.cpp
g++ -c customMain.cpp
g++ min_heap.o customMain.o
The error:
customMain.o:customMain.cpp:(.text+0x41): undefined reference to `MinHeap<char>::insert(char, int)'
collect2.exe: error: ld returned 1 exit status
Any help would be greatly appreciated!
Two options.
1) Move the template implementations out of the cpp file, and put them in the header. The compiler, when compiling main.cpp, cannot see the code it needs to generate the specialisation for char, so you end up being left with an unresolved external. Moving the code to the header will solve the issue (almost all template code resides in header files)
2) You can export specialisations from the cpp file, but then the types are locked down in advance (i.e. you can only use the exported types), which kinda reduces the flexibility and whole point of using templates. That's why 99.99% of people choose option 1, 99.99% of the time.
// export specialisations for char, short, int, and float
template class MinHeap<char>;
template class MinHeap<short>;
template class MinHeap<int>;
template class MinHeap<float>;

weird undefined reference error when compiling multiple files [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
I am trying to code a toy program to exercise C++, but I got a weird undefined reference error that I can not solve.
My code consists of 3 file:
ex13_6.h:
#include<vector>
namespace ex13_6 {
template<class T> class Cmp {
public:
static int eq(T a, T b) {return a == b;}
static int lt(T a, T b) {return a < b;}
};
template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v);
}
ex13_6.cpp
#include<vector>
#include"ex13_6.h"
namespace ex13_6 {
template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) {
int s = v.size();
T swap;
for (int i=0; i<s; i++) {
for (int j=0; j<s; j++) {
if (C::lt(v.at(j), v.at(i))) {
swap = v.at(i);
v.at(i) = v.at(j);
v.at(j) = swap;
}
}
}
}
}
main.cpp:
#include"ex13_6.h"
#include<iostream>
#include<vector>
using namespace std;
using namespace ex13_6;
int main() {
// Sort using default comparison for int
vector<int> v_int;
for (int i=0; i<10; i++) {
v_int.push_back(10-i);
}
bubble_sort(v_int);
cout << "sort of int vector:\n";
for (vector<int>::const_iterator it = v_int.begin(); it != v_int.end(); it++) {
cout << ' ' << *it;
}
cout << '\n';
}
And I am compiling using:
g++ main.cpp -o main -std=gnu++0x ex13_6.cpp
Here is the error message:
/tmp/ccRwO7Mf.o: In function `main':
main.cpp:(.text+0x5a): undefined reference to `void ex13_6::bubble_sort<int, ex13_6::Cmp<int> >(std::vector<int, std::allocator<int> >&)'
collect2: ld returned 1 exit status
I really appreciate any help!
Move your implementation of the bubble_sort template into your header file.
Templates are not like generics from Java, all the magic happens at compile time in C++. In order for the compiler to generate the code for each template instantiation, it must be visible, and to do that, it must be in the header (or some other file) and included in each translation unit that uses it.
Your templated function definition should be in the ex13_6.h file:
#include<vector>
namespace ex13_6 {
template<class T> class Cmp {
public:
static int eq(T a, T b) {return a == b;}
static int lt(T a, T b) {return a < b;}
};
template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) {
int s = v.size();
T swap;
for (int i=0; i<s; i++) {
for (int j=0; j<s; j++) {
if (C::lt(v.at(j), v.at(i))) {
swap = v.at(i);
v.at(i) = v.at(j);
v.at(j) = swap;
}
}
}
}
}
You need to put the template implementation in the header file.
When instantiating a template the compiler needs to "see" the implementation, so if you just include the header, the implementation needs to be there.
Don't include a .cpp file.

C++ function with a struct vector as a return value

I want to create a private function in C++ (VS2010).
It should return a vector/array of structs/userdefined type.
However I think my declaration of the function in the cpp file is perhaps wrong.
Or maybe already in the header. Can somebody have a look at it?
My header looks like this:
#pragma once
using namespace std;
#include <algorithm>
#include <vector>
class clsWString2
{
private:
struct udtWChar2
{
wstring Text;
int OrigPos;
};
bool m_bDirty;
vector<udtWChar2>pToWChar2(wstring u);
vector<udtWChar2>m;
public:
clsWString2(void);
~clsWString2(void);
void ReplaceCompareBinary(wstring uSearchFor, wstring uReplaceBy);
void ReplaceCompareText(wstring uSearchFor,wstring uReplaceBy);
void ReplaceByPos(int uStartPos1Based,int uLen0Based, wstring uReplaceBy);
void FeedString(wstring u);
void Append(wstring u);
wstring CharAtPos(int uIndex);
int OrigPos(int uIndex);
};
And my .cpp file looks like this:
#include "StdAfx.h"
#include "clsWString2.h"
clsWString2::clsWString2(void)
{
m.resize(0);
}
clsWString2::~clsWString2(void)
{
}
vector<udtWChar2> clsWString2::pToWChar2(wstring u)
{
vector<udtWChar2> n;
n.resize(0);
for (int i=0;i<u.size();i++)
{
wstring sChar;
sChar=u.substr(i,1);
udtWChar2 nc;
nc.Text =sChar;
nc.OrigPos=i;
n.push_back (nc);
}
return n;
}
In the source file, when you define the function, the return type is not in the scope of the class so the class in the vector needs to be fully qualified:
vector<clsWString2::udtWChar2> clsWString2::pToWChar2(wstring u)
{
...
}
Ah, I got it:
vector<clsWString2::udtWChar2> clsWString2::pToWChar2(wstring u)
You can not use directly udtWChar2 as type , you need define type def or you need use as struct udtWChar2
Like :
in .h
vector < struct udtWChar2 > pToWChar2(wstring u);
vector < struct udtWChar2 > m;
in .cpp
vector < struct clsWString2::udtWChar2 > clsWString2::pToWChar2(wstring u)

redefinition of template<class T> in C++

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.