I roughly got the following setup:
#include <iostream>
using namespace std;
template<typename T>
class Element{
T getX() const;
T getY() const;
private:
T x,y;
std::vector<float> handling_times;
float cost;
};
template<typename T, typename Tnext>
class Bloc {
T getX() const;
T getY() const;
private:
T x,y;
Tnext num_blocs;
float effort;
float damage_done;
};
template<typename T>
class Measurements {
void calcMeasurements(const std::vector<T*> &data);
float getMean() const;
private:
float mean;
};
int main() {
std::vector<Element<int>*> elements;
// fill with elements
std::vector<Bloc<float,2>*> blocs;
// fill with blocs
// calculate mean of blocs effort
Measurements<Bloc<float,1>> bloc_mean_effort_measurement;
bloc_mean_effort_measurement.calcMeasurements(blocs);
return 0;
}
So two classes Element
and Bloc
which hold some data I'd like to perform Measurements
on. For example, I'd like to measure the getMean()
of an Element
's handling_times
which is of type std::vector<float>
. Another case would be to measure the mean of std::vector<Bloc<float>*> blocs
based on the effort stored in each Bloc
. As you can see the input types for an Measurement
vary but the functionality behind the mean calculation always stays the same. I'd like to have this functionality only implemented once (mean is only the simplest example I could think of) and use it on different types. Furthermore, I can't get my head around, how to pass the Measurement
object based on which entity (e.g. Element
costs
or Bloc
effort
) the measure should be computed. Would it make sense to have an enum PossibleMeasurements
in Element
with HANDLING_TIMES
and COSTS
. So to say for each private variable I would like to be able to compute measures on.
If I understand the question correclty, you have more or less this:
struct A {
std::vector<int> a;
};
struct B {
int value;
B(int x) : value(x) {}
};
typedef std::vector<B> Bvect;
And now you want to calculate the mean of the values with the same generic function whether they are in an A
or in a Bvect
. This generic function already exists and is called std::accumulate
. For the object containing the vector you would do
A foo;
foo.a.push_back(123);
std::cout << std::accumulate(foo.a.begin(),foo.a.end(),0.0) << "\n";
You have to pass two iterators indicating the first and one past the last element to be accumulated, and an initial value.
For the Bvect
it looks quite similar, we just have to supply a custom way of adding up the elements:
Bvect b;
b.push_back(B(123));
std::cout << std::accumulate(b.begin(),
b.end(),
B(0),
[](B b1,B b2){
return B(b1.value + b2.value);
}).value << "\n";
I use a lambda to access the values to be added and construct a B
holding the sum of the two values.
PS: This examples only calculate the sum, to get the average simply divide by number of elements.