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 4 years ago.
In general, templates are implemented in the header files (as many answers in Stack Overflow point out) so the code template is available to the compiler when it needs it to create a new instance of the class/function. However, in my case, some of the methods in my template class can be used only for a certain type, so my class looks like:
Class header
#ifndef LEC_H
#define LEC_H
#include <iostream>
template <typename T>
class LEC
{
public:
LEC()
{
}
void func() const;
void func2() const
{
std::cout << "Func 2" << std::endl;
}
};
#endif // LEC_H
Class cpp
#include "lec.h"
template <typename T>
void LEC<T>::func() const
{
std::cout << "Func: " << typeid(T).name() << std::endl;
}
template class LEC<float>;
template class LEC<double>;
The last two lines of the cpp file allow me to use func() because I explicitly instantiate this class template for these two types. When I use this class template in a program I can use any type as long as I do not call func():
#include "lec.h"
int main()
{
LEC<float> a;
LEC<double> b;
a.func2();
a.func();
b.func2();
b.func();
LEC<char> c;
c.func2();
return 0;
}
But, since the code is not available for the compiler to intsantiate func() for a LEC class with type char, I cannot do c.func() or I will get a compiler error:
undefined reference to `LEC::func() const'
This is a simplification of my real code. However, in my code, when I do LEC<char> c to create an instance of the class I get the error, without calling any methods, only by constructing the class.
Any idea on how to find out why this, apparently not used method, has to be linked anyways?
Is there a way so the compiler (in my case I am using clang++: clang version 6.0.0-1ubuntu2) points out where is this method used within the code?
Otherwise, can somebody explain why this (not having to link to a non-used class method) is working in the provided example and not in my code?
Edit
The cmake looks like:
add_library(lec_lib SHARED lec.cpp lec.h)
add_executable(lec_main main.cpp)
target_link_libraries(lec_main lec_lib)
Hence, the compiled library is linked with the executable.
Edit 2
Please avoid suggesting answers such as Why templates can only be implemented in the header file since I already know that the template has to be available to the compiler when the class is instantiated for a new type. My question is different. Why can I instantiate a type for which not all the template implementations are available as long as I do not use the specific class methods for which the template implementation is not provided at instantiation time (in the example case func())
Edit 3
Regarding the suggestion that this is a duplicate of What is an undefined reference/unresolved external symbol error and how do I fix it?. Again my question is different. I am looking for answers on why in the example I can instantiate LEC<char> when LEC<char>::func() is not visible for the compiler when it compiles the main program. And inthe case that this cannot be done and L3C<char>::func() is required to be linked, how to find why the method linkage is required while it is not being used (which is what happens in my real code).
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 1 year ago.
Assume these two cc files:
0.cc
#include <iostream>
template <class T>
T test(){
return 5;
}
int main(){
return test<int>();
}
1.cc
template <class T>
T test(){
return 5;
}
We compile them with g++ 0.cc 1.cc.
This compiles and runs successfully but if above functions were not templates then we would get a duplicate symbol error during compilation and linking phase.
Why using templates does not generate a link error?
Template is not instantiated until it is called in the code. Think of it as a local function to the compiled object.
Therefore, template as such is not exported and is not subject to linking of any kind, as it can't be referenced from another object. Should you be calling template defined in another header, it would still be instantiated in the local object.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
Why is it giving me a linking error? I think it's OK to access static members with this->x. Logically it sounds OK. I guess an instance pointer can access what a class owns as per OOPS concepts.
You need to also define the static member variable. For example:
// in .h
class some_class {
static int v; // it's just a declaration
};
// in .cpp
int some_class::v; // here's the defination
Put declarations in your Foo.h file:
class Foo {
static int v;
};
Put defenitions in your Foo.cpp file:
int Foo::v;
Here are some explanations: Why the static data members have to be defined outside the class separately in C++, Defining static members in C++
I find it helpful to treat linking errors differently. If you do something against the rules of the language -- the compilation error will be issued, so if you get a linking error it must be not something that you've done against the rules of the language directly, rather than you've omitted something. And usually the error message tells you what exactly you have omitted.
This question already has answers here:
What does it mean to have an undefined reference to a static member?
(2 answers)
Closed 9 years ago.
I have a .cpp file that looks something like this:
//other code
namespace {
class C1;
class C2;
class C2{
public: static int counter;
//member functions here
};
class C1{
//other code
C2::counter = 10;
};
}
When I run 'make' I get the following error:
relocation R_386_GOTOFF against undefined symbol '(anonymous namespace)::C2::counter' can not be used when making a shared object...
Am I missing something simple here? Shouldn't the static int be available for class C1 to change it? Also, I am developing this as a part of the Clang library's. Also, I can share the Makefile if that helps.
You have missed out on providing the definition of you static variable. This definition must occur outside the class and only one definition is allowed. Usual way to do this is to provide the definition in the implementation file.
Because you are directly using it, without providing any definition for it, you are getting the error.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can templates only be implemented in the header file?
When I include MyClass.h and do:
MyClass<int, int> ccc = MyClass<int, int>();
ccc.myMethod1(3, 4);
I get a lot of errors telling undefined reference to constructor and methods ... However when I include MyClass.cpp (which is not a proper why to code) there is no error ! How to fix that ?
I'm compiling under Code::Blocks using g++
The reason is that template classes are not compiled, only instantiated templates will be compiled.
Rule of thumb: don't place template implementations in a cpp file but either directly in the header or another file included by the header (if you want to part implementation from the interface).
E.g:
myclass.h
template<typename A>
class MyClass
{
...
};
#include "myclass.inc"
myclass.inc
//implementation goes here:
....
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the implementation and the declaration of a template class be in the same header file?
My header file has
template <typename T>
class AA : public BB<T>
{
public:
AA()
{ ... }
this is working fine. But I need to separate the constructor implementation from header file.
So in cpp, I have
template <typename T>
AA<T>::AA()
{ ... }
When I compile this, it compiled but I get unresolved external symbol error. What am I missing here?
You can explicitly instantiate templates in your implementation file using :
template class AA<int>;
this will generate a definition from a template, but it is of use only if you know what types your class clients will use
If you put a template implementation into a .cpp file you need to make sure that it gets instantiated: the compiler won't do it automatically for you. Roughly the same question was answered about a day ago: do template always have to be in the header?