如何对迭代器的模板专业化进行排序?

How to sort the template specialisation for iterators?

本文关键字:专业化 排序 迭代器      更新时间:2023-10-16

我正在编写一个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然后使用该功能而不是专业化吗?

不,顺序无关紧要。

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

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

哇!那不是真的。编译器执行重载解析以查找函数调用的最佳候选项,无论它们之前处于什么顺序。

当然,如果你有一个介于两者之间的函数,你将无法调用第二个函数(假设你没有第二个函数的声明(,但这里的情况并非如此,因为无论你在哪里调用它们,这两个重载都是已知的。

难道Bidirectional Iter不适合Forward Iter然后使用该功能而不是专业化吗?

在本例中没有,因为代码使用的是称为标记调度的技术。"标签"是完全独立的,通常只是一个空的类struct some_tag {};(但在这种情况下不是(。如果不是这种情况,那么仍然没有,因为过载解析仍然存在,即使双向迭代器可以转换为前向迭代器,仍然存在不需要任何转换的重载,这是一个更好的匹配。

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

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

这称为重载解析(和名称查找,以及该页面顶部链接的其他内容(。

。不是Bidirectional Iter适合Forward Iter

的情况

有点。

您正在结合两件事:

迭代器
  1. 类别之间的(概念(关系(双向迭代器扩展了前向迭代器等,如此处的表格所示(与
  2. 迭代器类别标记之间的关系。

也就是说,从逻辑上讲,你可以说双向迭代器是前向迭代器,std::bidirectional_iterator_tagstd::forward_iterator_tag,并且你的重

Iter partition(Iter first, Iter last, UnaryPredicate pred,
               std::forward_iterator_tag);
Iter partition(Iter first, Iter last, UnaryPredicate pred,
               std::bidirectional_iterator_tag);

是候选者,对于双向迭代器,根据链接页面的隐式转换序列排名部分,第二个重载是更好的匹配(这是一个完全匹配,正如您所期望的那样,这是您可以获得的最好的(。

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