unresolved external symbol "public: __thiscall Vector<int> [...]" - c++

So, I've created a basic VC++ program, and created a template class with 1 method (besides the constructor and destructor). I'm getting the following errors:
>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Vector<int>::~Vector<int>(void)" (??1?$Vector#H##QAE#XZ) referenced in function _main
>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Vector<int>::Vector<int>(int)" (??0?$Vector#H##QAE#H#Z) referenced in function _main
>c:\users\edy\documents\visual studio 2010\Projects\ex01\Debug\ex01.exe : fatal error LNK1120: 2 unresolved externals
Here is my code:
(CPP Class file)
using namespace std;
#include "Vector.h"
template <class T> Vector<T>::Vector(int n)
{
this.crt = 0;
this.dim = n;
this.elem = new T[100];
}
template <class T> void Vector<T>::add(T e)
{
this.elem[crt] = e;
this.crt++;
}
template <class T> Vector<T>::~Vector(void)
{
this.crt = 0;
}
(H Class file)
#pragma once
template <class T> class Vector
{
public:
int dim;
T* elem;
Vector(int n);
void add(T e);
~Vector(void);
private:
int crt;
};
(Main file)
using namespace std;
#include "Vector.h"
int main(void)
{
Vector<int> x(5);
//x.add(1); <--- if i decomment this line, it throws an additional error
return 0;
}
Most solutions involved not implemented methods, but I have all my methods implemented. I have no idea what could be wrong. Any help?

Template class implementation need to be visible to all translation units that use them. Move the implementations to the header file.
Before you ask - no, there's no way to hide them, unless you know in advance which specializations for the class you have. If you want your Vector to be generic, the implementations need to be visible.
If you want to separate them, to usual way to go about it is to have the implementations in a .impl file which you include in the header.

If you intend to implement the template in a .cpp file, you will need to provide an explicit instantiation of the template there as well. You can add to the template's .cpp file:
class template Vector<int>;
at the bottom. This will instantiate an int version of your vector template. But, you will find your template easier to use if you follow Luchian's advice. If you do as he suggests, the compiler will create the instantiations on demand for you as you use Vector<> on different types. If you leave it in a .cpp file, you will have to add an explicit instantiation each time you want to create a different kind of Vector<>.
Some think explicit instantiation is "leaner" than implicit, because if different sets of object files use the same template instantiations many times, the compiler may be creating just as many instantiations. However, the linker will remove the duplicate instantiations in the end when the executable is linked together. Even so, the bloat still persists if multiple shared libraries have reused the same template with the same parameters, even though the dynamic linker will clean it up. If executable loading time is important, this may be a reason to prefer explicit instantiation. If you have a very large project, and build and link times are an issue, this may also be a reason to prefer explicit instantiation.
Otherwise, you should stick with implicit instantiation.

Related

DLL + export class + template member func = unresolved external symbol. Any chance to fix?

First of all, This is not a duplicate question, because 1) this is a linker problem, compiler is passed successfully because I have explicitly instantiated. 2) It's not about template class, but template member function, 3) I have some restrictions on the code structure so some existing tricks do not apply. I have searched my title here and the first few threads (40832391, 20330521, 25320619, 12848876, 36940394) are all about template class, not template member function. Some other threads are actually talking about failure of instantiation so actually a compiler issue but I have tried explicit instantiation and compiling has passed successfully, to repeat. So I hope you can suppress the temptation a little bit to close my question as duplicate and here comes my thread.
Environment:
Windows 10 version 1803
Visual Studio 2015 Update 3
Debug x64 mode in VS
Source:
There are two projects:
1) DllProject, build as a dll, contains two sources: Dll.h and Dll.cpp.
Dll.h:
#pragma once
#ifdef _WINDLL
#define API_TYPE __declspec(dllexport)
#else
#define API_TYPE __declspec(dllimport)
#endif
class API_TYPE AClass {
public:
template <class T> void Func(T& data);
template <class T> void CallFunc(T& data) {
Func<T>(data);
}
};
Dll.cpp:
#include "Dll.h"
template <class T> void AClass::Func(T& data) {
data++;
}
template void AClass::Func<float>(float&); //attempt to explicitly instantiate
2) ExeProject, built as an exe, contains Exe.cpp.
Exe.cpp:
#include "Dll.h"
int main() {
AClass a;
float f = 0.f;
a.CallFunc<float>(f);
}
As you can see, what I want is to only call the template member function CallFunc defined in dll which in turn calls another core template member function Func that does the real work. I don't need to call Func directly in exe so I don't need to export it in dll. Only CallFunc is in the API that needs to be exported and it works fine. The dll project DllProject compiles correctly. The exe project ExeProject also compiles without any problem. But errors arise at linking time:
1>------ Build started: Project: ExeProject, Configuration: Debug x64 ------
1>Exe.obj : error LNK2019: unresolved external symbol "public: void __cdecl AClass::Func<float>(float &)" (??$Func#M#AClass##QEAAXAEAM#Z) referenced in function "public: void __cdecl AClass::CallFunc<float>(float &)" (??$CallFunc#M#AClass##QEAAXAEAM#Z)
1>C:\tmp\DllProject\x64\Debug\ExeProject.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I have explicitly instantiated the template member function Func in Dll.cpp at line 8, so compilation works. But linker fails to link to this instantiated function in dll from inside CallFunc. I think the function is instantiated in dll, not in exe, because I specified __declspec(dllimport) for the class. I don't know why CallFunc can't find Func; it's just right above it.
The sources are isolated and minimized from a big opensource (DllProject corresponds to the library itself while ExeProject to test code), so the implementation and declaration of template member function are separated into two files which is unavoidable in large project, and the code structure are not to be changed. The DllProject, as its name suggests, is to be build as a dll, though building and linking everything as static library works without any problem. I have done a lot of search, but threads in this forum and others either move the template implementation into the class declaration, or into the header by #include a .tpp file, all violating the above restrictions, or suggest explicit instantiation in various ways of expression, which I think I have done already because compiling is passed.
I have tried the following methods:
1) Compile under Release configuration
2) use inline (and even __forceinline)
3) Put explicit specialization in Dll.h in class:
class API_TYPE AClass {
public:
template <class T> void Func(T& data);
template<> void AClass::Func<float>(float&);
template <class T> void CallFunc(T& data) {
Func<T>(data);
}
};
4) Put explicit specialization in Dll.h outside class:
class API_TYPE AClass {
...
};
template<> void AClass::Func<float>(float&);
6) Put explicit instantiation in Dll.h outside class:
class API_TYPE AClass {
...
};
template void AClass::Func<float>(float&);
7) Add API_TYPE in the declaration of Func, template implementation and explicit instantiation
template <class T> void API_TYPE Func(T& data);
But none of them works and reports the same error.
8) Put explicit instantiation in Dll.h in class:
class API_TYPE AClass {
public:
template <class T> void Func(T& data);
template <class T> void CallFunc(T& data) {
Func<T>(data);
}
template void AClass::Func<float>(float&);
};
Compile error: error C2252: an explicit instantiation of a template can only occur at namespace scope
9) Put explicit specialization in Dll.cpp:
Compile error: error C2910: 'AClass::Func': cannot be explicitly specialized
I hope that's enough to demonstrate my effort. So, is there any chance to fix the "unresolved external symbol" under the aforementioned restriction? In case you forget it or didn't read it at all, the restriction is
The template implementation of Func must be separate
from its declaration, i.e., must not be in class declaration or in header file.
In case you assume I don't know template function should be instantiated, to repeat, I have explicitly instantiated Func, and tried it in many ways. So compiler is perfectly happy but the linker spews the error "unresolved external symbol." So why can't the linker find the already instantiated template member function? I also checked the output symbols in the import library DllProject.dll using dumpbin. The symbol ??$Func#M#AClass##QEAAXAEAM#Z indeed resides in it, as factual as the earth rotating eastward. So do you know how to actively trace the behavior of the linker to figure out why it fails to find the function location instead of blind guessing? Thanks a lot.
№6 with export directive should work:
template API_TYPE void AClass::Func<float>(float&);
Explicit instantiation tells the compiler that this variant is instantiated in some translation unit while export directive informs the linker that it is should be exported / imported.

unresolved external symbol - constructor

I have a class graph.h written like this
#include <fstream>
using namespace std;
template <typename T>
class Graph
{
private:
T ** graphData;
public:
Graph(ifstream & inputFile);
~Graph(){};
friend ofstream & operator<<(ostream&, const Graph &);
};
where constructor Graph(ifstream & inputFile); is defined in graph.cpp:
#include "graph.h"
template <typename T>
Graph<T>::Graph(ifstream & inputFile){}
I tried to make an instance of this class in main.cpp:
#include <fstream>
#include "graph.h"
using namespace std;
int main()
{
ifstream myFile ("example.txt");
Graph<int> * IntGraph = new Graph<int>(myFile);
return 0;
}
but I keep getting these errors
Error 1 error LNK2019: unresolved external symbol "public: __thiscall Graph<int>::Graph<int>(class std::basic_ifstream<char,struct std::char_traits<char> > &)" (??0?$Graph#H##QAE#AAV?$basic_ifstream#DU?$char_traits#D#std###std###Z) referenced in function _main C:\Users\Vlada\Dropbox\FJFI\BP - Graph partitioning\BP-program\BP-program\main.obj BP-program
Error 2 error LNK1120: 1 unresolved externals C:\Users\Vlada\Dropbox\FJFI\BP - Graph partitioning\BP-program\Debug\BP-program.exe BP-program
I tried to search, but none of the result I found seemed to me like this.
Each compilation unit that refers to member functions of a template class needs to see the function definitions.
So move the constructor definition from the cpp module to the header.
Use the following include statement after your declaration of graph.h. This way the implementation is still separated from the definition, and the compiler can access it.
#include "graph.cpp"
A template is not a class or a function. A template is basically a generalized pattern which helps the compiler to generate a particular type of requested class or a function.
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. For example, if you’re trying to use a Graph, the compiler must see both the Graph template and the fact that you’re trying to make a specific Graph.
Your compiler probably doesn’t remember the details of one .cpp file while it is compiling another .cpp file. This is called the “separate compilation model.”
References :
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
Why can templates only be implemented in the header file?

global template objects c++

i have a class
class ICIecHdlcSetup
{
//some thing
};
to create a global access object i do this:
//in obj.cpp:
ICIecHdlcSetup obj_ICIecHdlcSetup(0x00,0x00,0x16,0x00,0x00,0xFF);
//in obj.hpp:
extern ICIecHdlcSetup obj_ICIecHdlcSetup;
now i have a template class:
template <class TValue>
class ICData
{
//some thing
};
but the same way would not work
//in obj.cpp:
ICData <uint8_t> temperture(7,64,41,0,0,255) ;
//in obj.hpp:
extern ICData <uint8_t> temperture ;
and make this error:
Error 10 error LNK2019: unresolved external symbol "public: void __thiscall ICData<unsigned char>::set_value(unsigned char)" (?set_value#?$ICData#E##QAEXE#Z) referenced in function "void __cdecl object_instantiation(void)" (?object_instantiation##YAXXZ) E:\sv_repos\Test\Test\VS2010\Test\Test\Objects.obj Test
thanks in advance.
The error given most likely means the function referenced simply doesn't exist, in general or in the current compilation unit.
Check to make sure it has been defined in the class body (in the header in the templated case) or is being imported properly (if coming from an external source, such as DLL or library; a common issue but unlikely with templates), including the library being linked against.
The form of your extern global variable appears to be correct, and that does work with templates generally speaking. The error seems specific to your templated class, but there is not information on whether that function actually exists in your posted code.

template member functions in c++

I have a problem with generics in c++.I have two Matrix.h and Matrix.cpp files.Here is files:
#pragma once
template<class T>
class Matrix
{
public:
static T** addSub(int size,T** firstMatrix,T** secondMatrix,int operation);
}
and Matrix.cpp
#include "Martix.h"
template<class T>
static T** Matrix<T>::addSub( int n,T **firstMatrix,T **secondMatrix,int operation)
{
//variable for saving result operation
T **result = new T*[n];
//create result matrix
for( int i=0;i<n;i++)
result[i] = new T[n];
//calculate result
for( int i=0;i<n;i++)
for(int j=0;j<n;j++)
result[i][j] =
(operation == 1) ? firstMatrix[i][j] + secondMatrix[i][j]:
firstMatrix[i][j] - secondMatrix[i][j];
return result;
}
when I run these I get the below error:
Error 1 error LNK2019: unresolved external symbol "public: static int * * __cdecl Matrix<int>::addSub(int,int * *,int * *,int)" (?addSub#?$Matrix#H##SAPAPAHHPAPAH0H#Z) referenced in function "public: static int * * __cdecl Matrix<int>::strassenMultiply(int,int * *,int * *)" (?strassenMultiply#?$Matrix#H##SAPAPAHHPAPAH0#Z) C:\Users\ba.mehrabi\Desktop\Matrix\matrixMultiplication\main.obj matrixMultiplication
what is the problem?
Unfortunately, you can't have the declaration of a template class in the *.cpp files. The full definition has to stay in the header file. This is a rule of many C++ compilers.
See this: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
A template is not a class or a function. A template is a "pattern"
that the compiler uses to generate a family of classes or functions.
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. For example, if you're
trying to use a Foo, the compiler must see both the Foo template
and the fact that you're trying to make a specific Foo.
Your compiler probably doesn't remember the details of one .cpp
file while it is compiling another .cpp file. It could, but most do
not and if you are reading this FAQ, it almost definitely does not.
BTW this is called the "separate compilation model."
The link has a workaround, but keep in mind that a template is a glorified macro so the header file is probably the best place for it.
The poster of this SO post shows a demonstration of the workaround.
First of all, the definition of functions of a class template, should go in the header itself.
Second, if you define the static member function out of class (though in the header itself), then don't use the static keyword (in the definition). It only needed in the declaration only.
Add
template Matrix<int>;
at the end of your cpp file and it will work. But you need to learn a few things about templates, otherwise you'll have to deal with lots of issues you don't understand.

How to compile Templates located in different files in C++?

When I put all the source in one file, the program successfully builds. However when I split them into header files, I get a link error.
The main of my program:
//C++_Class_Templates.cpp
#include <iostream>
#include <vector>
#include "Queue.h"
using namespace std;
//Usage for C++ class templates
void main()
{
MyQueue<int> q;
q.Add(1);
q.Add(2);
}
The Queue.h looks like this
#pragma once
#include <vector>
template <typename T>
class MyQueue
{
std::vector<T> data;
public:
void Add(T const &);
void Remove();
void Print();
};
and the Queue.cpp looks like this:
#include "Queue.h"
template <typename T> void MyQueue<T> ::Add(T const &d)
{
data.push_back(d);
}
When I try to build it, I get this error:
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall
MyQueue<int>::Add(int const &)" (?Add#?$MyQueue#H##QAEXABH#Z) referenced in function _main
The short answer is: "you don't."
The longer answer is: well, it's basically the same as the short answer. For more information, see the C++ FAQ Lite entry "Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?" Except for certain limited-use scenarios (like when you have a small set of known arguments with which you will use the template and you can explicitly instantiate it with those types), the definition of the template must be available when you try to use it.
Separating declaration and definition for templates is not trivial.
The compiler must see the definition to be able to compile a specialization but it must also know the parameters to use. C++ was designed to be compiled one "compile unit" at a time and those two parts (the definition and the parameters) must be visible at the same time.
So either you put all a list of all specializations you will need in the implementation file of the template or you put the whole definition in the .h file. Both of those two solutions have however drawbacks.
See this answer to the same problem you are facing for a more complete explanation.