Okay, it seems like you implemented a class template. Class template need a slightly different treatment than classes as they do not finally describe a class but rather are a template that can be used to describe a lot of similar classes but with different template arguments.
I assume your code looks somewhat like that:
Oscillator.hpp
namespace eftilo
{
template <typename SampleType>
BufNaiveOscillator
{
public:
BufNaiveOscillator();
void process (juce::dsp::ProcessContextReplacing<SampleType>& context);
}
}
Oscillator.cpp
#include "Oscillator.hpp"
namespace eftilo
{
template <typename SampleType>
BufNaiveOscillator::BufNaiveOscillator()
{
// do some setup
}
template <typename SampleType>
void BufNaiveOscillator::process (juce::dsp::ProcessContextReplacing<SampleType>& context)
{
// do some processing
}
}
Now, if you are compiling the project, the compiler will compile PluginProcessor.cpp
and Oscillator.cpp
in parallel, individually from each other. PluginProcessor
references a specific instantiation of the template where SampleType
is float
. It does however not know at that point what the function eftilo::BufNaiveOscillator<float>::BufNaiveOscillator()
looks like as it’s not fully described in the scope of that file as the compiler sees it, so it leaves a note for the linker (ld
) to look for it somewhere else after all files have been compiled. In parallel, another compilation process parses Oscillator.cpp
. All it finds in this file is a definition of the implementation of the details of the class template you declared in Oscillator.hpp
but no hint for what template parameter choices it should actually compile this class. So it will actually compile nothing. After that the linker looks for some compiled version of eftilo::BufNaiveOscillator<float>::BufNaiveOscillator()
and fails to find it. This is why you get this error message.
Now how to solve this?
There are two choices. The first is to include a list of all template instantiations that the class template should actually be compiled for in the translation unit. This means you could add
template class BufNaiveOscillator<float>;
template class BufNaiveOscillator<double>;
at the end of your Oscillator.cpp
file so that now the compiler sees that it should compile the template defined above for this two specific types. Now the linker will be able to resolve a reference to BufNaiveOscillator<float>
, as this version has explicitly been compiled. It will still give you an error if you e.g. referenced BufNaiveOscillator<int>
in your code, as this version has not been compiled anywhere.
The other option that is used frequently is to define your class template header-only. This means, instead of splitting it up into a .hpp
header file and a separately compiled .cpp
translation unit, you can just put the whole definition right into the header. Now, every translation unit that references your template can see the full definition and can compile the version for your template type of choice along with the surrounding code.
I hope my guess was right and this helps you 