I have a problem instantiating a generic object belonging to generic subclass. I get an undefined symbol error even though I implemented the function. I tried to recreate a minimal and reproducible example. The example I managed to recreate is similar to the one I got but here I get that the constructor is undefined while in my real but "un-pastable" code the error said that all the functions belonging to the superclass were undefined. But I think that the cause of the errors is the same and solving one will solve the other.
Here is the folder structure:
.
├── Makefile
├── abstract.cpp
├── concrete.cpp
├── interface.hpp
└── test
├── Makefile
└── test.cpp
And here is the content of the files:
interface.hpp contains the classes definitions
#ifndef INTERFACE_123
#define INTERFACE_123
namespace ca {
template <typename T>
class AbstractClass {
public:
virtual ~AbstractClass() = default;
virtual void simulate(unsigned n);
protected:
AbstractClass(int n);
int n;
};
namespace seq {
template <typename T>
class ConcreteClass : public AbstractClass<T> {
public:
ConcreteClass(int n);
};
} // namespace seq
} // namespace ca
#endif
abstract.cpp and concrete.cpp contain the implementations. concrete.cpp basically only extends abstract.
abstract.cpp
#include <iostream>
#include "interface.hpp"
template <typename T>
ca::AbstractClass<T>::AbstractClass(int n) : n(n){};
template <typename T>
void ca::AbstractClass<T>::simulate(unsigned n) {
std::cout << "inside simulate" << std::endl;
}
concrete.cpp
#include "interface.hpp"
template<typename T>
ca::seq::ConcreteClass<T>::ConcreteClass(int n) : AbstractClass<T>(n) {}
I build a static library with ar and ranlib and then try to use it in tests/test.
Here are the test/Makefile and test/test.cpp:
Makefile
CXX = g++
CXXFLAGS = -std=c++17 -g -O3 -Wall -pedantic
.PHONY: all
all: libr test
test: test.o ../libminimalexample.a
$(CXX) $(CXXFLAGS) -L.. -o $@ $< -lminimalexample
libr:
cd .. && $(MAKE)
#include "../interface.hpp"
int main() {
auto c = ca::seq::ConcreteClass<short>(10);
}
As it can be seen the test.cpp simply tries to create a ConcreteClass object. But when I go to compile the file I get the following error message:
g++ -std=c++17 -g -O3 -Wall -pedantic -L.. -o test test.o -lminimalexampleUndefined symbols for architecture x86_64: "ca::seq::ConcreteClass::ConcreteClass(int)", referenced from: _main in test.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
But as it can be seen I did define the constructor of ConcreteClass in the file concrete.cpp, didn't I?