This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 1 year ago.
I have been writing this class for logging but I haven't been fixing this problem.
mylogger.cpp
#include "../inc/mylogger.h"
MyLogger::MyLogger()
{
cout << "hi" << endl;
}
template<typename... Args>
void MyLogger::function1(Args... args)
{
printf( args...);
}
MyLogger MYLOGGER = MyLogger();
mylogger.h
#ifndef MYLOGGER_H
#define MYLOGGER_H
#include <iostream>
#include <iostream>
#include <cstdarg>
#include <string>
#include <thread>
#define LOG_WRITE MYLOGGER.function1
using namespace std;
class MyLogger{
public:
MyLogger();
template<typename... Args> void deneme(Args... args);
};
extern MyLogger MYLOGGER;
#endif
main.cpp
#include <iostream>
#include "../inc/mylogger.h"
using namespace std;
int main(int argc, char** argv)
{
LOG_WRITE("hello", 3, 4, 1);
return 0;
}
I got this error.
undefined reference to `void MyLogger::function1<char, int, int, int>(char, int, int, int)'
I don't understand. How to fix it?
You have implementation of template in other file, the compiler cannot find it and create a specific implementation for certain type. You must create file "templates.cpp" and declare a specific template there. Like on this photo:
Or you can set all your implementation of your functions from mylogger.cpp in mylogger.h
Related
I am attempting to create a templated vector class, but upon compilation I am receiving an error of
def.hpp:3:1: error: 'TempVector' does not name a type
I keep referring to reference material and my syntax and handling of the header file declaration and definition (.h and .hpp) seem right to me, but I can not figure out what I am overlooking.
Below is the three files I am working with, thank you.
driver.cpp:
#include <iostream>
#include <string>
#include "dec.h"
using namespace std;
int main() {
TempVector <int> v1;
cout<<"ran successfully"<<endl;
}
dec.h:
#ifndef DEC_H
#define DEC_H
#include <iostream>
#include <utility>
// Declaration of class Vector
template <typename T>
class TempVector {
public:
TempVector ();
private:
T* array;
static const unsigned int spare = 10;
};
#include "def.hpp"
#endif
def.hpp:
template <typename T>
TempVector<T>::TempVector () {
std::cout<<"ran successfully";
}
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 2 years ago.
I'm trying to work with deque and template and I wanted to add others files (func.cpp and func.h) so I can declare all my function in these files and then include func.h in main.cpp but I got an some errors:
1. argument list for variable template "display" is missing in main.cpp
2.'deque': undeclared identifier in func.cpp
3.'d': undeclared identifier in func.cpp
here's the main.cpp:
#include <iostream>
#include <algorithm>
#include <deque>
#include "funcr.h"
using namespace std;
int main()
{
deque <int> d1{ 1,5,3,9 };
d1.push_front(2);
display(d1);
return 0;
}
and here's the func.cpp:
#include <iostream>
#include <deque>
template<typename T>
void display(deque<T> d)
{
for (auto e : d)
std::cout << e << std::endl;
}
and there is the func.h:
#pragma once
template<typename T>
void display(deque<T>d);
can someone help me please?
You must define display in func.h, because templated functions must be implemented in header files unless they are explicitly instantiated.
Also, you did not write using namespace std; in func.h (not that you should write it anywhere, especially headers). As a result, you need to write std::deque instead of merely deque.
So func.h should look like the following:
#include <iostream>
#include <deque>
template<typename T>
void display(const std::deque<T>& d)
{
for (auto e : d)
std::cout << e << std::endl;
}
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have a templated class named DataHandler
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <set>
#include "constants.h"
template <typename T>
using Car = std::pair< T, T>;
template <typename T>
using SparseMatrix = std::vector< Car<T> >;
template <class T>
class DataHandler
{
public:
// initializes a new DataHandler only if none has been created,
// otherwise return the living instance
static DataHandler<T>* getInstance()
{
if(!dataHandler)
dataHandler = new DataHandler();
return dataHandler;
}
void readFile();
SparseMatrix<T>* getSparseBlue(){ return &sparseBlue; }
SparseMatrix<T>* getSparseRed(){ return &sparseRed; }
virtual ~DataHandler();
private:
// static DataHandler to ensure only one instance can be created
static DataHandler<T> *dataHandler;
// private constructor to use DataHandler as a Singleton
DataHandler();
int numElem = 0;
int m_rows, m_cols = -1;
#endif // DATAHANDLER_H
The source file is:
#include "data_handler.h"
#include <fstream>
#include <algorithm>
#include <omp.h>
#include <chrono>
using namespace std;
using namespace constants;
// Global static pointer used to ensure a single instance of the class.
template<typename T>
DataHandler<T>* DataHandler<T>::dataHandler = NULL;
template<typename T>
DataHandler<T>::DataHandler()
{
//ctor
}
template<typename T>
DataHandler<T>::~DataHandler()
{
//dtor
}
template<typename T>
void DataHandler<T>::readFile()
{
// do some stuff
}
// Instantiation of relevant templates
template class DataHandler<unsigned char>;
template class DataHandler<unsigned short int>;
In the last two lines I instantiate the templates which I define in main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <algorithm>
#include "data_handler.h"
#include "dense_traffic_handler.h"
#include "sparse_traffic_handler.h"
#include "constants.h"
using namespace std;
// Check the number of rows/cols to choose between char or short int for the sparse case
bool matrixIsSmall()
{
return true;
}
void integerCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
}
void charCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
SparseTrafficHandler<T> sth;
set<unsigned short int> step = dh->getstep();
int currentStep = 0;
set<unsigned short int>::const_iterator stepToSave = step.begin();
}
int main(int argc, char *argv[])
{
if(matrixIsSmall())
charCase();
else
integerCase();
return 0;
}
Compiler gives me an error: undefined reference to DenseTrafficHandler::DenseTrafficHandler<unsigned short>(DataHandler<unsigned short>*)
DenseTrafficHandler header is like that:
#ifndef TRAFFICHANDLER_H
#define TRAFFICHANDLER_H
#include "constants.h"
#include "data_handler.h"
class DenseTrafficHandler
{
public:
template<typename T>
DenseTrafficHandler(DataHandler<T> *dh);
virtual ~DenseTrafficHandler();
private:
int m_cols, m_rows;
char* data;
char ** dense = NULL;
};
#endif // TRAFFICHANDLER_H
DenseTrafficHandler source is:
#include "dense_traffic_handler.h"
using namespace std;
using namespace constants;
template <typename T>
DenseTrafficHandler::DenseTrafficHandler(DataHandler<T> *datah)
{
DataHandler<T> *dh = datah;
dense = dh->getDense();
m_rows = dh->getm_rows();
m_cols = dh->getm_cols();
}
DenseTrafficHandler::~DenseTrafficHandler()
{
//dtor
}
So I have two questions:
Why do I receive this error and how can I manage it?
Is there a way in DataHandler source to not specify
template <typename T>
DataHandler<T>::functionName() for every function? (I mean something like using namespace Datahandler<T>)
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.
I have a header file, RandFunctions.hpp which contains a template function,
#ifndef _RANDFUNCTIONS_HPP_
#define _RANDFUNCTIONS_HPP_
#include <stdlib.h>
#include <time.h>
namespace surena
{
namespace common
{
template<typename RealT> inline
RealT
RealRandom()
{
return rand()/(RealT(RAND_MAX)+1);
}
};
};
#endif
and another header file, Search.hpp which includes RandFunctions.hpp,
#ifndef _SEARCH_HPP_
#define _SEARCH_HPP_
#include "RandFunctions.hpp"
#include <stdlib.h>
#include <time.h>
namespace surena
{
namespace search
{
template<typename RealT>
class CTest
{
public:
CTest() {srand((unsigned)(time(0)));}
RealT
GenRand(){ return common::RealRandom(); }
};
};
};
#endif
when I include Search.hpp in a cpp file, for example,
#include "Search.hpp"
int
main(int argc, char** argv)
{
CTest<float> test;
return(0);
}
I get the following compile time error:
‘RealRandom’ is not a member of ‘surena::common’
What is wrong here?
Since RealRandom is a template function with no parameters, you need to provide a template argument:
GenRand(){ return common::RealRandom<RealT>(); }
^^^^^^^
Also in your main you'd have to qualify your test variable with the proper namespaces:
surena::search::CTest<float> test;
^^^^^^^^^^^^^^^^
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
Undefined reference to function template when used with string (GCC)
C++ templates, undefined reference
I feel I'm missing something linking a C++ project.
I'm not sure if the problem is in the header sources or includes so I made a minimal code sample to demonstrate it.
Main module
minmain.cpp:
#include <stdio.h>
#include <vector>
#include <string>
#include "nodemin.h"
using namespace std;
int main()
{
// Blist libs are included
Node<int>* ndNew = ndNew->Root(2);
return 0;
}
Header file
nodemin.h:
#ifndef NODETEMP_H_
#define NODETEMP_H_
using namespace std;
template<class T>
class Node
{
protected:
Node* m_ndFather;
vector<Node*> m_vecSons;
T m_Content;
Node(Node* ndFather, T Content);
public:
// Creates a node to serve as a root
static Node<T>* Root(T RootTitle);
};
#endif
node module
nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
Compile line:
#g++ -Wall -g mainmin.cpp nodemin.cpp
Output:
/tmp/ccMI0eNd.o: In function `main':
/home/******/projects/.../src/Node/mainmin.cpp:11: undefined reference to`Node<int>::Root(int)'
collect2: error: ld returned 1 exit status
I tried compiling into objects but the linking still failed.
Add template class Node<int>; to nodemin.cpp:
#include <iostream>
#include <string.h>
#include <vector>
#include "nodemin.h"
using namespace std;
template <class T>
Node<T>::Node(Node* ndFather, T Content)
{
this->m_ndFather = ndFather;
this->m_Content = Content;
}
template <class T>
Node<T>* Node<T>::Root(T RootTitle) { return(new Node(0, RootTitle)); }
template class Node<int>;