tags:

views:

45

answers:

3

I was trying to write a templatized quicksort function. The thought in my head was that I would write a quicksort that can operate on any data structure that has a subscript operator and an order relation on the objects contained within it, so I could do things like

quicksort<deque<int> >();
quicksort<vector<string> >(); 

etc.

I started out with a function like

template<typename T>
void quicksort(T& list);

the problem I immediately ran into was coming up with a function that performs the swap operation which is necessary for sorting. I need to know if the values I'm swapping are strings, chars, ints, whatever so I can make a temporary to perform the swap!

So I need to be able to do something like this (I know this syntax is incorrect, I'm just trying to illustrate what I'm trying to do):

template<typename T, typename R>
void quicksort(T<R>& list);

so I can know what type of object is contained within T while I'm performing the swap. Clearly this means that T has to be, itself, a template class with a template argument specifying what type it contains but that's not really a big deal.

Is this possible? It seems like it should be. What is this called?

+1  A: 

All of the containers have a typedef value_type that you can use to get T:

template <typename ContainerT>
void quicksort(ContainerT& container)
{
    typedef typename ContainerT::value_type ElementT;
    // etc.
}

That said, wherever possible, algorithms should be implemented using iterators, to further decouple them from specific container implementations. For example,

template <typename RandomAccessItT>
void quicksort(RandomAccessItT first, RandomAccessItT last)
{
    typedef std::iterator_traits<RandomAccessItT>::value_type ElementT;
    // etc.
}
James McNellis
Except built-in arrays :-)
Peter Alexander
It would be better to define a `container_traits<T>` struct that uses `T::value_type` in the primary template, and specialises for built-in arrays.
Peter Alexander
@Peter: An array is not a container (where "container" means "adheres to the STL or standard library container concepts"). Pointers into an array can be used as iterators, though. It is better to use iterators.
James McNellis
Thanks! I guess that in general I should include a typedef for value_type in every container I make from now on, huh?
Alexander Questioning Bresee
@Alexander: Yes; there's actually a spec for the STL (http://www.sgi.com/tech/stl/Container.html) that defines the interface containers must implement and what the semantics of different types of iterators are. (To the best of my knowledge, the SGI STL spec that I linked to matches the actual C++ spec close enough to use it for implementing your own containers and such).
James McNellis
+2  A: 

If T is a proper STL container, you can get the value type with:

typename T::value_type

So, for example, if T is an std::vector<std::string>, then typename T::value_type is an std::string.

Charles Salvia
+1  A: 

You can use std::swap to swap two values.

Your template function should be like this :

template < class ContainterType >
void quicksort( ContainerType &container )
{
 //  ...
}
VJo