C++ Unresolved external symbol with Class templates [duplicate] - c++

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 9 years ago.
Here's a simple example of using class templates in C++. This code works.
#include <iostream>
using namespace std;
template <class T>
class Test {
public:
Test();
void print();
private:
int i;
};
template <class T>
Test<T>::Test() {
i=1;
cout<<"New instance"<<endl;
}
template <class T>
void Test<T>::print() {
cout<<"Test"<<endl;
}
int main() {
Test<int> i;
i.print();
return 0;
}
So when I separate this code in 3 files: main.cpp, Test.h, Test.cpp:
//Test.h
#include <iostream>
using namespace std;
template <class T>
class Test {
public:
Test();
void print();
private:
int i;
};
//Test.cpp
#include "Test.h"
template <class T>
Test<T>::Test() {
i=1;
cout<<"New instance"<<endl;
}
template <class T>
void Test<T>::print() {
cout<<"Test"<<endl;
}
//main.cpp
#include "Test.h"
using namespace std;
int main() {
Test<int> i;
i.print();
return 0;
}
I get an errors:
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Test<int>::print(void)" (?print#?$Test#H##QAEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Test<int>::Test<int>(void)" (??0?$Test#H##QAE#XZ) referenced in function _mai
1>C:\Programming\C++\stuff\templass\Debug\templass.exe : fatal error LNK1120: 2 unresolved externals
I use Microsoft Visual C++ 2010 Express. So I searched a lot about unresolved external symbol but didn't find anymore for this case. So what's my mistake?

Templates cannot be compiled like any other source file. Both interface and implementation should live in the header file (although some split them in .hpp files for interface and .ipp files for implementation, and then include the .ipp file at the end of the .hpp file).
How would the compiler know what classes to generate when the template class is compiled?

Related

unresolved external symbol when passing a function pointer [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
I'm trying to create a generic button and I want to be able to pass a function to call when I click it.
main.cpp:
#include "Window.h"
int testfunction() {
print("Test");
return 1;
}
...other stuff...
window->SetButtonFunction_NoArgs<int>(" *unrelated stuff* ", &testfunction);
window is a WindowMain class:
window.h:
class WindowMain {
*Stuff*
template <class R1> void SetButtonFunction_NoArgs(string id, R1(*func)());
*Other Stuff*
};
window.cpp:
///Find the object of that id and set the fuction to it
template <class R1> void WindowMain::SetButtonFunction_NoArgs(string id, R1(*func)()) {
for (int i = 0; i < objects_.size(); i++) {
if (objects_[i].getId() == id) {
objects_[i]->AddButton_NoArgs<R1>(func);
}
}
}
The problem is here somewhere I think but I can't find it... When I try to compile it gives me this:
1>main.obj : error LNK2019: unresolved external symbol "public: void __cdecl WindowMain::SetButtonFunction_NoArgs<int>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int (__cdecl*)(void))" (??$SetButtonFunction_NoArgs#H#WindowMain##QEAAXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##P6AHXZ#Z) referenced in function "void __cdecl Create(void)" (?Create##YAXXZ)
Thanks for help!
Template methods must be defined in header file. If it wasn't template you could move definition to .cpp file (you would want to include window.h though)

linker error (unresolved symbol) with template class in DLL

I get a linker error - unresolved symbol - when using a (specialized) template class from a DLL (Visual Studio 2008 compiler). I tried to use the 'explicit template instantiation' trick described also here in Stackoverflow, but it didn't work. I broke it down to a very simple reproducable example:
I have a dynamic library (DLL) 'MyTemplates.lib' with a header file 'MyTemplates.h' (and a source file 'MyTemplates.cpp' without any code which simply includes this header file) with the following content:
template <class T>
class A
{
public:
A()
{ int x = 7; }
};
template <class T>
class B : public A<T>
{
public:
B()
{}
};
// do explicit template instantiation for classes A<int> and B<int>
// macro 'MYTEMPLATES_API' is defined in the usual way as:
//#ifdef MYTEMPLATES_EXPORTS
// #define MYTEMPLATES_API __declspec( dllexport )
//#else
// #define MYTEMPLATES_API __declspec(dllimport)
//#endif
template class MYTEMPLATES_API A<int>;
template class MYTEMPLATES_API B<int>;
Now i have another dynamic library 'UserLibary' (which links against 'MyTemplates.lib') with the files 'Util.h' and Util.cpp'. The file 'Util.h' is as follows:
#include "MyTemplates.h"
class UserClass
{
public:
UserClass();
public:
A<int> bla;
B<int> blubb;
};
and the content of the file 'Util.cpp' is:
#include "Util.h"
UserClass::UserClass()
{
}
The problem is now that my library 'UserLibrary' does compile well, but it gives two linker errors as follows:
1>Util.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall B<int>::B<int>(void)" (__imp_??0?$B#H##QAE#XZ) referenced in function "public: __thiscall UserClass::UserClass(void)" (??0UserClass##QAE#XZ)
1>Util.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall A<int>::A<int>(void)" (__imp_??0?$A#H##QAE#XZ) referenced in function "public: __thiscall UserClass::UserClass(void)" (??0UserClass##QAE#XZ)
So the linker can not find the symbols for the default constructors of classes A<int> and B<int>. Why is this possible, and how can i get rid of these linker errors ? I thought that the explict template instantiation of the class A<int> and B<int> (in file 'MyTemplates.h') would solve this, but unfortunately it doesn't seem to help - or am I using it in the wrong way ? My compiler is Visual Studio 2008, operating system is windows 7 64 bit, and code is compiled in 64bit.

LNK2019 linking error in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ template, linking error
I have two linking errors and I have no idea what's wrong with the code and how to fix them:
main.obj:-1: error: LNK2019: unresolved external symbol "public:
__thiscall A::A(void)" (??0?$A#VB####QAE#XZ) referenced in function "public: __thiscall B::B(void)" (??0B##QAE#XZ)
and
main.obj:-1: error: LNK2019: unresolved external symbol "public: void
__thiscall A::exec(void (__thiscall B::*)(void))" (?exec#?$A#VB####QAEXP8B##AEXXZ#Z) referenced in function "public:
void __thiscall B::run(void)" (?run#B##QAEXXZ)
Explaining the code a little:
This class has to execute a function from the derived class. function exec is called from the derived class with a function from the derived class parameter. Signature of this function is void function();
//header.h
#ifndef HEADER_H
#define HEADER_H
template <class T>
class A
{
public:
typedef void (T::*ExtFunc)();
A();
void funcA();
void exec(ExtFunc func);
};
#endif // HEADER_H
//header.cpp
#include "header.h"
template<typename T>
A<T>::A() { }
template<typename T>
void A<T>::funcA()
{
cout << "testA\n";
}
template<typename T>
void A<T>::exec(ExtFunc func)
{
(T().*func)();
}
In main.cpp I derive a class from A class and pass the derived class as template paramtere. Then I execute function exec through the run() function.
//main.cpp
#include <iostream>
#include "header.h"
using namespace std;
class B : public A<B>
{
public:
B() { }
void run()
{
exec(&B::funcB);
}
void funcB()
{
cout << "testB\n";
}
};
int main()
{
B ob;
ob.run();
return 0;
}
Can anyone tell me what's going on?...
When you are using templates, generally you cannot put the implementation in a .cpp file - you have to put the whole class in the header. So move all the code from header.cpp to the .h.
You can get around this by doing an explicit instantiation inside the .cpp file - instantiating the template for a particular type. But this requires that you know ahead of time which types will need an instantiation and will prevent you from adding new instantiations. The only benefit is a reduction in compile time.

Function returns enum defined in another class (fatal link error)

This seems like a problem that is common. I defined an enum in classA and then included classA in classB. Then, in classB I defined a function which returns the enum type defined in classA...see below. I get the following error:
aFirst.obj : error LNK2019: unresolved external symbol "public: enum justEnum::things_t __thiscall usesTheEnum::returnsThings(void)" (?returnsThings#usesTheEnum##QAE?AW4things_t#justEnum##XZ) referenced in function _wmain
1>C:\Documents and Settings\Ben\My Documents\Visual Studio 2010\Projects\aFirst\Debug\aFirst.exe : fatal error LNK1120: 1 unresolved externals
#pragma once
class justEnum
{
public:
justEnum(void);
~justEnum(void);
enum things_t{ONE, TWO};
};
#pragma once
#include "justEnum.h"
class usesTheEnum
{
public:
usesTheEnum(void);
~usesTheEnum(void);
justEnum::things_t returnsThings(void);
};
#include "StdAfx.h"
#include "usesTheEnum.h"
#include "justEnum.h"
usesTheEnum::usesTheEnum(void)
{
}
usesTheEnum::~usesTheEnum(void)
{
}
justEnum::things_t returnsThings()
{
return justEnum::ONE;
}
// tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include "justEnum.h"
#include "usesTheEnum.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
usesTheEnum aUser;
justEnum anEnum;
justEnum::things_t anotherEnum;
anotherEnum = justEnum::ONE;
aUser.returnsThings();
cout << anotherEnum;
return 0;
}
You need to specify that your definition of returnsThings() is part of the usesTheEnum class.
justEnum::things_t usesTheEnum::returnsThings()
{
return justEnum::ONE;
}
error LNK2019: unresolved external symbol "public: enum justEnum::things_t __thiscall usesTheEnum::returnsThings(void)"
The compiler is complaining that usesTheEnum::returnThings() is not defined, and I cannot see a definition in the code you posted. You should provide a definition for the function in one translation unit.
I don't think I can emphasize enough how important it to learn to read error messages. The compiler is doing it's best to tell you what is wrong.
not shure, but can't you just move the enum out of the class?
Or on the .cpp of the class write something like
extern enum classname::things_t;
just to have the enum added to the generated lib wich is what will be linked against.

Linker error LNK2019 while trying to compile prog with template declarations

Here the code
#include <iostream>
#include <conio.h>
using namespace std;
template <typename T> class grid
{
public:
grid();
~grid();
void createCells();
private:
T **cells;
};
int main(int argc, char **argv)
{
grid<int> intGrid;
_getch();
return 0;
}
While trying to compile - got a message:
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall
grid<int>::~grid<int>(void)" (??1?$grid#H##QAE#XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall
grid<int>::grid<int>(void)" (??0?$grid#H##QAE#XZ) referenced in function _main
What need to do?
You need to define the constructor and destructor (you just declared them):
template <typename T> class grid
{
public:
grid()
{} // here
~grid()
{} // and here
void createCells();
private:
T **cells;
};