Public Group

# My first STL + template

This topic is 4978 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

After reading the STL and newbies I realized I should get on it. So I just got home, and after about 20 mins total I created this:
// testie2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

using namespace std;

template <typename T>
T	Mean( vector<T> t )
{
// set result to 0
T re = 0;

// cast and set the size
int sz = (int)t.size();

// loop and sum
for(size_t i = 0; i < t.size(); ++i)
re += t;

// return the sum/size
return (T)(re / sz);
}

int _tmain(int argc, _TCHAR* argv[])
{
vector<int>		V;
vector<float>	F;

// seed the generator
srand( (unsigned)time(NULL));

for(int i = 0; i < 100; ++i)
{
// generate a random number
int rnd = rand() % 1000;

// insert the number
V.insert(V.begin(), rnd);
F.insert(F.begin(), (float)rnd);
}

// calculate the mean of the numbers
int	res = Mean<int>(V);
float	re2 = Mean<float>(F);

// display results
cout << res << endl;
cout << re2 << endl;

system("pause");
return 0;
}


I had a little trouble with clearing out the type-casting warnings (conversion from 'x' to 'y' possible loss of data), but it works now. I went to the DADS site linked in that prevoius thread, and that is where I got the idea to do the mean. I still want to make templated functions for median, midrange, and mode algorithms too. All-in-all, its a great thread to force you into sucking it up and learning STL. Not a lot of resources came up easily with google, so here is one that helped me with the std::vector stuff. Comments welcome, I just wanted to share my learning experience.

##### Share on other sites
Good job! Shame I'm too contempt with reading books on programming than programming to make anything...
Good luck with your future templats, STL, etc!

##### Share on other sites

Most STL algorithms use pairs of iterators to decouple the algoritm from the actual container it's a usefull ideom.
You're passing the vector by value, that's not good! basicly it means that you copy the whole thing just to send it to your function use a const refrence (refrence to const I guss is the correct terminology) instead.

Casting away typesafty is in most cases the wrong solution, espicially in this case since you could have used size_t instead and got rid of the warnings that way.

Anyhow, good luck with your future endouvers.

##### Share on other sites
Quote:
 Original post by DigitalDelusionsome comments:Most STL algorithms use pairs of iterators to decouple the algoritm from the actual container it's a usefull ideom.

That was a concern at first, I know I have seen them in other STL for(..) loops. I did not get any errors, and the code worked so I left it be. How should I use the iterators?
Quote:
 You're passing the vector by value, that's not good! basicly it means that you copy the whole thing just to send it to your function use a const refrence (refrence to const I guss is the correct terminology) instead.

good catch, I am so bad about that really. I think it is because I do not think of it happening, I just think of it as working.
Quote:
 Casting away typesafty is in most cases the wrong solution, espicially in this case since you could have used size_t instead and got rid of the warnings that way.Anyhow, good luck with your future endouvers.

I did use size_t for 'sz' at first, but I think it gave me another warning on the return line. How should size_t be handled? Is it really good to delcare a var as size_t when it will be used later with another type? If you don't mind explaining a better way.

Thanks!

##### Share on other sites
here's a slightly modified version that gets rid of most of the issues
template <typename T, typename FwItr>T mean(FwItr b, FwItr e){	T sum = T(), cnt = T();	for(; b != e; ++b, cnt = cnt + 1)		sum += *b;	return cnt ? sum / cnt : T();}

usage would look like this
// display resultscout << mean<int>( V.begin(), V.end()) << endl;cout << mean<float>( F.begin(), F.end()) << endl;

note the added flexibility, if you would want a float mean for the int array you simply would change the first line to
cout << mean<float>( V.begin(), V.end()) << endl;

##### Share on other sites
Wow, that code is a slap in the face. And I do not mean you are insulting me. I love the three uses of T(), it never crossed my mind. Only two questions come up to me, 'for(; b != e; ++b, cnt = cnt + 1') why not '++cnt', the long 'cnt = cnt + 1' seems out of place in that nice block. I have never used a comma in the third 'for()' param, is it something to do with that? And second, so the 'b' and 'e' are just pointers, and thats all that we are really comparing? The 'sum += *b;' makes me think so, along with your prevoius post. :)

edit: tag misuse

##### Share on other sites
cnt = cnt + 1 is because cnt isn't always of integral type but Im hopeing that any type used for the result at least will support adding 1 to it.

'b' and 'e' are iterators, the concept of an iterator is something that works quite much like a pointer it is a conceptual abstraction of a pointer and they exists in many flavours like forward , bidirectional and random access iterators to name but a few. Forawrd iterators can only be stepped forward bidirectional can be stepped both forward and backward and random access acts pretty much like you would expect a plain pointer to :)

##### Share on other sites
Quote:
 Original post by DigitalDelusionForawrd iterators can only be stepped forward bidirectional can be stepped both forward and backward and random access acts pretty much like you would expect a plain pointer to :)

So thats why it was named 'FwItr'. Thanks. :)

##### Share on other sites
Quote:
 Original post by DigitalDelusioncnt = cnt + 1 is because cnt isn't always of integral type but Im hopeing that any type used for the result at least will support adding 1 to it

Actually, cnt should indeed be of type size_t not of type T. Or, if you're worried about warnings, the int mozie used was OK for most cases.

Also, mozie, there was a rather important inefficiency in your original code (which using iterators does avoid), in that you were passing the vector by value, thus making a copy of all the values it contains (ouch). Passing by constant reference would have eliminated the problem:

template <typename T> T Mean(const vector<T>& t)

Furthermore, on a compliant compiler, you should be able to do Mean(V) without specifying 'float' or 'int', and the compiler will figure things out automatically from the type of V.

##### Share on other sites
Quote:
 Original post by DigitalDelusionhere's a slightly modified version that gets rid of most of the issueswith your eariler attempt. *** Source Snippet Removed ***usage would look like this// display resultscout << mean( V.begin(), V.end()) << endl;cout << mean( F.begin(), F.end()) << endl;note the added flexibility, if you would want a float mean for the int array you simply would change the first line to cout << mean( V.begin(), V.end()) << endl;

Good try but your code is not very generic [smile], here is a version that requires no need to give explicit types (takes advantage of iterator traits & auto type deduction courtesy of the compiler) and reuse exisiting algorithms:

#include <numeric>  // accumlate#include <iterator> // iterator_traits#include <iostream>template < typename InputIterator >typename std::iterator_traits<InputIterator>::value_typemean(InputIterator first, InputIterator last) {    typedef typename std::iterator_traits<InputIterator>::difference_type difference_type;    const difference_type N = std::distance(first, last);    return std::accumulate(first, last, 0) / (N ? N : 1);}int main() {  int A[] = { 1, 2, 3, 4, 5 };  const int N = sizeof(A) / sizeof(int);  std::cout << "mean value: " << mean(A, A + N) << std::endl;  }

[Edited by - snk_kid on March 30, 2005 10:58:22 AM]

1. 1
Rutin
32
2. 2
3. 3
4. 4
5. 5

• 13
• 9
• 9
• 9
• 14
• ### Forum Statistics

• Total Topics
633325
• Total Posts
3011370
• ### Who's Online (See full list)

There are no registered users currently online

×