Unresolved external symbol. Definition ok [duplicate] - c++

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 6 years ago.
I know this problem may occur when I declare function and not define it.
But this is not the case.
//In the 'H' file. Template class.
BSNode(T data);
\\In the cpp definitions
template <class T>
BSNode<T>::BSNode(T data)
{
_root = this;
_data = data;
_right = NULL;
_left = NULL;
}
And still, I get the next Error:
Error 1 error LNK2019: unresolved external symbol "public: __thiscall BSNode<int>::BSNode<int>(int)" (??0?$BSNode#H##QAE#H#Z) referenced in function _main c:\Users\a\OneDrive\ss\visual studio 2013\Projects\Project5\2\Source.obj 2_TREES
What also may cause this Error to occur if its not the incompatibility between the 'H' and the 'cpp' files?

The code that uses this constructor with the int instantiation should also be in the .cpp file. The compiler needs it to generate the instance of the code, because it cannot generate all possible instances.
Several solutions:
move at least one use of the constructor with the int instance in the cpp file
rename the .cpp file into a .template file that you can include in every file that uses the BSNode instances.
add template class BSNode<int>; in the .cpp file to force the template instantiation.

Related

Is it possible inherit from Template class C++ specialized on himself [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
Let's say we have base class Table
template <typename T>
class Table
{
public:
Table();
virtual ~Table() = default;
private:
// get all column names as list
virtual std::list<std::string> getAllColumnsImpl();
};
and I want inherit TestTable class and override method getAllColumnsImpl from base class:
class TestTable :
public Table<TestTable>
{
public:
TestTable();
virtual ~TestTable() = default;
std::string Description;
int Count;
private:
// get all column names as list
std::list<std::string> getAllColumnsImpl() override;
};
Is it possible in general ?
For example I have linker errors like:
error LNK2019: unresolved external symbol "public: __cdecl Table<class TestTable>::Table<class TestTable>(void)" (??0?$Table#VTestTable####QEAA#XZ) referenced in function "public: __cdecl TestTable::TestTable(void)" (??0TestTable##QEAA#XZ)
You can do it, it's called CRTP - the Curiously Recurring Template Parameter. It's very handy and there are many blogs and resources explaining uses for it.
The error you're getting is because you need to have the template's function bodies in the template's header file.
Each cpp file is compiled to a separate object file, and templates are resolved on a per-cpp file basis. When you put template code in a cpp file, then it's just "template < T >" and the compiler doesn't know what T is, so no code is generated (unless it's requested from the same cpp file, with an actual type and not T).
However, your other cpp file knows that it wants a "template < TestTable >", but it doesn't have access to the code that would make that work, because that's stuck in the other cpp file, which only knows the generic "template < T >". Neither cpp file is able to generate the missing code, so you get the linker error. Putting all the template code together in the header file removes the issue.

C++ linkage error for inline member function [duplicate]

This question already has answers here:
Why are C++ inline functions in the header?
(8 answers)
Closed 9 years ago.
I have the following code:
IFile.h
class IFile
{
public:
IFile();
~IFile(void);
inline bool IsValidFileType() const;
};
IFile.cpp
IFile::IFile()
{
//IsValidFileType();
}
IFile::~IFile(void)
{
}
inline bool IFile::IsValidFileType() const
{
return true;
}
main.cpp
int main(int argc, char* argv[])
{
IFile* pFile = new IFile();
pFile->IsValidFileType();
return 0;
}
When compiling the code I get the following error:
error LNK2019: unresolved external symbol "public: bool __thiscall IFile::IsValidFileType(void)const " (?IsValidFileType#IFile##QBE_NXZ) referenced in function _main
If I change wither "inline" or "const" qualiferes for the function, or call it inside the constructor, the program will complile.
Can you please explain this behaviour?
How can the compiler inline a function whose code it cannot see while it is compiling? When compiling main.cpp, the compiler is being asked to do just this.
An inline function's code gets compiled into each translation unit that references it (that's the idea, after all). Meaning, you need to include the code in the header file.
The inline keyword promises to the compiler that it will be able to see the definition in each translation unit (*.cpp file) in which it is used. You break this promise, since main.cpp can't see the definition although it includes IFile.h.
Usually functions with the inline keyword should be defined in a header file, not a source file.
Since the function is inline, you have to define it in the header file, not in the cpp file.

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.

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.