template <typename type>
double vector_mean(const vector<type>& my_vec, double order = 1)
{
if (my_vec.size() == 0)
{
cout << "Vector mean error" << endl;
exit(1);
}
double sum = 0;
for (unsignedlongint i = 0; i < my_vec.size(); i++)
{
sum += pow(my_vec[i], order);
}
sum = pow(sum, (double) (1. / order));
sum /= pow((double) my_vec.size(), (double) (1. / order));
return sum;
}
I'm trying to templatise this function over the container (in addition to the current templatisation over the contained data type), so that I can choose between std::vector, std::deque... and other STL containers.
I tried doing this many ways, but it doesn't compile. Could you guys please tell me how to do this?
#include <iostream>
#include <vector>
usingnamespace std;
template <class T>
double container_mean(T& my_cont, double order = 1)
{
if (my_cont.size() != 0)
{
double sum = 0;
for (unsignedlongint i = 0; i < my_cont.size(); i++)
sum += pow(my_cont[i], order); //??
sum = pow(sum, (double) (1. / order));
sum /= pow((double) my_cont.size(), (double) (1. / order));
return sum;
}
else
cout << "Vector mean error" << endl;
exit(1); // >.>
}
int main()
{
std::vector<int> test(5);
test[0] = 10;
test[1] = 30;
test[2] = 20;
test[3] = 40;
test[4] = 50;
std::cout << container_mean(test) << std::endl;
std::cin.ignore();
return 0;
}
Also, because a majority of containers don't have the same way of access to it's elements, I would highly suggest a more universal method to go about it (i.e. STL iterators ). This was not shown in the example I gave.
Also, when you give us an example to work with, it's much easier on everyone if you make a test case yourself like I did here.
You're trying to solve the problem the wrong way. As the above poster said, you want to template over iterators.
1 2 3 4 5
template<typename Iterator>
iterator_traits<Iterator>::value_type geometric_mean(Iterator first, Iterator last, int order) {
//loop over elements from first to last
//doing calculation
}
Edit: Just realised it isn't geometric mean, didn't read code properly
When you give a container a type such as "vector<int>", that vector isn't of type vector, it's of type vector<int>. You can pass whatever container you want after that, there's no point in checking for the datatype the container holds as far as I know. In a templated function like that, it should make no difference. The container holds a standard on how to access elements, check size, etc. If the container passed doesn't follow those rules, it will give an obvious compile-time error.
Aside from that, I'm not sure I understand what you're trying to do. You don't need the "type" template there, it will be used incorrectly. For instance if you pass a vector<int> to that function like: "container_mean<std::vector, int>(myVec)" where myVec is of type std::vector<int>, this wouldn't compile since myVec is *not* of type std::vector, it's of type std::vector<int>.
Actually I understand the difference between vector<double> and vector<int> on the basis that they are compile time classes. I understand, as well, that bitset<4> and bitset<5> are different entities and have nothing to do with each other, but they would have someting to do with each other because the definitions inside them allow them to read different bitsets with different template parameters.
But the issue here is that I want to "instantiate" my class the way I want, I don't want it to be detected automatically. So I want to tell the compiler to take it as vector<int> when I want, and vector<double> when I want, too. I actually avoid automatic instantiation. I don't find it a good idea.
In the sense you mentioned it totally makes sense if I want it to be detected automatically. But I'd like to have more control on that.
Actually the purpose is not this cute simple function of averaging. The point is learning this thing in general :-)
I find it really difficult to understand how the compiler would take such a "double" templatisation. I can imagine this possible only if we templatise on two steps, first for data, and then for container. Am I seeing this wrong? :-)
typename is simply boilerplate to indicate that it's a type, nothing more. You should be able to remove it with no problem.
typename ContainerType::value_type sum_values( const ContainerType& container ) is simply the function declaration.
typename ContainerType::value_type result = 0; is using the type that was passed to the container. So, the value_type of vector<int> should be (literally) type int.
In the case of STL containers it's probably wiser to use the value_type member typedef,
but the prorper way to do it in the general case would be template template parameters.