为什么 std::basic_string::substr 不遵循 [begin, end) 约定?

Why doesn't std::basic_string::substr follow the [begin, end) convention?

方法 std::basic_string::substr has the arguments pos, count, specifying the logical range of elements in positions [pos, pos + count + 1). Conversely, most of the standard library functions (for example, std::for_each) 有参数,某种形式类似于 begin, end,指定范围 [begin, end)

这似乎是一个例外,然后,让一些人感到困惑(参见问题here, here, here, and here). Why wasn't the usual range convention used here? Note also that std::vector::erase,另一个随机访问容器的方法,确实遵循通常的惯例。

一个简单的猜测:

您引用的不同方法有不同的行为,这可能就是为什么有些人使用迭代器而有些人不使用的原因。

std::for_each 是通用的 - 拥有适用于任何容器(甚至原始数组)的方法的通用版本的最简单方法是使用迭代器。

std::vector::eraseSequenceContainer 概念的一部分,因此它必须具有可以在任何类型的容器上工作的 "generic" 形式(您可以使用 poscount 表示 std::vector,但是 std::list 呢?或者 std::set?)。拥有这样的概念对于创建通用代码很有用:

template <typename C>
void real_remove(C &c, const typename C::value_type &value) {
     c.erase(std::remove(c.begin(), c.end(), value), c.end());
}

这只有效,因为 std::...::erase 对任何 SequenceContainer 都有明确的定义。

另一方面,std::basic_string::substr 只是 std::basic_string 的一部分(不像 erasestd::vectorstd::list、... ) 和 returns a std::basic_string1(不是迭代器,你在这里用迭代器做什么?)。

std::basic_string 中还有其他 "non-generic"(即某些概念不是强制性的)方法,通常是整个 find 方法家族,insert 有一个用 size_typeappend 等重载。

从主观的角度来看,我认为 std::basic_string 的行为与其他容器不同,因为它不是(我不确定标准是否要求 std::basic_string SequenceContainer 或类似的东西)。

1 你不能在这里使用 return 迭代器,因为你想要一个新的 std::basic_string,所以你会有一个采用迭代器的方法但是return 一个对象...我会发现这比 pos/count 而不是 first/last. 更令人不安

我不能说为什么,我不在那里,但是有一个范围构造函数用于您错过的 [begin, end) 约定。

template< class InputIt >
basic_string( InputIt first, InputIt last,
              const Allocator& alloc = Allocator() );

历史原因。标准库有多个起源,STL 就是其中之一。它带来了 begin,end 约定。 std::string 早于 STL 合并到标准库中,并且有大量现有代码使用了 .substr(pos,length)