Let's assume I have a probability class with a method that computes the average of an array. Because it's possible that this method be passed an array of floats, doubles, ints, etc, I assumed it would be appropriate to make this method a template method.
But when passing an array, I have to define a the type of array and length of an array. So my question is: how do I configure the template to accept two inputs? I have referenced the web but have had limited luck in seeing a good example.
I've posted my code below
Probability Header
#ifndef COFFEEDEVMATH_PROBABILITY_H
#define COFFEEDEVMATH_PROBABILITY_H
class Probability
{
public:
Probability(void);
template <typename T, int N>
void ExpectedValueDataSet(const std::array<T, N>& data)
{
T test = data[0]; // This is irrelevant, but simply a place holder example.
}
protected:
private:
};
#endif // COFFEEDEVMATH_PROBABILITY_H
Main
#include <iostream>
#include <Probability.h>
int main()
{
float hoor[] = {3, 3, 1, 1};
Probability prob;
prob.ExpectedValueDataSet(hoor, 4);
}
The problem is that you've defined your source array as a shitty C array instead of a std::array
. If you define your source array as a std::array
, you won't have this problem.
Also, there's no need to pass the length in addition, as you have with your example.
Is it valid to define templates to accept parameters that are ints, floats, etc.?
It's perfectly fine. But to pass an array, you must have an array.
std::array<float,4> hoor2 = {3.0f, 3.0f, 1.0f, 1.0f};
In the corresponding template you must use size_t
, not int
template <typename T, size_t N>
void ExpectedValueDataSet(const std::array<T, N>& data) {}
how do I configure the template to accept two inputs?
Just add an additional parameter. To pass a pointer and a length, you create a template that receives a pointer and a length
template <typename T>
void ExpectedValueDataSet( T const * data, int N){}
There is also a special syntax for c style arrays that will allow you to pass them without having to specify the length, as that argument will be deduced from the type.
template <typename T, size_t N >
void ExpectedValueDataSet( const T (&data)[N]) { }
Together we have
class Probability
{
public:
template <typename T, size_t N>
void ExpectedValueDataSet(const std::array<T, N>& data) {}
template <typename T>
void ExpectedValueDataSet( T const * data, int N){}
template <typename T, size_t N>
void ExpectedValueDataSet(const T (&data)[N]){};
};
See live working exampe here
Please note that you are trying to pass old plain C array float hoor[]
to function with parameter of type std::array<T,N>
which is NOT directly compatible with plain C array.
Correct syntax to pass plain C array as reference is:
template <size_t N, typename T>
void ExpectedValueDataSet(const T (&data)[N])
{
T test = data[0];
}
Usage example:
float hoor_f[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_f);
int hoor_i[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_i);
Ultimately, I have a feeling that the following is what you should be doing:
template<typename C>
typename C::value_type average(C const& c)
{
return std::accumulate(std::begin(c), std::end(c), C::value_type{}) / c.size();
}
std::vector
whenever possible.std
is good.The above code satisfies all three and works with the following examples:
std::vector<double> vd = { 0., 1., 3., 4.4 };
std::array<float, 4> af = { 3.f, 5.f, 6.f };
std::list<int> li = { 1, 2, 3 };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With