This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Static member initialization in a class template
(3 answers)
Closed 4 years ago.
Let's say for some reason, I want to have a class template MyTemp with some static data member smDummyVar :
Mytemp.h
#ifndef MY_TEMP_H
#define MY_TEMP_H
template<class T>
class MyTemp{
...
private:
static int smDummyVar;
...
};
#include "MyTemp.cpp"
#endif //MY_TEMP_H
Mytemp.cpp
...
template<class T> int MyTemp<T>::smDummyVar = 0;
...
Since the compiler requires that the definition and declaration of a template be at the same place, so I include MyTemp.cpp in MyTemp.h .
Now: I want to use MyTemp at many places and create objects using the template:
case1.cpp
#include "MyTemp.h"
void dummyfunc1(){
MyTemp<int> myTemp1;
}
case2.cpp
#include "MyTemp.h"
void dummyfunc2(){
MyTemp<int> myTemp2;
}
I won't get any error from the compiler, but I'd get warning from the linker:
"multiple definition for MyTemp<int>::smDummyVar" ... defined in invalid_group(case1.o) ... rejected in favour of symbol defined in ...(case2.o)
Question: how can I get rid of this warning ?
Thanks a lot in advance for your help !
====================================
inspired by one of the answers in this thread Why can templates only be implemented in the header file?
I found the following solution:
i. remove #include "MyTemp.cpp" in MyTemp.h
ii. specialized.h
#include "MyTemp.h"
typedef MyTemp<int> MySpecialized;
iii. specialized.cpp
#include "MyTemp.cpp"
template class MyTemp<int>;
iv. give specialized.cpp to cmake file
v. include specilized.h in case1.cpp and case2.cpp
the "multiple definition" warning issued by the linker will go away.
Thank you guys for helping !
Related
This question already has answers here:
Separating class code into a header and cpp file
(8 answers)
Closed 5 months ago.
I don't know how to add functions of a class outside its scope to it, use them in another class and then compile it.
MyMain.cpp
#include"MyClass.cpp"
int main(){
MyClass myClass;
myClass.run();
}
MyClass.cpp
#ifndef MYCLASS_CPP
#define MYCLASS_CPP
#include<iostream>
class MyClass {
private:
void usage();
public:
void run();
};
void MyClass::usage(){
std::cout << "usage called" << std::endl;
}
void MyClass::run(){
usage();
}
#endif
I try to compile it with:
g++ MyMain.cpp MyClass.cpp -o main
With that I get the following error message:
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::usage()':
MyClass.cpp:(.text+0x0): multiple definition of `MyClass::usage()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x0): first defined here
/usr/bin/ld: /tmp/ccN7GfOD.o: in function `MyClass::run()':
MyClass.cpp:(.text+0x38): multiple definition of `MyClass::run()'; /tmp/ccLhxS6v.o:MyMain.cpp:(.text+0x38): first defined here
collect2: error: ld returned 1 exit status
If I have understood the concept correctly, the function headers within the class serve only as placeholders. The actual functionality is then "overwritten" by the external functions, which also contain a body.
And why does the error message say, that the function is already defined in the MyMain.cpp?
I have also seen that there are many similar questions here, but unfortunately I could not expand my understanding of the basic problem to solve it.
Is it possible that I am using the command to build the class with C++ incorrectly or that I can save the #include "MyClass.cpp"?
Kind regards
Several things wrong. here's the steps to put it right
Rename MyClass.cpp to MyClass.h.
Create a new empty file MyClass.cpp
Move the function definitions MyClass::usage() { .. } and MyClass::run() { .. } from MyClass.h to MyClass.cpp. You should probably also move #include <iostream> but this is not essential.
Add #include "MyClass.h" to MyClass.cpp
Change #include "MyClass.cpp" to #include "MyClass.h" in MyMain.cpp
Then build as you are doing now. That part is correct.
Essentially the technique is to separate your code into declarations and definitions. The declarations go into header files, which are included in the cpp files. The cpp files contain the definitions and are what you compile.
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:
Multiple definition of ... linker error
(3 answers)
Closed 6 years ago.
I am starting to use CUDA and thrust for a project of mine, so I am still new to some of it aspects. I ran into the following problem.
I have to separate .cu files which I want to use with a common header file which has a struct that both of them shall be able to use. It is something like this:
////////Global.h
#ifndef global_h
#define global_h
struct globalParam
{
uint64_t spaceToUse;
globalParams() : spaceToUse(1024*1024*1024) {}
};
globalParam glParam;
#endif
The First .cu file looks like this:
////////firstcufile.cu
#ifndef firstcufile_cu
#define firstcufile_cu
#include "Global.h"
template<typename T>
QVector<T> GPUcalculateNormSq(const QVector<T>& real, const QVector<T>& imag)
{
QVector<T> result (real.size());
uint64_t maxSpace = glParam.spaceToUse;
//Some Code to use thrust and using tops maxSpace bytes.
return result;
}
template QVector<float> GPUcalculateNormSq(const QVector<float>& real, const QVector<float>& imag);
template QVector<double> GPUcalculateNormSq(const QVector<double>& real, const QVector<double>& imag);
#endif
The second .cu file looks like this:
////////secondcufile.cu
#ifndef secondcufile_cu
#define secondcufile_cu
#include "Global.h"
template<typename T>
double getMean(const T& vec)
{
uint64_t spaceNeededOnGPU = vec.size() * sizeof (T);
uint64_t maxSpace = glParam.spaceToUse;
//Some code to make sure tops maxSpace bytes on GPU
double sum = thrust::reduce(std::begin(vec), std::end(vec));
return sum / vec.size();
}
template double getMean(const QVector<float>& vec);
#endif
Now the error I get is:
secondcufilecuda_d.o:(.bss+0x18): multiple definition of `glParam'
firstcufilecuda_d.o:(.bss+0x18): first defined here
The functions above seem similar, but thats becauseI tried to make them as simple as possible. It would be possible to write everything into a single .cu file, but I would like to split it up if possible.
What am I doing wrong with the linker? I am compiling and linking from within a Qt Creator project. Let me know if you need my lines from the .pro file to know how I use the nvcc compiler.
It's due to the fact that Global.h is included multiple times and each time it is included it provides: globalParam glParam;. That is not a forward declaration (i.e. not just a type signature) but amounts to an actual instantiation of a globalParam struct. This then, causes there to be two variables both named glParam (each corresponding to a separate #include of Global.h) and that gives you multiple definition errors.
Quick fix: try using extern if you wish to share your global variable (then the linker knows that it's just a reference to, well, a 'external' symbol).
Better fix: consider refactoring your code to pass in the global parameter via reference or pointer as argument to your functions. That way you won't even have to declare the glParam variable in the header, side stepping the entire issue and making your code more easy to understand/reason about into the bargain.
This question already has answers here:
How can a C++ header file include implementation?
(7 answers)
Closed 6 years ago.
I am just wondering how the compiler can handle the situation where a member function is declared & defined only in a include file but this .h file is included multiple times in different source codes without complains of the linker regarding multiple definition of ....
foo_1.h:
class foo
{
public:
auto in_include() -> void { printf( "in in_include()\n" ); }
foo();
};
foo_1.cpp:
#include <stdio.h>
#include "foo_1.h"
foo::foo()
{
printf( "in foo()\n" );
in_include();
}
and finally foo_main.cpp:
#include <stdio.h>
#include "foo_1.h"
int main()
{
foo fooObject;
}
These MCVE compiles and links fine and produces the expected output:
in foo()
in in_include()
BUT, when I add in foo_1.h this line int globar_var; then the linker complains [as I expect it]:
/tmp/ccfjJJAT.o:(.bss+0x0): multiple definition of `globar_var'
/tmp/cciob9sM.o:(.bss+0x0): first defined here
I do not consider as a duplicate because I ask why the linker does not complain. The other question is more or less asking why a function can be defined in a header file.
Class member functions that are defined with a body within the class declaration automatically become inline functions, and therefore it's OK even if the definition is compiled multiple times. You can get the same for non-class functions by using the inline keyword.
How this is implemented in practice is up to the compiler - it could actually inline the code every time it's called (think copy and paste), or it could arrange for some linker magic I don't fully understand to happen that prevents the collision.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
Is it possible to pass the template-parameters to a function somewhere else defined?
For instance I have the class
Barrier.pp
template<Location L, Knock K>
class Barrier
{
//...
void checkBarrier( ... )
{
BarrierBest_checkBarrier<L, K>( ... );
}
//...
}
Other.cpp
template<Location L, Knock K>
BarrierBest_checkBarrier( ... )
{
//Use L and K to do call other function
}
As I have it right now the compiler throws a unresolved external symbol for all the possible combinations of the template parameters, that is, BarrierBest_checkBarrier<1,1>, BarrierBest_checkBarrier<1,0>, BarrierBest_checkBarrier<0,1>, BarrierBest_checkBarrier<0,0>
Is there a way to make this work?
If there are a limited number of combinations, you can explicitly instantiate your template, allowing you to keep your code separated between header and source files.
Put this at the bottom of your source file
template void BarrierBest_checkBarrier<0, 0>(...);
template void BarrierBest_checkBarrier<0, 1>(...);
template void BarrierBest_checkBarrier<1, 0>(...);
template void BarrierBest_checkBarrier<1, 1>(...);
If you want other files calling your function to pick their own parameters not in this list, you must put the whole templated code into a header file.
The problem may be that your templated functions are in cpp files, not in headers. The template parameters have to be known at the compile time. If you have separate compilation units, they are not.