Calculate the type of iterative return at the time of compilation


I need a function that takes two arguments arg1 and arg2

template<class T1, class T2>
SomeReturnType Foo(T1 arg1, T2 arg2);

The arguments can be a pointer or an std::iterator, either a bidirectional_iterator of a random_access_iterator. Foo does some operation with those iterators and needs to return an iterator to another object, but the returned iterator is of the following type

ptr, T   -> iterator< iterator_traits<T>::iterator_category >
T,   ptr -> iterator< iterator_traits<T>::iterator_category >
ptr, ptr -> iterator< random_access_iterator_tag >

random_access_iterator, random_access_iterator -> iterator< random_access_iterator_tag >

random_access_iterator, T -> iterator< iterator_traits<T>::iterator_category >
T, random_access_iterator -> iterator< iterator_traits<T>::iterator_category >
T, T                      -> iterator< bidirectional_iterator_tag> >

I plan to call helper functions from Foo based on iterator_category_tags of the arguments, using function overloading to take care of the dispatch. But I dont know how to compute the return type of Foo.

EDIT: I see the problem now. The return type of Foo is derived from std::iterator, and can be the argument of the Foo function. This is a problem because the traits class that I have been using were not specialized for these return types, only the base classes of the return types. I think the solution is to use the is derived_from metafunction.

EDIT2: the title clearly does not reflect the content of the question. To make this useful for others I am soliciting suggestions for a better title.

If I understand correctly that you're looking for a way to derive the return type from the argument types, you can do it in the classical way, like following (for the first few cases):

#include <iterator>

template<typename T1, typename T2>
struct ret_iterator {};

// ptr, T   -> iterator< iterator_traits<T>::iterator_category >
template<typename P, typename T>
struct ret_iterator<P *, T>
  typedef std::iterator<typename std::iterator_traits<T>::iterator_category, P> iter;

// T,   ptr -> iterator< iterator_traits<T>::iterator_category >
template<typename T, typename P>
struct ret_iterator<T, P *>
  typedef std::iterator<typename std::iterator_traits<T>::iterator_category, P> iter;

// ptr, ptr -> iterator< random_access_iterator_tag >
template<typename P>
struct ret_iterator<P *, P *>
  typedef std::iterator<std::random_access_iterator_tag, P> iter;

// random_access_iterator, T -> iterator< iterator_traits<T>::iterator_category >
template<typename T>
struct ret_iterator<std::random_access_iterator_tag, T>
  typedef std::iterator<typename std::iterator_traits<T>::iterator_category, T> iter;

template<typename P, typename T>
struct ret_iterator<std::iterator<std::random_access_iterator_tag, P>, T>
  typedef typename ret_iterator<std::random_access_iterator_tag, T>::iter iter;