I have a simple function setup to check if a value is in a std::vector, and I would like to use a 'Template' to beable to use the function with all classes.
Some definitions
std::vector<ItemID_t> *spareItems;
ItemID_t newItem;//note this is an enumeration value
The function works perfectly if I call with
bool b = !vectorContains(*spareItems,newItem);
and the function looks like
bool vectorContains(std::vector<ItemID_t> &vector,const ItemID_t& value){
return std::find(vector.begin(), vector.end(), value)!=vector.end();
}
but if I try to implement generics with the call
bool b = !vectorContains<ItemID_t>(*spareItems,newItem);
and the function definition
template <class T>
bool vectorContains(std::vector<T> &vector,const T& value){
return std::find(vector.begin(), vector.end(), value)!=vector.end();
}
It fails in the second example and gives me this linker error
error LNK2019: unresolved external symbol "bool __cdecl turtle::vectorContains<enum turtle::ItemID_t>(class std::vector<enum turtle::ItemID_t,class std::allocator<enum turtle::ItemID_t> > &,enum turtle::ItemID_t const &)" (??$vectorContains#W4ItemID_t#turtle###turtle##YA_NAAV?$vector#W4ItemID_t#turtle##V?$allocator#W4ItemID_t#turtle###std###std##ABW4ItemID_t#0##Z) referenced in function "public: void __thiscall turtle::Barracks::swapItems(int,enum turtle::ItemID_t)" (?swapItems#Barracks#turtle##QAEXHW4ItemID_t#2##Z)
Thank you
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
i'm just writing an array class as practice in Microsoft Visual Studio 2010 but i'm getting some annoying errors. here they are:
1>test.obj : error LNK2019: unresolved external symbol "public: __thiscall arrays<int>::~arrays<int>(void)" (??1?$arrays#H##QAE#XZ) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: int & __thiscall arrays<int>::operator[](int)" (??A?$arrays#H##QAEAAHH#Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: bool __thiscall arrays<int>::operator==(class arrays<int> const &)const " (??8?$arrays#H##QBE_NABV0##Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: int const & __thiscall arrays<int>::operator=(class arrays<int> const &)" (??4?$arrays#H##QAEABHABV0##Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: __thiscall arrays<int>::arrays<int>(class arrays<int> const &)" (??0?$arrays#H##QAE#ABV0##Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class arrays<int> const &)" (??5#YAAAV?$basic_istream#DU?$char_traits#D#std###std##AAV01#ABV?$arrays#H###Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class arrays<int> const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$arrays#H###Z) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: int __thiscall arrays<int>::getsize(void)const " (?getsize#?$arrays#H##QBEHXZ) referenced in function _wmain
1>test.obj : error LNK2019: unresolved external symbol "public: __thiscall arrays<int>::arrays<int>(int)" (??0?$arrays#H##QAE#H#Z) referenced in function _wmain
1>c:\users\bm\documents\visual studio 2010\Projects\arrays\Debug\arrays.exe : fatal error LNK1120: 9 unresolved externals
how can I fix them?
here is my code:
arrays.h
#ifndef ARRAYS_H
#define ARRAYS_H
#include <iostream>
using namespace std;
template <typename T>
class arrays{
friend ostream &operator<<(ostream &output, const arrays &a);
friend istream &operator>>(istream &input, const arrays &a);
public:
arrays(int = 10);
arrays(const arrays &);
~arrays();
int getsize() const;
const T &operator=(const arrays &);
bool operator==(const arrays &) const;
bool operator!=(const arrays &right) const{
return !((*this)==right);
}
T &operator[](int);
T operator[](int) const;
private:
int size;
T *ptr;
};
#endif
arrays.cpp
#include "stdafx.h"
#include <iostream>
#include "arrays.h"
#include <cstdlib>
using namespace std;
template <typename T>
arrays<T>::arrays(int mysize){
size = mysize;
ptr = new(int[size]);
for(int i = 0; i< size; i++)
ptr[i] = 0;
}
template <typename T>
arrays<T>::arrays(const arrays<T> &myarray){
size = myarray.size;
ptr = new(int[size]);
for(int i = 0; i< size; i++){
ptr[i] = myarray.ptr[i];
}
}
template <typename T>
arrays<T>::~arrays(){
delete [] ptr;
}
template <typename T>
int arrays<T>::getsize() const {
return size;
}
template <typename T>
const T &arrays<T>::operator=(const arrays<T> &right){
if ( &right != this){
if(size != right.size){
delete [] ptr;
size= right.size;
ptr = new(int[size]);
}
for(int i =0; i < size; i++)
ptr[i] = right.ptr[i];
}
return *this;
}
template <typename T>
bool arrays<T>::operator==(const arrays<T> &right) const{
if(right.size != size)
return false;
for(int i = 0; i<size; i++)
if(ptr[i] != right.ptr[i])
return false;
return true;
}
template <typename T>
T &arrays<T>::operator[](int subscript) {
if(subscript < 0 || subscript >= size){
cout << "error: subscript out of range";
}
return ptr[subscript];
}
template <typename T>
T arrays<T>::operator[](int subscript) const {
if(subscript < 0 || subscript >= size){
cout << "error: subscript out of range";
exit(1);
}
return ptr[subscript];
}
template <typename T>
istream &operator>>(istream &input, const arrays<T> &a){
for(int i = 0; i< a.size; i++)
input >> a.ptr[i];
return input;
}
template <typename T>
ostream &operator<<(ostream &output, arrays<T> &a){
for(int i= 0; i<a.size;i++)
output << a.ptr[i];
return output;
}
any help would be appreciated.
Implementation code for a template class must live in the header, not in the .cpp file. This is required so that other code that use your template class can "instanciate" it's code based on the template parameter.
So just move all your code from your .cpp to your .h and you're good to go.
I have defined a method with an optional/defaulted last argument called noAutoResolve as follows:
typedef std::shared_ptr<IMessage> TMessagePtr;
class NetworkService : public IConnectionManagerDelegate, public net::IStreamDelegate
{
public:
void send_message(std::string identity, msg::TMessagePtr msg, QObject* window, std::function<void(int, std::shared_ptr<msg::IMessage> msg)> fn, bool noAutoResolve = false);
}
and later:
void NetworkService::send_message(std::string endpoint, msg::TMessagePtr msg, QObject* window, std::function<void(int res, std::shared_ptr<msg::IMessage> msg)> fn, bool noAutoResolve)
{
}
The linker is now unhappy about unresolved externals in the following line where I intentionally omitted the last argument:
service_->send_message(endpoint_, msg, this, [this](int result, msg::TMessagePtr msg){
// .....
});
Is that not possible in c++?
Error LNK1120 1 unresolved externals QTServer QTServer.exe 1
Error LNK2019 unresolved external symbol "public: void __thiscall NetworkService::send_message(class std::basic_string,class std::allocator >,class std::shared_ptr,class QObject *,class std::function)>)" (?send_message#NetworkService##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$shared_ptr#UIMessage#msg###3#PAVQObject##V?$function#$$A6AXHV?$shared_ptr#UIMessage#msg###std###Z#3##Z) referenced in function "public: void __thiscall QTWindow::ExecuteCommand(void)" (?ExecuteCommand#QTWindow##QAEXXZ) QTServer QTWindow.obj 1
The fn parameter of your function is type of std::function<void(int, std::shared_ptr<msg::IMessage> msg)>. However, the lambda you are passing is:
[this](int result, msg::TMessagePtr msg){
// .....
}
This function has the signature of void(int, msg::TMessagePtr), so if there is no conversion from std::shared_ptr<msg::IMessage> to msg::TMessagePtr, the code cannot compile.
Your problem is therefore not about the optional parameter. For a quick fix, if you have access to a C++14 compiler, try getting the lambda parameters as auto:
[this](auto result, auto msg){
// .....
}
See code below. There's something wrong with it, because the linker is complaining it can't find the Memory's functions, but I can't figure out why.
memory.h
#pragma once
#include "includes.h" //it just includes other strandard headers.
class MemoryUnit
{
public:
MemoryUnit() {}
virtual int getValue() = 0;
virtual int getSize() = 0;
virtual void setValue(int) = 0;
virtual ~MemoryUnit() {};
};
class Byte : public MemoryUnit
{
int value;
public:
static int size;
Byte(int byte) :value(byte) {};
int getSize() { return size; }
int getValue() { return value; };
void setValue(int byte) { value = byte; }
~Byte() {};
};
namespace Memory
{
extern int size;
extern MemoryUnit** map;
void checkAddress(int address);
int read(int adress);
MemoryUnit* getOperation(int address);
void write(int adress, MemoryUnit* data);
void writeByte(int adress, int data);
}
memory.cpp
#include "includes.h"
#include "memory.h"
#include "simulator.h" // it contains only externed constants.
namespace Memory
{
int size = 0;
MemoryUnit** map = NULL;
inline MemoryUnit* getOperation(int address)
{
return map[address];
}
inline void checkAddress(int address)
{
if (address < 0 || address >= MAX_MEMORY_SIZE)
throw std::out_of_range("Invalid memory address.");
}
inline int read(int address)
{
checkAddress(address);
return map[address]->getValue();
}
inline void write(int address, MemoryUnit* data)
{
checkAddress(address);
delete map[address];
map[address] = data;
}
inline void writeByte(int address, int data)
{
checkAddress(address);
map[address]->setValue(data);
}
}
Everywhere the class/namespace memory.h declares is includes memory.h. Is here anything wrong in the code below?
Edit:
I'm using Visual Studio 2015.
Errors I got when building the project:
LNK1120 5 unresolved externals simulator.exe
LNK2019 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" referenced in function "void __cdecl ALU::setFlags(int)" alu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" cu.obj
LNK2019 unresolved external symbol "class MemoryUnit * __cdecl Memory::getOperation(int)" referenced in function "void __cdecl CU::run(void)" cu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" helpers.obj
LNK2019 unresolved external symbol "void __cdecl Memory::write(int,class MemoryUnit *)" referenced in function "void __cdecl readProgramCommands(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall MemoryPointer::getValue(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall IndirectMemoryPointer::getAddress(void)" helpers.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" main.obj
alu.h and alu.cpp for the first error:
//alu.h
#pragma once
#include "includes.h"
#include "operation.h"
namespace ALU
{
int operation(Operation* op);
void setFlags(int result);
}
//alu.cpp
#include "includes.h"
#include "simulator.h"
#include "alu.h"
#include "memory.h"
#include "operation.h"
namespace ALU
{
int operation(Operation* operation)
{
// ...
setFlags(result);
return result;
}
inline void setFlags(int result)
{
Memory::writeByte(FLAG_Z, result == 0);
// ...
}
}
You need to put the inline function definition inside your header file (they both must appear in every translation unit where they are used), you can separate declaration and definition but both must be in the header file. Also they must be declared as inline.
N4140 dcl.fct.spec 7.1.2.4
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly
the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its
definition appears in the translation unit. —end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is ill-formed.
When you're using inline functions or methods, their definitions should be visible for every source unit that uses them. You defined your inline functions in Memory.cpp, that's why you get 'unresolved' linker error.
To fix your problem you can:
Remove inline modifier and keep functions definitions in Memory.cpp.
Keep inline modifier but move functions definitions to Memory.h.
I have a Thread pool of the type that can be found here.
I try doing the following:
/* Allocate a ThreadPool */
shared_ptr<SpinTools::ThreadPool> pool(new SpinTools::ThreadPool(4));
/* Start processing each image in Core container */
for (int img_idx = 0; img_idx < num_images; img_idx++) {
pool->enqueue(_worker_task, img_idx, _args, _stats);
}
My worker task has the following prototype:
void _worker_task(int img_idx, ProcessorArgs &args, Stats &stats)
however this won't compile and MSVC displays the error
Error 14 error LNK2019: unresolved external symbol "public: class std::future<void> __cdecl ThreadPool::enqueue<void (__cdecl&)(int,struct ProcessorArgs,struct SpinCore::Features::Stats &),int &,struct Sift::ProcessorArgs &,struct SpinCore::Features::Stats &>(void (__cdecl&)(int,struct ProcessorArgs,struct SpinCore::Features::Stats &),int &,struct ProcessorArgs &,struct SpinCore::Features::Stats &)" (??$enqueue#A6AXHUProcessorArgs#Sift##AEAUStats#Features#SpinCore###ZAEAHAEAU12#AEAU345##ThreadPool#SpinTools##QEAA?AV?$future#X#std##A6AXHUProcessorArgs#Sift##AEAUStats#Features#SpinCore###ZAEAHAEAU45#1#Z) referenced in function "public: virtual void __cdecl Sift::process(void)" (?process#Sift##UEAAXXZ)
Edit: adding the header for ThreadPool::enqueue for completness:
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
You need to place the implementation of ThreadPool::enqueue in the header. MSVC can't generate the implementation if it's in .cpp file only (or at least earlier versions could not)
PacketBuilder is a little Class which allow to write into a char* array. The Append Functions:
template <class T>
void PacketBuilder::Append(const T value)
{
memcpy((&m_Buffer) + m_Index, (const void*) &value, sizeof(T));
m_Index += sizeof(T);
}
Compiling without errors. If I call Append and use T as unsigned short (WORD). It works great. If I use T as unsigned char. I get an Linker Error.
m_Builder.Append<unsigned char>(0x01); // Error: LNK1120
m_Builder.Append<unsigned short>(0x0001); // Works
Error from VS2010 (sry i got german vs2010):
error LNK2019: Verweis auf nicht
aufgelöstes externes Symbol ""public:
void __thiscall
PacketBuilder::Append(unsigned char)"
(??$Append#E#PacketBuilder##QAEXE#Z)"
in Funktion ""public: void __thiscall
Client::DoHandshake(void)"
(?DoHandshake#Client##QAEXXZ)".
1>C:\XXX\C++\SilkroadEmu\Debug\LoginServer.exe
: fatal error LNK1120: 1 nicht
aufgelöste externe Verweise.
Translated to English:
error LNK2019: Unresolved external
symbol ""public: void __thiscall
PacketBuilder::Append(unsigned char)"
(??$Append#E#PacketBuilder##QAEXE#Z)"
in Function ""public: void __thiscall
Client::DoHandshake(void)"
(?DoHandshake#Client##QAEXXZ)".
1>C:\XXX\C++\SilkroadEmu\Debug\LoginServer.exe
: fatal error LNK1120: 1 unsresolved
external symbol.
Put the method definition in the header (hpp file), not in the implementation (cpp) file.
Your PacketBuilder is not a class template, as far as I can see. PacketBuilder::Append is however a template method, which requires that it's definition must be visible at any point of instantiation of this method. The only really safe way to assure this is to put the complete definition of this method template into the header file:
class PacketBuilder {
// declarations of non-template members
public:
template <class T>
void Append(const T value)
{
memcpy((&m_Buffer) + m_Index, (const void*) &value, sizeof(T));
m_Index += sizeof(T);
}
};