I've done a bunch of research on class templates, and looked at examples, but I'm having trouble implementing.
I have a RollingAverage class that was written to handle an array of int, but I want it to be able to use other data types.
Here's my code:
Header file:
template <typename T> class RollingAverage {
private:
T* ptr;
static const int maxNumSamples = 100;
T sampleArray[maxNumSamples];
int numSamples = maxNumSamples;
int numSamplesTaken = 0;
int sampleIndex = 0;
T previousRollingAverage = 0;
T rollingAverage;
unsigned long sampleSum = 0;
public:
RollingAverage(int numSamples);
//RollingAverage();
void reset();
void clear();
void initialize(int numSamples);
T takeSample(T sample);
T getLastNthSample(T n);
int getSlope();
int getAverage();
T getSampleSum();
int getNumSamplesTaken();
int getMaxNumSamples();
};
CPP file
template <typename T> RollingAverage<T>::RollingAverage(int numSamples){
initialize(numSamples);
}
template <typename T> void RollingAverage<T>::reset(){
clear();
numSamples = maxNumSamples;
}
template <typename T> void RollingAverage<T>::clear(){
numSamplesTaken = sampleIndex = rollingAverage = previousRollingAverage = sampleSum = 0;
}
template <typename T> void RollingAverage<T>::initialize(int numSamples){
if(numSamples<=maxNumSamples){this->numSamples=numSamples;}
numSamplesTaken = 0;
sampleIndex = 0;
previousRollingAverage = 0;
rollingAverage;
sampleSum = 0;
}
template <typename T> T RollingAverage<T>::takeSample(T sample){
if(numSamplesTaken < numSamples){ numSamplesTaken++; }
if(++sampleIndex == numSamples){ sampleIndex = 0; }
sampleSum += sample;
sampleSum -= sampleArray[sampleIndex];
sampleArray[sampleIndex] = sample;
previousRollingAverage = rollingAverage;
rollingAverage = (int) (sampleSum / (long) numSamplesTaken);
return rollingAverage;
}
template <typename T> T RollingAverage<T>::getSampleSum(){
return sampleSum;
}
template <typename T> int RollingAverage<T>::getNumSamplesTaken(){
return numSamplesTaken;
}
template <typename T> T RollingAverage<T>::getLastNthSample(T n){
int newIndex = sampleIndex;
if( n <= numSamplesTaken ){
if (sampleIndex < n){
newIndex = numSamplesTaken - (n - sampleIndex);
}
else{
newIndex = sampleIndex - n;
}
return sampleArray[newIndex];
}
else{return 0;}
}
template <typename T> int RollingAverage<T>::getSlope(){
return(rollingAverage - previousRollingAverage);
}
template <typename T> int RollingAverage<T>::getAverage(){
return rollingAverage;
}
template <typename T> int RollingAverage<T>::getMaxNumSamples(){
return numSamples;
}
THIS IN ITSELF COMPILES FINE!
But when I instantiate an object of this in another class, lets call it SomeClass, and attempt to call member functios of RollingAverage, every member function call throws a compiler error:
Header:
class SomeClass{
private:
const int sensorAvgNumSamples{100};
RollingAverage<int> sensorRollingAverage;
public:
SomeClass();
void initialize(int sensorVal);
};
CPP file
SomeClass::SomeClass()
//uses initializer list to construct objects using parameters
: sensorRollingAverage(RollingAverage<int>(sensorAvgNumSamples))
{
//some code
}
void SomeClass::initialize(int sensorVal){
if( sensorRollingAverage.getNumSamplesTaken() < sensorAvgNumSamples ){
sensorRollingAverage.takeSample(sensorVal);
}
}
Each call to a RollingAverage member function gets:
undefined reference to `RollingAverage<int>::getNumSamplesTaken()'
Or whichever function is being called.
Sketch code if it matters:
SomeClass someClass;
int num;
void setup() {
someClass.initialize(3);}
void loop() { }
The errors include the constructor calls in the initialization list for SomeClass. These aren't specifically causing the problem because that initialization list works great for the non-template version of RollingAverage.
Any help would be appreciated. As always I apologize for my total noobnes at C++. If you need more/less context let me know.