Reputation: 4254
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.
Upvotes: 0
Views: 183
Reputation: 16898
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;
};
Upvotes: 1
Reputation: 511
You can use boost function traits for this. Look here http://www.boost.org/doc/libs/1_52_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
you can use it like this :
boost::function_traits<FunctionSignature>::result_type
Upvotes: 1