"Undefined Symbols" Linker Error with Simple Template Class

Undefined symbols linker error with simple template class

The template definition (the cpp file in your code) has to be included prior to instantiating a given template class, so you either have to include function definitions in the header, or #include the cpp file prior to using the class (or do explicit instantiations if you have a limited number of them).

C++ Linking Errors: Undefined symbols using a templated class

When you define your template in a .cpp file, you have to explicitly instantiate it with all the types / template parameters known the template will be used beforehand like this (put it in the .cpp file):

template class TreeNode<Player>;

If you don't know with which template parameters the template will be used, you have to put all the definitions into the header. like

template<typename T>
class TreeNode {
public:
TreeNode() /* now, also put the code into here: */ { doSomething(); }
};

The reason is that when you are going to use the template from somewhere, the compiler has to be able to generate the code for that specific instantiation of the template. But if you place the code into a .cpp file and compile it, there is no way for the compiler to get its hands on the code to generate the instantiation (except when using the infamous export keyword, which is only supported by very few compilers).

This is also an entry in my C++ Pitfalls answer: What C++ pitfalls should I avoid?

Templates linker error: Undefined symbols (linker error), but everything in one file

The below syntax within the definition of struct:

const static NumberT value = 0;

is a declaration with an initializer, not a definition. That is, the compiler may use its value for optimization purposes, but once value is ODR-used (e.g., bound to a reference), that entity must have an address in memory. By using std::chrono::duration as a result of operator"", you force value to be bound by a reference that duration's constructor accepts as a parameter, hence the linker is allowed to complain about the missing definition. In order to provide a definition, put the following lines after the definition of the struct itself:

template <typename NumberT, size_t Depth>
const NumberT _StringToNumber<NumberT, Depth>::value;

and after the specialization:

template <typename NumberT, size_t Depth, char Head, char ... Tail>
const NumberT _StringToNumber<NumberT, Depth, Head, Tail ...>::value;

Or make all of the declarations inline (c++17):

template <typename NumberT, size_t Depth>
struct _StringToNumber<NumberT, Depth> {
inline const static size_t total_depth = Depth;
inline const static NumberT value = 0;
};

Also note that identifiers starting with an underscore followed by an upper-case letter are reserved for the implementation.

C++ Function Template, Undefined Symbol for Architecture

You are not allowed to seperate the declaration and definition of a templated function in the same way that you would a normal function (declaration in '.hpp' file, definition in '.cpp' file). There are a couple of ways you can get around that.

You can declare AND define the function in the same place in the header file.

OR

You could try this, in a file called functions.inl:

template<typename T> 
inline string vector_tostr(std::vector<T> v){
std::stringstream ss;
std::string thestring = "";
if(v.size() > 0){
ss << "[";
for(size_t i = 0; i < v.size(); i++){
if(i != 0)
ss << " ";
ss << v[i];
}
ss << "]";
thestring = ss.str();
}
return thestring;
}

Then, at the end of the header file (functions.hpp), type this in:

#include "functions.inl"

.inl is the file extension for the inline header file. You can use this to seperate the declaration
and definition of templated functions.

Undefined symbols for architecture x86_64 (I have found error, but I can not fix it.)

This is a well-known problem with template friends. The problem it that a compiler treats a friend declaration as a non-template, but it is a template. If you insist on the out-of-class definition of operator<<, you can do the following:

template<class T>
class Stack;

template<class T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);

template<class T>
class Stack {
public:
friend std::ostream &operator<< <> (std::ostream&, const Stack<T>&);
};

template<class T>
std::ostream& operator<<(std::ostream&, const Stack<T>&) {
//...
}

In other words, you should first tell a compiler that friend operator<< is a template.

Demo



Related Topics



Leave a reply



Submit