在编译时计算迭代器返回类型

时间:2012-11-27 10:45:23

标签: c++ templates

我需要一个带有两个参数arg1arg2

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

参数可以是指针或std::iterator,也可以是random_access_iterator的bidirectional_iterator。 Foo对这些迭代器执行一些操作,并且需要将迭代器返回到另一个对象,但返回的迭代器是以下类型的

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

我计划根据参数的iterator_category_tags从Foo调用辅助函数,使用函数重载来处理调度。但我不知道如何计算Foo的返回类型。

编辑:我现在看到了问题。返回类型Foo派生自std :: iterator,可以是Foo函数的参数。这是一个问题,因为我一直使用的traits类并不专门用于这些返回类型,只有返回类型的基类。我认为解决方案是使用is derived_from元函数。

EDIT2:标题显然不能反映问题的内容。为了使其对其他人有用,我正在征求关于更好标题的建议。

2 个答案:

答案 0 :(得分:1)

您可以使用提升功能特征。 看这里http://www.boost.org/doc/libs/1_52_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html

你可以像这样使用它:

boost::function_traits<FunctionSignature>::result_type

答案 1 :(得分:1)

如果我正确理解你正在寻找一种从参数类型派生返回类型的方法,你可以用经典的方式来做,如下面的(对于前几种情况):

#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;
};