tags:

views:

119

answers:

2

Hi everyone, my question is sure a simple one for anybody familiar with C++ syntax. I'm just learning c++ and this is some sort of homework.

template<typename Iter>
void quickSort(Iter begin, Iter end)
{        
    //..
    auto pivot = * ( begin + (end - begin)/2 );
    //..
}

pivot is supposed to contain value from the center of [begin, end] interval. Ite The code i wrote there works, but auto is a keyword from the new standart of language. How to do it the old-way? What to write instead of auto?

Thanks, Ilya.

+9  A: 

typename std::iterator_traits<Iter>::value_type

This will work if your template is instantiated with Iter as a pointer type.

By the way, typename isn't part of the type itself. It tells the compiler that value_type really is a type. If it was the name of a function or a static data member, then that affects the syntax. The compiler doesn't necessarily know what it is, since the specialization of iterator_traits for Iter might not be visible when the template is compiled.

Steve Jessop
This is the best possible solution, but it's worth pointing out that it's not a general solution. It's not guaranteed to work with everything that a user might try to pass in as an iterator... they may still need to add value_type to their iterator object (or create a specialisation for the traits). An alternative is simply to continue using iterators, and create an iterator to the pivot, dereferencing it as needed, without needing the value type inside the templated function.
Tony
@Tony: that's true, and `auto` is better for that reason. However, all the standard algorithms require the user to pass something that has `iterator_traits` (24.3.1), and it's reasonable for user-defined function templates to have the same restriction. People who write iterators can use `std::iterator` as a base class to bridge the gap between *trying* to pass in an iterator, and actually passing in an `Iterator` ;-)
Steve Jessop
@Steve: yes, absolutely (and you got a +1 from me already).
Tony
@Tony, @Steve - here's a noob question, can the typeid() operator be used? Something like type_info
Les
@Les: you can use typeid, and typeid applied to *Iter (rather than Iter) can tell you the textual name of the value type, but you can not create an object of that type based on the typeid... there's no link to a factory method / constructor in the typeid information.
Tony
@Les: what Tony said. GCC has a `typeof` extension, and C++0x has `decltype`, which actually give you the type rather than just the type_info for the type. But in this particular case neither of them improves on `auto`.
Steve Jessop
A: 

The answer of Steve is right; in C++98, you have to use std::iterator_traits or you can use Iter::value_type if you know that the iterator has this typedef (e.g. is derived from std::iterator). However, there is another problem in your code: you normally can't simply divide iterators. This works with pointers, of course, but not in the more general case. A more general approach would be:

Iter itPivot = std::advance(begin, std::distance(begin, end)/2);
F. Mueller
The original code doesn’t divide iterators, and this wouldn’t work, not even with pointers. The code instead uses subtraction, which works on all random access iterators (not only pointers). And since quicksort will be sorted for other iterator types anyway (an efficient implementation anyway), the use of `operator -` here is fine.
Konrad Rudolph