I am implementing a simple Linked List, but I keep getting the LNK2019 error, I simplified my code to the minimum to track the problem,but I keep getting it. I am using Visual Studio 2010. My header file is:
#ifndef __TSLinkedList__H__
#define __TSLinkedList__H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "LinkedNode.h"
template <class T>
class LinkedList
{
public:
LinkedList(void);
~LinkedList(void);
protected:
LinkedNode<T> * head;
};
The implementation file is:
#include "StdAfx.h"
#include "LinkedList.h"
template <class T>
LinkedList<T>::LinkedList(void)
{
head = NULL;
}
template <class T>
LinkedList<T>::~LinkedList(void)
{
}
the main function is:
#include "stdafx.h"
#include "stdlib.h"
#include "LinkedList.h"
int _tmain(int argc, _TCHAR* argv[])
{
LinkedList<int> mList;
system("PAUSE");
return 0;
}
and I am getting this error:
Error 1 error LNK2019: sÃmbolo externo "public: __thiscall LinkedList::~LinkedList(void)" (??1?$LinkedList#H##QAE#XZ) in function _wmain
I get the same error with the Constructor. The funny thing is that it is pointing to _wmain, and my main function is called _tmain. I already tried to change Subsystem linker from /SUBSYSTEM:WINODWS to /SUBSYSTEM:CONSOLE, but it was already set up as /SUBSYSTEM:CONSOLE. Obviously my implementation does a lot more than this, but I ripped out all of it to track this problem. Help wpuld be apreciated, this is driving me nuts. I am new to C++.
Move the function implementations to the header file.
In order to generate code for the specialization, the compiler must have the definitions of the functions available to each translation unit.
#ifndef __TSLinkedList__H__
#define __TSLinkedList__H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "LinkedNode.h"
template <class T>
class LinkedList
{
public:
LinkedList(void);
~LinkedList(void);
protected:
LinkedNode<T> * head;
};
template <class T>
LinkedList<T>::LinkedList(void)
{
head = NULL;
}
template <class T>
LinkedList<T>::~LinkedList(void)
{
}
#endif
The compiler doesn't compile your template class member definitions, since they are not included in any compilation unit.
However, it does see that some members are used, so it will generate 'undefined' symbols for these.
Then comes the linker, trying to match the undefined symbols to some symbols defined in one of the compiled object files.
But, the LinkedList::~LinkedLis() destructor hasn't been compiled, so it's in none of the object files, and that's what the linker complains about.
You can fix this by
including the definition file in the main source file,
or pasting the definitions inside the template header file,
or including the template implementation file from the bottom of the template header file (my favorite)
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I know this problem is well known, but none of the solutions work for me. I know a popular cause of this error is the compiler can't find the definition of a function in any of the source files, but I have defined the function them.
I am using Visual studio 2015 community.
Form.h
#pragma once
template<typename T>
class Form
{
public:
void GenerateForm(T i);
};
Form.cpp
#include "stdafx.h"
#include "Form.h"
template<typename T>
void Form<T>::GenerateForm(T i)
{
std::cout << i << endl;
}
Main.cpp
#include "stdafx.h"
#include "Form.h"
int main()
{
Form<int> f;
f.GenerateForm(12);
return 0;
}
Error:
PrimeForm.obj : error LNK2019: unresolved external symbol "public: void __thiscall Formula<double>::GenerateForm(int)" (?GenerateForm#?$Formula#N##QAEXH#Z) referenced in function _main
C:\Users\John\Dropbox\Visual Studio 2015\PrimeForm\Debug\PrimeForm.exe : fatal error LNK1120: 1 unresolved externals
When you try to compile form.cpp the compiler doesn't know what type T will be. Therefore it won't be able to compile this as an object file to be linked with your compiled main.cpp object file.
You'll need to include all of the declarations and definitions of a templated class to the files that need it (in this case your main.cpp file).
This can be simply done as follows:
Form.h
#pragma once
template<typename T>
class Form
{
public:
void GenerateForm(T i);
};
#include "Form.template" /* Note include Form.template here */
Form.template
#include "stdafx.h"
/* Don't include form.h in this file */
template<typename T>
void Form<T>::GenerateForm(T i)
{
std::cout << i << std::endl;
}
main.cpp
#include "stdafx.h"
#include "Form.h" /* including Form.h will include Form.template as well */
int main()
{
Form<int> f; /* Compiler now knows to instantiate a Form class with type Int as the template parameter */
f.GenerateForm(12);
return 0;
}
Note the main difference is that you don't include "Form.h" in Form.template but include "Form.template" at the bottom of Form.h
It is better practice to use the ".template" file ending for templated class implementation files.
I'm trying to intercept "the data" from standard output (for this question I'm working with cout). Also for this question I'm working with double, but the program should be able to handle any primitive data type. When I try to compile my code I get this error:
undefined reference to `std::ostream& SpyOutput::operator<<
(double const&)' collect2: error: ld returned 1 exit status
this is my main:
#include "SpyOutput.h"
#define endl '\n'
int main ( int argc, char *argv[], char *env[] ) {
double d1 = 12.3;
SpyOutput spy(&cout);
spy << d1;
return 0;
}
this is my header file:
#include <iostream>
using namespace std;
class SpyOutput {
private:
ostream* output;
public:
SpyOutput(ostream* os);
template <class T>
ostream &operator<<(const T &x);
};
this is my implementation file:
#include "SpyOutput.h"
SpyOutput::SpyOutput(ostream* os){
output = os;
}
template <class T>
ostream& SpyOutput::operator<<(const T &x){
// SOME CODE GO HERE
return *output;
}
I have googled this error (and similar) without finding a working solution, thanks in advance for any help or hint that you can provide to me! :-)
What's the problem?
For an explanation why it doesn't compile, see "Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?"
As an example, consider the header file foo.h which contains the following template function declaration:
// File "foo.h"
template<typename T>
void foo();
Now suppose file foo.cpp actually defines that template function:
// File "foo.cpp"
#include <iostream>
#include "foo.h"
template<typename T>
void foo()
{
std::cout << "Here I am!\n";
}
Suppose file main.cpp uses this template function by calling foo():
// File "main.cpp"
#include "foo.h"
int main() { foo<int>(); ... }
If you compile and link these two .cpp files, most compilers will generate linker errors. Because in order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to "fill in" the template. If the template body is defined in the .cpp the compiler won't see it and hence won't generate any code for it.
How to fix it?
There is more than one possible solution around this issue. I suggest moving the definition of the template function into the .h file.
// File "foo.h"
template<typename T>
void foo()
{
std::cout << "Here I am!\n";
}
In your source you can call it as usual:
// File "main.cpp"
#include "foo.h"
int main() { foo<int>(); ... }
You need to place your template implementation of SpyOutput::operator<< into the header file
I decided to cut the necessary code down to the bare minimum needed to display this error. I have an STL list wrapper template class that exists in hc_list.h file. The entire code is below:
// hc_list.h file
#ifndef HC_LIST_H
#define HC_LIST_H
#include <cstdlib>
#include <list>
template <typename T>
class hcList
{
private:
std::list<T> selfList ; // a single internal STL list to hold the values
public:
hcList(void) {} ;
~hcList(void){} ;
// The error occurs on the line below
template <typename U> friend std::ostream& operator<<(std::ostream &, const hcList<U> &) ;
} ;
#endif // HC_LIST_H
This code is included in the main.cpp file, where the main function is below:
// main.cpp file
#include <iostream>
#include "hc_list.h"
int main()
{
std::cout << "Begin Test" << std::endl;
return 0;
}
This code, when entered into a CodeBlocks project will compile as is with 0 errors or warnings. However, then I include another cpp file and attempt to include the list header, like the following:
// anyNamedFile.cpp file
#include "hc_list.h"
When I include any cpp file into the project, I get a compiler error:
error: expected initializer before '&' token
I do not understand what I am doing wrong, and could really use some help.
Your header file uses std::ostream, (just before an &) but does not include any header which might declare it.
Try adding
#include <iosfwd>
in your header.
I have a rather standard situation where I want to use a templated class in the following way:
Define a .h file
Have it include the .cpp
In every other compiler that I try (i.e. g++ and clang/llvm) this works fine. In visual studio, it tells me that the file has already been defined.
If I manually cut and paste the text from the .cpp into the .h file, then everything works out just fine. I was under the impression that that was exactly what #include was supposed to do.
My hunch is that visual studio is compiling the .cpp file more than once somehow (though I placed #pragma once on the .h and .cpp files).
What is going on, and how can I make my template classes behave in VS?
Code follows:
.h:
#pragma once
template <class T>
class myVector
{
private:
void grow();
public:
int size;
int index;
T** words;
void pushBack(T* data);
inline T* operator[](int);
myVector(void);
~myVector(void);
};
#include "myVector.cpp"
.cpp:
#pragma once
#include "stdafx.h"
#include <cstdlib>
#include "myVector.h"
#include <iostream>
using namespace std;
template<class T>
myVector<T>::myVector(void)
{
this->size = 2000;
words = new T*[size];
index=0;
}
template<class T>
void myVector<T>::pushBack(T* input)
{
if(index<size)
{
words[index]=input;
}
else
{
grow();
words[index]=input;
}
index++;
}
template<class T>
T* myVector<T>::operator[](int i)
{
return words[i];
}
template<class T>
void myVector<T>::grow()
{
//cout<<"I grew:"<<endl;
size*=2;
words = (T**)realloc(words,size*sizeof(T*));
}
template<class T>
myVector<T>::~myVector(void)
{
delete[] words;
}
It seems to me that your confusion arises from not knowing how #pragma once and translation units work.
#pragma once, much like include guards, prevent the contents of a file (usually a header) from being pulled into a single translation unit more than once.
If you #include <vector> in multiple implementation files, the contents will be pulled in all of them, but only once for each translation unit.
So you should remove the #include "myVector.cpp", as MSVS automatically compiles implementation files, and it's also wrong.
Note that template definitions have to be visible, so you'll need to either move them to the .h file, like you did, or, using your current approach, rename the .cpp file to something like .impl or even .h and include it.
I'm trying to create a linked list class in Eclipse but I can't get it to compile properly.
Here is my .cc file (code snipet)
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
and here is my list.h file (code snipet)
#ifndef __LIST_H__
#define __LIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "list.cc"
#endif /* __LIST_H__ */
I try "Building All" in eclipse but I get the following error:
make all
Building file: ../list.cc
Invoking: Cross G++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"list.d" -MT"list.d" -o "list.o" "../list.cc"
../list.cc:13: error: redefinition of 'bool List<T>::isEmpty()'
../list.cc:13: error: 'bool List<T>::isEmpty()' previously declared here
make: *** [list.o] Error 1
Help please...thanks. I'll be happy to provide any clarifications needed
EDIT: I was given the .h file so I know that it is correct. I also know that I am supposed to have a .cc file called list.cc (it is included at the end of the .h file)
You need to change the extension of the file with the implementation.
The compiler will process this file for compilation and will process it twice, since you're including it in the header.
Your file looks like this:
#include <iostream>
#include "list.h"
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
#include "dlist.cc"
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
which will in turn become
#include <iostream>
#ifndef __DLIST_H__
#define __DLIST_H__
template <typename T>
class List {
public:
bool isEmpty();
private:
struct node {
node *following;
node *previous;
T *contents;
};
node *firstNode;
};
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
#endif /* __DLIST_H__ */
using namespace std;
template <class T>
bool List<T>::isEmpty()
{
return (firstNode == NULL);
}
So the function isEmpty() is defined twice.
Rename the file to dlist.impl.
Try putting the definition for List<T>::isEmpty() in the same file as the class is declared.
Given the unusual form of the header you've been supplied with, to test it you will need another source file. To start with the new source file (say test.cpp) can just #include "list.h", which will check for any syntax errors but will not yet instantiate your List template.
(Just compile test.cpp, not list.cc, since list.cc is indirectly included by test.cpp)