如何为迭代器排序模板特化?

时间:2018-04-30 16:02:56

标签: c++ templates iterator

我正在编写partition函数,它是BidirectionalForward迭代器的专业化。

我不确定如果订单影响结果,那就是这两个版本是不同的。

第一

template< class BIter, class UnaryPredicate>
BIter __partition( BIter first,
                   BIter last,
                   UnaryPredicate pred,
                   std::bidirectional_iterator_tag);

template<typename FIter, typename UnaryPredicate>
FIter __partition(FIter first,
                  FIter last,
                  UnaryPredicate pred,
                  std::forward_iterator_tag);

template<typename FIter, typename UnaryPredicate>
FIter newton::partition(FIter first,
                        FIter last,
                        UnaryPredicate pred)
{
  return newton::__partition(first, last, pred, std::__iterator_category(first));
}

第二

template<typename FIter, typename UnaryPredicate> FIter
__partition(FIter first,
            FIter last,
            UnaryPredicate pred,
            std::forward_iterator_tag);

template< class BIter, class UnaryPredicate>
BIter __partition(BIter first,
                  BIter last,
                  UnaryPredicate pred,
                  std::bidirectional_iterator_tag);

template<typename FIter, typename UnaryPredicate>
FIter newton::partition(FIter first,
                        FIter last,
                        UnaryPredicate pred)
{
  return newton::__partition(first, last, pred, std::__iterator_category(first));
}

我看到gcc,llmv等使用第二个版本,但是...我读到编译器使用它的原型适合的第一个函数。

并不是Bidirectional Iter适合Forward Iter,然后使用该函数而不是专门的?

3 个答案:

答案 0 :(得分:3)

不,订单无关紧要。

如果category参数正好是std::bidirectional_iterator_tag,则一个函数比需要转换为基类的函数更好。

答案 1 :(得分:2)

  

我读到编译器使用了它的原型适合的第一个函数。

哇哇!那不是真的。编译器执行overload resolution以找到函数调用的最佳候选者,无论它们之前的顺序如何。

当然,如果你在两者之间的中间有一个功能,你将无法拨打第二个(假设你没有第二个声明),但是这不是这种情况,因为只要你称之为两个重载就知道了。

  

并不是Bidirectional Iter适合Forward Iter,然后使用该函数而不是专门的?

在这种情况下不行,因为代码使用的是一种称为标签分派的技术。 &#34;标签&#34;是完全独立的,通常只是一个空类struct some_tag {};(虽然不是这种情况)。如果情况并非如此,那么仍然没有,因为仍然会发生重载解析,即使双向迭代器可以转换为正向迭代器,仍然存在不需要任何更好匹配的转换的重载。

答案 2 :(得分:1)

  

我读到编译器使用它的原型适合的第一个函数。

Nope:它形成了一组可能的候选函数 - 这些函数具有正确的名称,可以匹配您的调用站点上的参数。然后它决定(或试图决定)哪个是最佳匹配。

这称为overload resolution(和名称查找,以及该页面顶部链接的其他内容)。

  

... Bidirectional Iter不符合Forward Iter

的情况

排序。

你要结合两件事:

  1. 迭代器类别(BidirectionalIterator扩展ForwardIterator等,如表here中)之间的(概念)关系
  2. iterator category tags
  3. 之间的关系

    也就是说,您可以逻辑说BidirectionalIterator 是-a ForwardIterator, std::bidirectional_iterator_tag是-a {{ 1}},以及你的重载

    std::forward_iterator_tag
    对于双向迭代器,

    但是,根据链接页面的隐式转换序列的排名部分,第二个重载是更好的匹配(它是精确的匹配,正如你所期望的那样是你能得到的最好的。)

    因此,我们可以更准确地说,两个重载之间没有歧义。