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.
Related
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.
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?
This question already has answers here:
Explicit specialization of function templates causes linker error
(2 answers)
Closed 8 years ago.
Having recently discovered templates, I've been trying to get a good grasp on them and came across a usage for them that I'd really like to implement; but having tried multiple things, I keep getting errors.
I'm trying to create a function that can take multiple types of parameters at once in any order.
(I'm using VS 2013.)
What I have right now is an "already defined" error (only when including tem.h in more than one file):
the exact first error (the rest are basically the same just for each test.. overload?):
Error 1 error LNK2005: "void __cdecl test<struct A>(struct A *)" (??$test#UA##$$$V##YAXPAUA###Z) already defined in main.obj c:\Users\User\documents\visual studio 2013\Projects\TemplateTest\TemplateTest\foo.obj TemplateTest
foo is just a .cpp file containing only: #include "tem.h"
tem.h:
#ifndef TEM_H
#define TEM_H
struct A {};
struct B {};
#include <iostream>
template<typename First, typename... Rest>
void test(First *t, Rest&&... args){
test(t);
test(std::forward<Rest>(args)...);
}
template<>
void test<A>(A *val){
std::cout << "Handled A" << std::endl;
}
template<>
void test<B>(B *val){
std::cout << "Handled B" << std::endl;
}
#endif
main.cpp:
#include <iostream>
#include "tem.h"
int main(int argc, char *argv[]){
std::cout << "running test..." << std::endl;
A a;
B b;
test(&a, &b);
return 0;
}
What am I missing that is causing this error?
Edit:
Making each instance of test inline prevents the error, but I don't think that's really the best solution
Function template specializations are not themselves templates, they are normal functions with fancy syntax. Like any other normal function, they should not be defined in header files unless you use the inline keyword.
Either add inline to both specializations, or leave just their declarations in the header and move the definitions to some .cpp file.
The main template definition is OK and should be left in the header intact.
A general advice though is to avoid function template specializations. You can use normal non-template overloads:
void test (A*);
void test (B*);
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.
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.