为啥 std::basic_string::substr 不遵循 [begin, end) 约定?
Posted
技术标签:
【中文标题】为啥 std::basic_string::substr 不遵循 [begin, end) 约定?【英文标题】:Why doesn't std::basic_string::substr follow the [begin, end) convention?为什么 std::basic_string::substr 不遵循 [begin, end) 约定? 【发布时间】:2016-09-28 05:50:50 【问题描述】:方法std::basic_string::substr
有参数pos, count
,指定位置元素的逻辑范围[pos, pos + count + 1)。相反,大多数标准库函数(例如,std::for_each
)都有参数,其形式类似于begin, end
,指定范围[begin, end)
这似乎是一个例外,因此,有些人会感到困惑(请参阅问题here、here、here 和here)。为什么这里没有使用通常的范围约定?另请注意,std::vector::erase
,另一个随机访问容器的方法,确实遵循通常的约定。
【问题讨论】:
您可以通过使用 contrustor 获得相同的行为。例如。std::string substringtext.begin(), text.end()
。不知道为什么substr
没有这么重载。
@Zereges:因为它是多余的。如果您有两个表示子字符串的迭代器,如果您也可以将它们传递给 std::string::string()
,为什么还要将它们传递给 std::string::substr()
重载。
@MSalters STL 中有很多冗余的重载甚至函数。 STL 的设计初衷不是简约。
【参考方案1】:
历史原因。标准库有多个来源,其中之一是 STL。它带来了begin,end
约定。 std::string
早于 STL 并入标准库之前,有很多现有代码使用 .substr(pos,length)
。
【讨论】:
...我想如果我们现在设计这个库,std::string
看起来会很不一样。【参考方案2】:
一个简单的猜测:
您引用的不同方法具有不同的行为,这可能就是为什么有些使用迭代器而有些不使用的原因。
std::for_each
是通用的 - 拥有适用于任何容器(甚至原始数组)的通用版本的方法的最简单方法是使用迭代器。
std::vector::erase
是SequenceContainer 概念的一部分,因此它必须有一个可以在任何类型的容器上工作的“通用”表单(您可以使用pos
和count
来表示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
的一部分(与erase
不同,它是std::vector
、std::list
的一部分...)并返回std::basic_string
1(不是迭代器,你会在这里用迭代器做什么?)。
std::basic_string
中还有其他“非泛型”(即某些概念不强制)方法,通常是整个 find
方法家族,insert
具有 size_type
、@987654341 的重载@,等等。
从主观角度来看,我认为最好有一个与其他容器不同的 std::basic_string
,因为它不是(我不确定标准是否要求 std::basic_string
是 SequenceContainer
或任何东西一样)。
1 你不能在这里返回迭代器,因为你想要一个新的std::basic_string
,所以你会有一个采用迭代器但返回一个对象的方法......我会觉得这更令人不安而不是pos
/count
而不是first
/last
。
【讨论】:
【参考方案3】:我不知道为什么,我不在那里,但是您错过了 [begin, end) 约定的范围构造函数。
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
【讨论】:
以上是关于为啥 std::basic_string::substr 不遵循 [begin, end) 约定?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?