Skip to main content
GameDev.net gamedev.net
🔒 Locked

Function template overloading [SOLVED!]

Started by felipedrl Mar 15, 2007 at 2:08 PM 9 replies 1.3k views
Original Post
felipedrl
felipedrl
Hi, I´d like to have my function flexible enough to receive an ordinary array, a STD vetor or a STD list abstract data type. So I created three overloaded template functions to handle them as this:

     extern template < class T > 
     T* getSelected( T **, ... );

     extern template < class T > 
     T* getSelected( std::vector< T *>, ... );
 
     extern template < class T > 
     T* getSelected( std::list< T * >, ... );


I was thinking that should be a way to do this in just one function. Can anyone give me a tip. Thanks in advance. [Edited by - felipedrl on March 15, 2007 7:57:17 PM]
mrbastard
mrbastard
Dealing with the abstraction at the level of the container makes it harder than it needs to be. Look into the concept of iterators. A pointer is an iterator, and all stl containers return iterators. This means that if your function template deals with arbitrary iterators, it will work for all your cases.

You'd probably want to put some restrictions on the type of iterator used (forward, random access, etc) but that would depend on your functions access pattern.
[size="1"]
NotAYakk
NotAYakk
template<typaname U, typename T>struct container_traits {  typedef T::iterator iterator;  typedef T::const_iterator const_iterator;  static iterator begin( T&t ) {return t.begin();}  static const_iterator begin( T const&t ) {return t.begin();}  static iterator end( T&t ) {return t.end();}  static const_iterator end( T const&t ) {return t.end();}  static iterator nth( T&t, size_t n ) {return t[n];}  static const_iterator nth( T const&t, size_t n ) {return t[n];}};template<typename U>struct container_traits<U, U*>:{  // ...};template<typename U>struct container_traits<U, std::list >{  // ...};etc


Now you have:
template<class T, class Container>T* GetSelected( Container&, ... ) {  typedef containter_traits<T*, Container> my_traits;  ...}


And the implementation of GetSelected uses the "my_traits" methods to interact with the container.

Be careful you don't overbloat the container traits -- they can be as hard to maintain as seperate functions if you aren't careful.
felipedrl
felipedrl
Actually I´m already using iterator to move through the list. My question is how to define the funtion signature so that the user can pass any kind of object in any data structure he wants.

For instance, if I define my function like this:

       extern template <class T>       T* getSelected( T**, ... );


could the user pass a std::list to it? Of course I cannot use a iterator with a ordinary C-array. I would need the size of the array as a parameter also, but I´m omiting this because it seems to be clear.

Thank you.

--------------- EDITED ------------------------------------------

Thank you NotAYakk, I saw your reply after replying this.
It will help a lot.
mrbastard
mrbastard
Perhaps I'm missing something, but I don't see why you need to pass the container. You should be able to pass an iterator/pointer to the first element and either number of elements or an iterator/pointer to the element after last. This is the idiom the stl algorithms use.

Perhaps I misunderstand what GetSelected is supposed to do.
[size="1"]
Paulius Maruska
Paulius Maruska
Quote:
Original post by felipedrl
could the user pass a std::list to it? Of course I cannot use a iterator with a ordinary C-array.

Why not?
template < class IteratorType > IteratorType getSelected( IteratorType first, IteratorType onePastTheEnd, ... );// inside the function, you have this:for(IteratorType it = first; it != onePastTheEnd; ++it) {// do something with (*it)}// or this:for(; first != onePastTheEnd; ++first) {// do something with (*first)}

Usage of the function:
std::vector< int > intVector;// push some data into the vectorstd::vector< int >::iterator selected = getSelected(intVector.begin(), intVector.end(), ...);// you can replace vector with list - it will work anywayint intArray[17];// assign some valuesint* selected = getSelected(&intArray[0], &intArray[16] + 1, ...);// this will work with any array


Note, all of the algorithms in std (stl?) uses this technique - you can use any of them with stl containers as well as with arrays.
felipedrl
felipedrl
First of all I wanna say that I´m very grateful for your patience and will to help.

I´ll tell the whole matter. I deleloped a library that uses viewport clipping algorithm to select any object in a canvas. All I need to know is how each object is drawn, so I need a pointer to Member Function as a param. The routine returns a pointer to the selected object. It´s important to say that the routine is already doing its job correctly. My problem is just to put the overloaded functions together.

The function complete definition is:
[source lang= "cpp"]template < class T >T* getSelected( std::vector<T *> objList, void (T::*draw)() const, GLint mouseX, GLint mouseY,                 GLdouble precision = 4.0, GLuint bufferSize = 512 );


I´m not very experienced with templates. I was amazed when Paulius told that we can use iterator with ordinary C-array.

I followed his tips and changed the definition to this:
template < class T >T getSelected( T first, T last, void (T::*draw)() const, GLint mouseX, GLint mouseY,                 GLdouble precision = 4.0, GLuint bufferSize = 512 )// And call it this waystd::vector< Shape * > objList;std::vector< Shape * >::iterator iter;Shape *s1 = NULL, *s2, *picked = NULL;s1 = new Sphere(-30.0, 20.0, 0.0 );s2 = new Cube( 20.0, 10.0, 0.0 );objList.push_back( s1 );objList.push_back( s2 );picked = getSelected( objList.begin(), objList.end(), &Shape::draw, x, y );


I get this error when try to compile:
no matching function for call to `getSelected(__gnu_cxx::__normal_iterator<Shape**, std::vector<Shape*, std::allocator<Shape*> > >, __gnu_cxx::__normal_iterator<Shape**, std::vector<Shape*, std::allocator<Shape*> > >, void (Shape::*)() const, int&, int&)' 


What is wrong? As I told you, because I´m new to templates and kind of new to programming too I can be missing something idiot.
How should I do that?

Thank you very much for your assistance!
mrbastard
mrbastard
I think you need to add another template parameter - you need one for the iterator type and another for the type you are taking a member function ptr to.
[size="1"]
felipedrl
felipedrl
Thanks for your amazing support mrbastard.
It´s working nice now. I´ve also learned a lot today with you.

See ya.
mrbastard
mrbastard
happy to help.
[size="1"]
Julian90
Julian90
Just highlighting the alternative to an extra template paramater as the extra paramater means a member function of something other then the type being iterated over may be passed.
// you need to #include <iterator> to use iterator_traitstemplate < class T >T getSelected( T first, T last, void (typename std::iterator_traits<T>::value_type::*draw)() const,               GLint mouseX, GLint mouseY, GLdouble precision = 4.0, GLuint bufferSize = 512 )

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.