So you’ve decided to code something and you think templates are better suited for it since it’ll make it more generic. Let’s take an example of this using a simple buffer class as shown below
#ifndef BUFFER_HPP
#define BUFFER_HPP
#include <memory>
template <typename T>
class Buffer {
private:
std::unique_ptr<T[]> buffer;
size_t _size;
public:
Buffer(int size = 0);
void resize(int size);
T& operator[] (int index);
size_t size() const;
T* get();
~Buffer();
};
#endif //BUFFER_HPP
This is a simple custom buffer class now we can create another separate file with the implementation as shown below,
#include "buffer.hpp"
#include <iostream>
template <typename T>
Buffer<T>::Buffer(int size)
{
buffer = std::unique_ptr<T[]>(new T[size]);
_size = size;
}
template <typename T>
void Buffer<T>::resize(int size)
{
if (size < 0)
return;
auto prev_buffer = std::move(buffer);
buffer = std::unique_ptr<T[]>(new T[size]);
int to_copy = size < _size ? size : _size;
for (auto i = 0; i < to_copy; i += 1) {
buffer[i] = std::move(prev_buffer[i]);
}
_size = size;
}
template <typename T>
T& Buffer<T>::operator[] (int index) {
if (index < 0 || index >= _size) {
return buffer[0];
}
return buffer[index];
}
template <typename T>
size_t Buffer<T>::size() const {
return _size;
}
template <typename T>
T* Buffer<T>::get() {
return buffer.get();
}
template <typename T>
Buffer<T>::~Buffer() {
std::cout<<"Removing buffer \n";
}
Linker error when code is split
When code is splitted like above, for a templated class or function then this result in linker error. This is because the compiler doesn’t know what to generate and thus you’ll see some errors like,
/usr/bin/ld: CMakeFiles/shared_ptr.dir/shared_ptr.cpp.o: in function `main':
shared_ptr.cpp:(.text+0x87): undefined reference to `Buffer<char>::Buffer(int)'
/usr/bin/ld: shared_ptr.cpp:(.text+0x19a): undefined reference to `Buffer<char>::operator[](int)'
/usr/bin/ld: shared_ptr.cpp:(.text+0x1fa): undefined reference to `Buffer<char>::~Buffer()'
/usr/bin/ld: shared_ptr.cpp:(.text+0x20f): undefined reference to `Buffer<char>::~Buffer()'
A simple solution to overcome this is to create a new file which includes both the header and cpp implementation file as shown below,
#ifndef BUFFERED_HPP
#define BUFFERED_HPP
#include "buffer.hpp"
#include "../buffer.cpp"
#endif //BUFFERED_HPP
In the code to the left, we’ve created a new header file which includes both the header and the cpp file.
The code which needs to use this Buffer class will need to include this header rather than buffer.hpp so the compiler knows what code to generate.
You can get the complete code at Smart Pointer with Custom Delete