【问题标题】:Why isn't std::next/prev templated by distance like std::advance?为什么 std::next/prev 不像 std::advance 那样按距离模板化?
【发布时间】:2026-01-04 20:55:02
【问题描述】:

出于好奇,将模板参数用于std::advance() 的距离类型,但使用迭代器的difference_type 用于std::next()std::prev() 中的距离的基本原理是什么?

为什么不使用相同的方法(任何一种)?

跟进:

默认n = 1 的存在似乎不会阻止nextDistance 模板化,正如answer below 中所建议的那样。这样编译:

#include <iterator>
#include <set>

template<typename InputIt,
    typename Distance = typename std::iterator_traits<InputIt>::difference_type>
InputIt my_next(InputIt it, Distance n = 1)
{
    std::advance(it, n);
    return it;
}

int main()
{
    std::set<int> s;
    my_next(s.begin());
    my_next(s.begin(), 10ul);

    return 0;
}

【问题讨论】:

  • 不是重复的,但与*.com/questions/15017065/…密切相关
  • 我会说“历史”,std::next 来自 C++11,并且具有更强的类型(更改 std::advance 肯定会破坏 ABI 和/或其他复古兼容性问题)。

标签: c++ c++11 iterator


【解决方案1】:

需要能够同时编译std::next(it, n)std::next(it),默认为1:

template<typename InputIt , typename Distance>
InputIt 
next(InputIt it, Distance n = 1)
{
    std::advance(it, n);
    return it;
}

void foo(int *p)
{
    next(p, 1);         // ok
    next<int*, int>(p); // ok
    next(p);  // error: no matching function for call to 'next(int*&)'
}

在 gcc bugzilla 中讨论了解决此重载问题的可能方法:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40497

【讨论】:

  • 我不关注。 std::next 甚至没有第二个模板参数。
  • @cigien 我认为这说明了为什么我们不能有第二个模板参数(它阻止使用默认参数)
  • @Meowmere 我不确定我是否理解。第二个模板参数也可以有一个默认值,比如typename Distance = int,然后这个答案中的next(p) 调用就可以编译得很好。
  • 顺便说一句,它只“回答”一种可能性,std::advance 可能使用difference_type(en.cppreference.com 的可能实现使用它)。