Jump to content
  • Advertisement
Sign in to follow this  
mozie

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
some comments:

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 this post


Link to post
Share on other sites
Quote:
Original post by DigitalDelusion
some 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 this post


Link to post
Share on other sites
here's a slightly modified version that gets rid of most of the issues
with your eariler attempt.

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 results
cout << 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by DigitalDelusion
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 :)


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

Share this post


Link to post
Share on other sites
Quote:
Original post by DigitalDelusion
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


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 this post


Link to post
Share on other sites
Quote:
Original post by DigitalDelusion
here's a slightly modified version that gets rid of most of the issues
with your eariler attempt.
*** Source Snippet Removed ***

usage would look like this

// display results
cout << 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;


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_type
mean(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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!