Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a C++ template function can I return a dereferenced argument type?

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.)

like image 851
jackj Avatar asked Jan 17 '10 01:01

jackj


2 Answers

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);
}
like image 130
Johannes Schaub - litb Avatar answered Sep 30 '22 14:09

Johannes Schaub - litb


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.

like image 34
AnT Avatar answered Sep 30 '22 14:09

AnT