unresolved external symbol - constructor - c++

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?

Related

Visual C++ 2015 linker error when forward declaring a struct as class

I have the following code (more than one file involved)...
//--- SomeInterface.h
struct SomeInterface
{
virtual void foo() = 0;
virtual ~SomeInterface(){}
};
//--- SomeInterfaceUser.h
#include <memory> //shared_ptr
class SomeInterface;
//NOTE: struct SomeInterface... causes linker error to go away...
class SomeInterfaceUser
{
public:
explicit SomeInterfaceUser(std::shared_ptr<SomeInterface> s);
};
//SomeInterfaceUser.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterface.h"
SomeInterfaceUser::SomeInterfaceUser(std::shared_ptr<SomeInterface> s)
{
}
//SomerInterfaceUserInstantiator.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterfaceImpl.h"
struct SomeInterfaceImpl : SomeInterface
{
virtual void foo(){}
};
void test()
{
SomeInterfaceUser x{std::make_shared<SomeInterfaceImpl>()};
}
Using the Visual C++ compiler, I get a linker error (LNK2019). Using GCC 4.8.4 this is not the case. Changing the forward declaration class SomeInterface to struct SomeInterface makes the linker error go away. I always thought that one should be able to use class/struct interchangeably? The interface of SomeInterfaceUser should not depend on whether SomeInterface is defined as class or struct, not so?
Is this a Visual C++ bug. I cannot find anything relating to it. I suspect the fact that the struct is used as template parameter has something to do with it.
Your help appreciated.
I've just been facing the same problem with both VC++ 2010 and VC++ 2017, and after some tests I've found that the problem resides in the symbol name the compiler gives to structs and classes internally.
Here a minimum example consisting in three files:
main.cpp
#include "bar.h"
struct Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
class Foo;
void bar(Foo* f);
bar.cpp
#include "bar.h"
void bar(Foo* foo) {}
When the project is compiled the following errors and warnings appear:
warning C4099: 'Foo': type name first seen using 'class' now seen using 'struct'
see declaration of 'Foo'
error LNK2019: unresolved external symbol "void __cdecl bar(struct Foo *)" (?bar##YAXPAUFoo###Z) referenced in function _main
fatal error LNK1120: 1 unresolved externals
Now, I swapped the struct and class declarations, so main.cpp and bar.h are now:
main.cpp
#include "bar.h"
class Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
struct Foo;
void bar(Foo* f);
As expected, the error still pops up:
error LNK2019: unresolved external symbol "void __cdecl bar(class Foo *)" (?bar##YAXPAVFoo###Z) referenced in function _main
BUT, and this is the interesting part, see that the symbols for the expected function (the one used in main()) in each case differ:
?bar##YAXPAUFoo###Z (when the parameter is a struct)
?bar##YAXPAVFoo###Z (when the parameter is a class)
Conclusion
The compiler gives slightly different names if the type is a struct or a class.
The linker then cannot find the proper definition because it is looking for a different one: bar.cpp defines one with the forward declaration, but for the moment it is called in main.cpp the actual declaration has taken placed, so a different function name is given in the symbols table.
Update (2023-02-03)
I've just seen that clang is able to report this issue:
error: 'Foo' defined as a struct here but previously declared as a class; this is valid, but may result in linker errors under the Microsoft C++ ABI [-Werror,-Wmismatched-tags]

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

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.

Is there a likely / common cause of a LNK2001 unresolved external symbol error when not using any outside libraries?

I am trying to create a new instance of a class, however I am receiving a LNK2001 unresolved external symbol error when I attempt to compile my code.
As far as I can tell I have written and included the class in exactly the same manner as I included another class, in both cases -
#include "class.h" // In main.cpp
class Class { // In class.h
private:
// etc.
public:
Class();
~Class();
// etc.
};
#include "class.h" // In class.cpp
Is there a common / likely cause of these errors, or a good way I might go about finding the source of the issue?
Edit: The error is
"Error 1 error LNK2019: unresolved external symbol "class Max
__cdecl max(void)" (?max##YA?AVMax##XZ) referenced in function _main main.obj Racing "
Edit: In both cases, a class is implemented across a .h and a .cpp file included in a project. The error is only appearing with one class.
Somewhere you have written this:
Max max();
What you intended was to declare a variable max of type Max.
C++ thinks you intend to declare a function max which returns an object of type Max. This is what it is looking for.
If you just say this:
Max max;
The issue will go away.
Edit: This only occurs with constructors which take no arguments. If the constructor takes arguments, C++ can see from the parameters (which will be rvalues, e.g. constants or expressions) that it is an instantiation of the class not a function declaration.
Max max(5); // Clearly cannot be a function, because 5 is an rvalue
Or
Max max(int); // Clearly cannot be an instantiation, because int is a type
But if the constructor takes no arguments, to distinguish between them, you have to drop the brackets if you are instantiating.

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.