std::string::npos == -1 总是正确的吗?
Is std::string::npos == -1 always true?
标题相对不言自明。我认识到与其他答案的相似性,但所有这些都有不同的运算符安排(因此有不同的转换规则)。所以我需要一个澄清这个特殊情况的答案。
如果有人能指出解释这一点的标准部分,我会很乐意投票并接受答案。
是的,定义为-1
N4296 § 21.4 / 5 为 std::basic_string
提供了 class 模板,其中包括行
static const size_type npos = -1;
你问的问题有漏洞
如果 int
的整数转换等级(严格)大于 string::size_type
并且 int
可以存储 string::size_type
的全部值范围,则 string::npos == -1
将为假,因为两个参数都将提升为 int
,而不是提升为 string::size_type
.
发生这种情况的环境会很不寻常。
这来自通常的算术转换:
...
Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the
rank of the type of the other operand, the operand with signed integer type shall be converted to
the type of the operand with unsigned integer type
Otherwise, if the type of the operand with signed integer type can represent all of the values of
the type of the operand with unsigned integer type, the operand with unsigned integer type shall
be converted to the type of the operand with signed integer type.
Otherwise, both operands shall be converted to the unsigned integer type corresponding to the
type of the operand with signed integer type.
NO,并不总是如此。然而,它比乍看起来要复杂一些:
首先让我们看看std::string
是什么(21.3/1):
The header <string>
defines the basic_string
class template for manipulating varying-length sequences
of char-like objects and four typedefs, string
, u16string
, u32string
, and wstring
, that name the specializations
basic_string<char>
, basic_string<char16_t>
, basic_string<char32_t>
, and basic_string<wchar_t>
, respectively.
从 21.4/5 开始:
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;
// [other members omitted]
};
请注意,虽然 npos
是用 -1
初始化的,但它的类型取决于 Allocator::size_type
,这意味着在没有进一步了解的情况下,我们不能简单地假设 string::npos == -1
将甚至编译。
现在,由于string
使用了默认分配器(模板参数毕竟在标准库提供的typedef中有默认值),让我们检查20.6.9:
typedef size_t size_type;
现在,我们基本上可以将问题重写为:size_t(-1) == -1
。现在发生的情况取决于子表达式的类型:左侧显然是 size_t
类型,而右侧是一个整型字面量,它的类型是 int
,当这样写时(没有进一步的预选赛)。
如果 size_t
至少与 int
一样大(对于标准狂热者:具有更大的整数转换等级,如 4.13 中所定义),则结果为 true
。否则,左侧 将提升为 int
,导致像 0xFFFF == -1
这样的比较(因为 size_t
是 uint16_t
和 int
有 32 位),即 false
.
请注意,虽然 16 位系统本身不再很常见(除了一些非常小的残余),int
标准并不限制为 32 位。以 64
位 size_t
和 128 位 int
为目标的编译器在技术上是兼容的。
所有引用均来自 C++11 标准 (ISO/IEC 14882:2011)。
标题相对不言自明。我认识到与其他答案的相似性,但所有这些都有不同的运算符安排(因此有不同的转换规则)。所以我需要一个澄清这个特殊情况的答案。
如果有人能指出解释这一点的标准部分,我会很乐意投票并接受答案。
是的,定义为-1
N4296 § 21.4 / 5 为 std::basic_string
提供了 class 模板,其中包括行
static const size_type npos = -1;
你问的问题有漏洞
如果 int
的整数转换等级(严格)大于 string::size_type
并且 int
可以存储 string::size_type
的全部值范围,则 string::npos == -1
将为假,因为两个参数都将提升为 int
,而不是提升为 string::size_type
.
发生这种情况的环境会很不寻常。
这来自通常的算术转换:
...
Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type
Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.
Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
NO,并不总是如此。然而,它比乍看起来要复杂一些:
首先让我们看看std::string
是什么(21.3/1):
The header
<string>
defines thebasic_string
class template for manipulating varying-length sequences of char-like objects and four typedefs,string
,u16string
,u32string
, andwstring
, that name the specializationsbasic_string<char>
,basic_string<char16_t>
,basic_string<char32_t>
, andbasic_string<wchar_t>
, respectively.
从 21.4/5 开始:
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; // [other members omitted] };
请注意,虽然 npos
是用 -1
初始化的,但它的类型取决于 Allocator::size_type
,这意味着在没有进一步了解的情况下,我们不能简单地假设 string::npos == -1
将甚至编译。
现在,由于string
使用了默认分配器(模板参数毕竟在标准库提供的typedef中有默认值),让我们检查20.6.9:
typedef size_t size_type;
现在,我们基本上可以将问题重写为:size_t(-1) == -1
。现在发生的情况取决于子表达式的类型:左侧显然是 size_t
类型,而右侧是一个整型字面量,它的类型是 int
,当这样写时(没有进一步的预选赛)。
如果 size_t
至少与 int
一样大(对于标准狂热者:具有更大的整数转换等级,如 4.13 中所定义),则结果为 true
。否则,左侧 将提升为 int
,导致像 0xFFFF == -1
这样的比较(因为 size_t
是 uint16_t
和 int
有 32 位),即 false
.
请注意,虽然 16 位系统本身不再很常见(除了一些非常小的残余),int
标准并不限制为 32 位。以 64
位 size_t
和 128 位 int
为目标的编译器在技术上是兼容的。
所有引用均来自 C++11 标准 (ISO/IEC 14882:2011)。