Template functions issue


#1

I have a this declared in Oscillator.h

   

template <typename FloatType>

void processBlock (AudioBuffer<FloatType>& outputBuffer, int startSample, int numSamples);

 

and the function in Oscillator.cpp:

template <typename FloatType>

void Oscillator::processBlock (AudioBuffer<FloatType>& outputBuffer, int startSample, int numSamples)

{   

}

When I compile, I get linker errors saying:

Undefined symbols for architecture i386:

  "void Oscillator::processBlock<double>(juce::AudioBuffer<double>&, int, int)", referenced from:

      void SynthVoice::processBlock<double>(juce::AudioBuffer<double>&, int, int) in SynthVoice.o

  "void Oscillator::processBlock<float>(juce::AudioBuffer<float>&, int, int)", referenced from:

      void SynthVoice::processBlock<float>(juce::AudioBuffer<float>&, int, int) in SynthVoice.o

ld: symbol(s) not found for architecture i386

clang: error: linker command failed with exit code 1 (use -v to see invocation)

I googled the error and every answer I see says to put the actual function in the header file instead of the cpp file.

But I noticed that the PluginProcessor files that Juce produces has the ::process function defined just like I'm trying to do, but with no erroes.

How can I do this? I like separate .h & .cpp files.

Thanks.


#2

Your problem is, that at the time the compiler compiles the implementation of your template (Oscilator.cpp) it doesn't create any code, because it has no specalisation. When the linker tries to link the SynthVoice.o with the Oscilator.o, he cannot resolve the symbol, because the compiler didn't create one.

You can force the compiler to create the symbols to link by requesting the specialisation at the end of the Oscilator.cpp file:

template void Oscillator::processBlock<float>(juce::AudioBuffer<float>&, int, int);
template void Oscillator::processBlock<double>(juce::AudioBuffer<double>&, int, int);

If you don't know which specialisations will be needed in the future you need to put the implementation in the header. Some also name the implementation Oscilator_cpp.h and add an #include "Oscilator_cpp.h" at the end of Oscilator.h, so the build rules don't try to compile the template implementation. An other common practice is using the suffix ".inl" for the implementation and also include it at the end of the header file.

For longer explanations see also on stackoverflow: http://stackoverflow.com/questions/1639797/template-issue-causes-linker-error-c

HTH


#3

Thanks. That did the trick.

Although...I'm still wondering why the PluginProcessor class that Juce auto-generated doesn't have this same problem or solution.