在 <char>sizeof(int) == 1 的平台中如何编码 char_traits::eof() ?
How is char_traits<char>::eof() encoded in platforms where sizeof(int) == 1?
我在C++标准中找到了这些摘录(引自N4687,但它可能永远存在(:
[字符特征.类型定义]
对于某个字符容器类型
char_type
,相关的容器类型INT_T
应为 类型或类,可以表示从相应的char_type
值转换的所有有效字符,以及文件结束值eof()
。
[字符特征要求]
表达式:
X::eof()
类型:
X::int_type
返回:一个值
e
使得X::eq_int_type(e,X::to_int_type(c))
对于所有值c
false
。
表达式:
X::eq_int_type(e,f)
类型:
bool
返回:对于所有
c
和d
,X::eq(c,d)
等于X::eq_int_type(X::to_int_type(c), X::to_int_type(d))
(...
c
和d
表示类型CharT
的值;(...);e
和f
表示类型X::int_type
的值
[字符.特征.专业化.字符]
using char_type = char; using int_type = int;
[基础.基础]
普通
char
、signed char
和unsigned char
是三种不同的类型,统称为窄字符类型。(...)char
、signed char
和unsigned char
占用相同的存储量并具有相同的对齐要求 (...(对于窄字符类型,对象表示形式的所有位都参与值表示形式。(...)对于无符号窄字符类型,值表示形式的每个可能的位模式都表示一个不同的数字。
有五种标准有符号整数类型:"
signed char
"、"short int
"、"int
"、"long int
"和"long long int
"。在此列表中,每种类型提供的存储量至少与列表中前面的存储量相同。
我在周围的文本中没有发现任何阻止sizeof(int) == 1
的东西。在大多数现代平台中,sizeof(int)
显然不是这种情况,其中 是 4 或 8,但明确用作示例,例如在 cpp首选项中:
注意:这允许极端情况,即字节大小为 64 位,所有类型(包括 char(均为 64 位宽,sizeof 为每种类型返回 1。
问题
如果int
和char
一样大,该标准没有为前者的任何对象表示留出太多空间,这些对象表示将不等于后者的所有值(通过to_int_type
(进行比较,只留下一些极端情况(如signed char
中存在的负零,但在int
中映射到INT_MIN
(不太可能在硬件中有效实现。此外,对于 P0907,似乎即使signed char
也不允许任何两个不同的位字符串表示相等的值,从而迫使它为 2^(bitsize( 不同的值,int
也是如此,并关闭了所有可能的漏洞。
在这样的平台上,如何符合std::char_traits<char>
的要求?我们是否有此类平台和相应实现的真实示例?
例如,假设我们有一个平台,其中char
是有符号的,长度为32位,int
也是如此。使用以下定义可以满足所有要求,其中X
std::char_traits<char>
:
X::eq
和X::eq_int
是简单的相等比较;X::to_char_type
返回其参数的值;X::eof
返回 -1,并且X::to_int_type(c)
是c
,除非c
是-1,在这种情况下它是-2。
-1 到 -2 的映射保证了所有c
X::eq_int_type(X::eof(), X::to_int_type(c))
为假,这是根据 C++20 表 69 对X::eof
的要求。
这可能对应于 -1 和 -2(甚至可能是所有负数(是"无效"字符值的实现,即它们存储在char
中是完全合法的,但从文件中读取永远不会产生具有此类值的字节。当然,没有什么能阻止您编写生成此类"无效"值的自定义流缓冲区,只要您愿意接受无法区分"下一个字符是 -1"和"我们在流的末尾"这一事实。
此实现唯一可能的问题是,对X::to_char_type(e)
的要求是它等于
如果对于某些
c
,X::eq_int_type(e,X::to_int_type(c))
是true
,c
;否则是一些未指定的值。
这可以理解为暗示,如果存在任何此类c
,那么它是独一无二的。当e
为 -2 时,将违反该规定,因为此处c
可以是 -1 或 -2。
如果我们假设唯一性是必需的,那么我认为没有任何可能的解决方案。