I see the following errors reported by the linker when trying to compile the code below:
g++ -pedantic-errors -Wall -Wextra -Werror -std=c++17 -o <program_name> <object_dir/*.o> -L/usr/lib -lstdc++ -lm -I<include.dir>
/usr/bin/ld: /mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/build/objects//mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/source/main/RvBaseUInt64Property.o: in function `RvBaseUInt64Property::RvBaseUInt64Property(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long)':
RvBaseUInt64Property.cpp:(.text+0x4e): undefined reference to `RvBaseProperty<unsigned long>::RvBaseProperty(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long)'
/usr/bin/ld: /mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/build/objects//mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/source/main/RvBaseUInt64Property.o: in function `RvBaseUInt64Property::~RvBaseUInt64Property()':
RvBaseUInt64Property.cpp:(.text+0xc6): undefined reference to `RvBaseProperty<unsigned long>::~RvBaseProperty()'
/usr/bin/ld: /mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/build/objects//mnt/c/Users/AhmedRahim/workspace/repos/RvBaseLib/source/tests/sanity_tests/sanity.o: in function `main':
sanity.cpp:(.text+0x84): undefined reference to `RvBaseProperty<unsigned long>::Print() const'
collect2: error: ld returned 1 exit status
As far as I'm aware, there should not be any issues regarding inheriting from a templated class as of C++17. I'm not sure what is going wrong here. Can anyone help?
RvBaseProperty.h:
template <typename T> class RvBaseProperty
{
private :
string mName {"Undefined"};
T mValue;
bool mValid {false};
static uint64_t mBasePropertyRefCount;
public :
explicit RvBaseProperty(string _name, T _value);
~RvBaseProperty();
...
void Print() const;
};
RvBaseProperty.cpp - only relevant parts shown.
#include "RvBaseProperty.h"
using namespace std;
template <typename T> uint64_t RvBaseProperty<T>::mBasePropertyRefCount = 0;
// ========================================================================
template <typename T> RvBaseProperty<T>::RvBaseProperty(
string _name,
T _value) :
mName (_name),
mValue (_value)
// ========================================================================
{
SetValid();
++mBasePropertyRefCount;
}
// ========================================================================
template <typename T> RvBaseProperty<T>::~RvBaseProperty()
// ========================================================================
{
--mBasePropertyRefCount;
}
BaseUInt64Property.h
#include "RvBaseProperty.h"
class RvBaseUInt64Property : public RvBaseProperty<uint64_t>
{
public:
explicit RvBaseUInt64Property(string _name, uint64_t _value);
~RvBaseUInt64Property();
};
BaseUInt64Property.cpp
#include "RvBaseUInt64Property.h"
// ========================================================================
RvBaseUInt64Property::RvBaseUInt64Property(
string _name,
uint64_t _value) :
RvBaseProperty<uint64_t>::RvBaseProperty(_name, _value)
// ========================================================================
{}
// ========================================================================
RvBaseUInt64Property::~RvBaseUInt64Property()
// ========================================================================
{}
main():
RvBaseUInt64Property const * prop0 = new RvBaseUInt64Property("uint64_t", 99);
prop0->Print();
You have to put your template definitions in the .h
so that clients that instantiate your template can see the definition.
Compilers do not instantiate (turn into object code) templates when they parse the definition as at that time the template parameters are not known. It is only when the template is used that the template parameters become known, and the template is turned into object code.
This statement excludes explicit instantiation where the template parameter is explicitly supplied, which is not the case in your code.
Kudos for not putting the template definitions inside of the template class declaration. That is an over-used feature of C++. Just put the definitions below the class declaration in the header file.