C++标准是否保证std::basic_string::npos + 1 == 0?

7

我希望消除算法中的特殊情况,为此我想确保std :: string :: npos + 1 等于 0

在我测试过的所有实现中都是正确的,并且在标准中搜索后,我发现了以下内容:

namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
    // ...
    typedef typename allocator_traits<Allocator>::size_type size_type;
    // ...
    static const size_type npos = -1;
    ...
  };
}

allocator_traits<Allocator>::size_type 被定义为一个无符号整数类型。

因此,我想知道,对于无符号整数类型T,(static_cast<T>(-1)) + 1 是否总是返回 0


1
numeric_limits<T>::max是什么? - Neil Kirk
3
在C++11中,您可以使用static_assert (std::string::npos + 1 == 0, "bizarre string::npos")语句。 - Basile Starynkevitch
1
@NeilKirk 我从另一个算法中收到了npos,所以如果pos == npos,我想要折叠t = std::string()的情况,否则返回s.substr(0, pos + 1) - dottedmag
2
可能是的,但编译器会将其优化为无效代码,这对下一个要处理你的代码的人类程序员来说是一个有用的提醒。 - Basile Starynkevitch
@BasileStarynkevitch 非常好的观点,谢谢。 - dottedmag
显示剩余3条评论
1个回答

5
不,给无符号整数类型的最大值加一并不能保证得到零。
如果`size_type`被定义为`unsigned short`,而`int`比`unsigned short`更宽,你的加法的左操作数将被转换为右操作数,并且您依赖于在左操作数的类型中执行加法。
更糟糕的是,但这极少发生,如果`unsigned short`的值位与`int`恰好相同,则加法将溢出并导致未定义的行为。
然而,您可以添加`1U`,并将加法的结果转换回`T`。这应该在常见实现上生成完全相同的代码,但对于所有实现都保证有效。

如果 sizeof(std::string::size_type) >= sizeof(int),则升级将为 unsigned 并且行为是有保证的。第三段 更糟糕的是,但是…… 是不正确的。 - David Rodríguez - dribeas
1
那是一个特殊情况,适用于小于 int 大小的尺寸。 - M.M
要准确地说,如果std::string::size_type的最大值大于int的最大值。是的,在这种情况下,加法将保证计算为零。至于“更糟糕的是”部分,有什么不正确的地方吗?(请记住,符号位不算作值位之一。我谈论的是一个实现,其中USHORT_MAX == INT_MAX,正如我所指出的那样,这非常不可能,但完全有效。) - user743382

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接