This question already has answers here:
CUDA linker error with template class
(1 answer)
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
My goal is to make a generic Cuda Kernel. My first step is trying to use templates in the function cudaMain (not yet in the Kernel - this will be my second step). cudaMain is called from my c++ main() file. From cudaMain the Kernel is called. This works fine, so long as I don't use templates. As soon as I add the templates to the class and cudaMainI get this error:
undefined reference to 'Cuda_class<int>::cudaMain(int, int, int*, int*, int*, int*, int*)'
Here's the code:
main.cpp:
#include "cuda_class.hpp"
Cuda_class<int> p;
p.cudaMain(trees.size(), trees[0].size(), treeArray_x, treeArray_y, treeArray_z, treeArray_ID, box);
cuda_class.hpp:
template <class T>
class Cuda_class{
public:
void cudaMain(int number_of_trees, int tree_size, T treeArray_x[], T treeArray_y[], T treeArray_z[], int treeArray_ID[], T box[]);
};
cuda_class.cu:
#include "cuda_class.hpp"
__global__
void insideBox(int *treeArray_x, int *treeArray_y, int *treeArray_z, int *treeArray_ID, int *box, int tree_size){
//for each thread has it's own tree starting here
int startOfTree = threadIdx.x * tree_size ;
int endOfTree = startOfTree + tree_size - 1;
traverseTree(treeArray_x, treeArray_y, treeArray_z, treeArray_ID, box, 1, startOfTree, endOfTree);
}
template <class T>
void Cuda_class<T>::cudaMain(int number_of_trees, int tree_size, T treeArray_x[], T treeArray_y[], T treeArray_z[], int treeArray_ID[], T box[]){
cudaSetDevice(MYDEVICE);
// do something allocate memory etc
//launch kernel
insideBox<<<1,32>>>(d_treeArray_x, d_treeArray_y, d_treeArray_z, d_treeArray_ID, d_box, tree_size);
//do some other stuff
}
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 2 years ago.
I'm making a prime generator with 3 file (two of them are .cpp and one is .h).
However when i try to build the whole project it in onlinegdb gives this error
/tmp/ccI5GCGK.o: In function `main':
main.cpp:(.text+0x11f): undefined reference to `int primegen(int&, long*, long*)'
collect2: error: ld returned 1 exit status
main.cpp
#include <iostream>
#include "primegen.h"
int main(void)
{
//taking input for number of test cases
int test_case{2};
long int lower_lim[MAX] = {5, 15}, upper_lim[MAX] = {15, 25};
//function present in primefunc.cpp
primegen(test_case,lower_lim,upper_lim);
}
primefunc.cpp
// to make SUCCESS known to this file
extern int SUCCESS;
//main function to prime generator between limits
int primegen(int &test, auto *low, auto *up)
{
static int cases=0;
if(cases == test)
return SUCCESS;
int diff=up[cases]-low[cases];
for(int i=0;i<diff;i++)
{
//some code to be added
}
}
primegen.h
// for making arrays of lower and upper limit
constexpr int MAX = 10;
constexpr int SUCCESS = 2;
// for printing out prime number
int primegen(int &, auto *, auto *);
EDIT :- I tried moving the function from the 2nd cpp to the main.cpp and it worked and also individual builds also gives success.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 6 years ago.
I'm trying to learn how to use templated classes. I've created a simple templated class numbers that holds 2 numbers that can be any data type. Then I made a method that returns the bigger number of the two in the object. For some reason I keep getting linker errors though... Here's the errors and code. Not sure what's wrong, Visual Studio didn't underline anything in my code.
They say "unresolved external symbol" if it's too small to read.
templated.h
template <class T>
class numbers {
public:
numbers(T x, T y);
T bigger();
private:
T a, b;
};
templated.cpp
#include "templated.h"
#include <iostream>
using namespace std;
template <class T>
numbers<T>::numbers(T x, T y) {
a = x;
b = y;
}
template <class T>
T numbers<T>::bigger() {
return a > b ? a : b;
}
main.cpp
#include <iostream>
#include "templated.h"
using namespace std;
int main() {
numbers <int>pair(1, 2);
cout << pair.bigger() << endl;
return 0;
}
Thanks for reading!
You're not supposed to put template implementations in a cpp/c file. Move them all to your .h file.
This is because cpp files are supposed to take functions that compile into implementation libraries (like dll files or compiled objects), while template functions have undefined types (yet), whose types get defined at compile time.
You can, however, put specializations of your template functions in the cpp file, where you specify what types you want to include in your compiled objects.
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 static array inside a class template. The linker complains about a undefined symbol and even after applying the tips I saw on the web, I can't figure out what goes wrong.
Header
template<unsigned int N1, unsigned int N2>
class Foo
{
private:
static const int Size = N1 * N2;
public:
// stuff
private:
static float mArray[Size];
}
CPP
template <unsigned int N1, unsigned int N2>
float Foo<N1, N2>::mArray[size] = {0};
The linker complains about Foo<...>::mArray not being defined. I got it to compile (and link) when I move the definition to the header but I know that this is bad practice for statics. What is the best approach here?
Cheers
As with nearly everything else template-y, the definition of the static data member of a class template needs to be accessible in all translation units using it—in other words, put it in the header file. The compiler+linker are required to make this work without multiple-definition errors.
This question already has answers here:
Defining static const integer members in class definition
(7 answers)
Closed 8 years ago.
I have the following classes:
MessageConstants.h:
class MessageConstants
{
public:
...
static const int ErrorDescriptionLength = 256;
...
};
SystemMessage.h:
class EvtError
{
private:
struct MsgData
{
int errorCode;
char errorDescription[MessageConstants::ErrorDescriptionLength];
}__attribute__((packed)) msgData;
public:
EvtError(int errorCode, string errorDescription);
inline void setErrorDescription(string desc){memcpy(msgData.errorDescription, desc.c_str(),
min(MessageConstants::ErrorDescriptionLength, (int)desc.length()));}
};
SystemMessage.cpp:
EvtError::EvtError(int errorCode, string errorDesc)
{
memset(&msgData, '\0', sizeof(msgData));
msgData.errorCode = errorCode;
memcpy(msgData.errorDescription, errorDesc.c_str(), min(MessageConstants::ErrorDescriptionLength, (int)errorDesc.length()));
}
I got the following link error on SystemMessage.cpp statement memcpy(msgData.errorDescription, errorDesc.c_str(), min(MessageConstants::ErrorDescriptionLength, (int)errorDesc.length())); :
In function EvtError::EvtError(int, std::string):
undefined reference to MessageConstants::ErrorDescriptionLength
collect2: error: ld returned 1 exit status
make: [link] Error 1
If I replace the MessageConstants::ErrorDescriptionLength with sizeof(msgData.errorDescription), the link error disappear.
My questions:
Why it doesn't complain the MessageConstants::ErrorDescriptionLength in the SystemMessage.h file, where there are two places with it?
How to avoid above link error?
The signature of min is:
template <typename T>
const T& min(const T&, const T&);
It takes its inputs by reference - which requires them to have storage. Your constant:
static const int ErrorDescriptionLength = 256;
Does not currently have storage. There are two ways to approach this. First, you can just add storage in your .cpp:
const int MessageConstants::ErrorDescriptionLength;
Second, you can just cast it to an int:
min((int)MessageConstants::ErrorDescriptionLength, (int)errorDesc.length())
// ^^^^^
Static variable must have a definition outside the class:
const int MessageConstants::ErrorDescriptionLength ;
This should go in exactly one .cpp. file in your project.
Sometimes you can get away without it, but in those cases it is either because the variable was not odr-used, or the program was ill-formed (but ODR violations don't require diagnosis).
This question already has answers here:
get function member address
(2 answers)
Closed 8 years ago.
I am trying to use function pointer in a c++ class but got an error.
#include <cstdio>
#include <iostream>
using namespace std;
class abc{
public:
void hello(){
printf("Hello world\n");
}
abc(){
void (*hw)(void);
hw = &hello;
hw();
}
}
int main()
{
abc ab;
return 0;
}
Error
error: cannot convert ‘void (abc::*)()’ to ‘void (*)()’ in assignment
But the following code works for me which is in code base. Can anyone please help me to find out the difference?
void hello(){
printf("Hello world\n");
}
int main()
{
void (*hw)(void);
hw = &hello;
hw();
return 0;
}
Function pointers are (unfortunately) completely different from method pointers, as the error is trying to indicate. This is because the object that the method works on needs to be passed in somehow, which is what makes methods fundamentally different from functions in the first place (and obviously affects how the call is done through the pointer). Method pointers are not even always the same size (and can be significantly larger than a function pointer) when multiple/virtual inheritance comes into play.
You need to declare a method pointer, and call it on behalf of an object of the right type using one of the esoteric .* or ->* operators:
class abc {
public:
void hello(){
printf("Hello world\n");
}
abc() {
void (abc::*hw)();
hw = &abc::hello;
(this->*hw)(); // or (*this.*hw)()
}
}