views:

204

answers:

2

What I mean is the following. I want a template function that takes two vector iterators (or two pointers to array of double) and returns a double that is somehow related to the vector iterators or array pointers that I pass. However, I want this to work for double or int, or any arithmetic type.

I think I'm not allowed to say:

template <class T> 
T* func(T Begin, T End)

 T new_variable = Begin + 5;

 return (*new_variable);
}

because the compiler won't understand what T* means. A solution I thought of is to take what I'm trying to return and make it a third argument:

template <class T> 
void func(T Begin, T End, T* new_variable)

 new_variable = Begin + 5;

 return (*new_variable);
}

Will this work? Even if so, is there another way of doing what I'm trying to do? (Sorry if I haven't been clear enough.)

+8  A: 

If you want to return a double (i.e the type that you would get when dereferencing), you can use the iterator traits:

template<typename RandomAccessIterator>
typename std::iterator_traits<RandomAccessIterator>::value_type 
func(RandomAccessIterator a, RandomAccessIterator b) {
    typedef typename std::iterator_traits<RandomAccessIterator>::value_type 
      value_type;

    // use value_type now, when you want to save some temporary
    // value into a local variable, for instance
    value_type t = value_type();
    for(; a != b; ++a) t += *a;
    return t;
}

These work for all iterators, including pointers:

int main() {
  int d[3] = { 1, 2, 3 };
  assert(func(d, d + 3) == 6);
}
Johannes Schaub - litb
This seems to be exactly what I needed! A few points, though:1) I think you forgot to initalize the for loop.2) Is it OK when you use typedef to name a new type to call it value_type? Isn't this a reserved keyword or something?3) I didn't know about iterator_traits because I'm reading Accelerated C++. Can I find out more about it in Josuttis's book?
jackj
@jackj 1) You can leave out the for-loop initial section if you don't need it. "t" is fully initialized to the default value of value_type (0 for int), 2) Yes, value_type is not reserved. We can use it to shorten the long type name. 3) yes josuttis' book should cover this. :)
Johannes Schaub - litb
Wow! This is my first time on stackoverflow, but I know I will be coming back. You guys are awesome! Thanks a bunch.
jackj
@jackj: You should click on the checkmark to the left of the upvote/downvote widget, so that others know you've accepted this answer.
Emile Cormier
+1  A: 

Well, your code seems to contradict what you described in the text. If T is the iterator type, then the result of the iterator dereference (as you said in the text) will not have type T * (as you seem to believe in the code). T * is a completely opposite thing: it is something you'd get if you took the address of your iterator, not dereferenced it.

In fact, there's no way to express the "dereferenced type" using C++ core language features (maybe decltype will do it in the future, as in decltype(*T())). The only way to describe the result of dereference of type T is to use a library-based solution: iterator traits, as Johannes explained in his answer.

AndreyT
Thanks outis and AndreyT. You're right, the code does contradict what I thought was happening. I guess I got confused by the fact that in C++ the unary * is used to declare a pointer, and also to dereference a pointer or an iterator, but these two things are separate.
jackj
@jackj: That's because you are supposed to read the declaration `T* id` as "the type of `*id` is `T`": which unfortunately leads to bugs like `T* a, b;`, which defines a `T*` and a `T`. It's also why it's `T id[n]` not `T[n] id`: because the type of `id[n]` is `T`.
Simon Buchan
@jackj: If you're having problems with type declarations, try reading http://unixwiz.net/techtips/reading-cdecl.html or http://www.ericgiguere.com/articles/reading-c-declarations.html. The simplest description I've seen (and the reason for the syntax) comes from http://cm.bell-labs.com/cm/cs/who/dmr/chist.html: imagine the declaration is an expression whose value is the type named at the start of the declaration (e.g. for `T (*d)[2]`, think of `(*d)[1]` as being a `T`).
outis