std::size_t 是不同的类型吗?

Afs*_*hin 27 c++ overloading size-t language-lawyer

C++ 标准提到了这一点std::size_t

该类型size_t实现定义的无符号整数类型,它足够大以包含任何对象的字节大小 ([expr.sizeof])。

现在我的问题是,这种类型是否与其他 unsigned int 类型不同。我的意思是,我是否应该能够有这样的重载:

void myfunc(std::uint16_t) {}
void myfunc(std::uint32_t) {}
void myfunc(std::uint64_t) {}
void myfunc(std::size_t) {}
Run Code Online (Sandbox Code Playgroud)

因为如果它是一个不同的类型,我应该能够拥有这些重载,而如果不是,我应该得到重新定义错误。我总是认为这std::size_t应该是一个不同的类型,但我目前收到重新定义错误,这意味着它不是(至少在 GCC 和 Clang 中)

我问这个问题的原因是我想知道我是否对不同的 unsigned int 大小重载了一个函数,我是否可以安全地假设其中一个将被调用std::size_t或不被调用。

use*_*522 16

现在我的问题是,这种类型是否与其他 unsigned int 类型不同。

您的问题在很大程度上取决于您对“ unsigned int types ”的确切含义。我假设这是指标准定义的“无符号整数类型”。

它不能是与其他无符号整数类型不同的类型。所有无符号整数类型都在[basic.fundamental]/2中专门列出。这些是标准无符号整数类型 unsigned charunsigned shortunsigned intunsigned longunsigned long long,以及扩展无符号整数类型(如果实现定义了任何类型)(在最常见的 C++ 实现中通常不是这种情况)。

如果您打算“ unsigned int types ”引用上面列出的标准无符号整数类型,那么答案就变成size_t既不要求也不禁止成为其中之一,因为它也可能是扩展无符号整数类型之一。但如果实现没有这些,那么它必须是标准无符号整数类型之一。

如果您希望“ unsigned int types ”表示标准中定义的任何也具有无符号符号性的“整数类型” ,那么答案又是它不能与该集合不同,因为该集合仅仅是该集合的超集所有无符号整数类型,添加,,以及可能的和(具有实现定义的符号)。char8_tchar16_tchar32_tcharwchar_t

(您可以在我上面链接的后 C++20 ISO C++ 草案 N4868 的 [basic.fundamental]/1 到 11 中的标准中找到所有提到的术语的定义。)


因为如果它是一个不同的类型,我应该能够拥有这些重载,而如果不是,我应该得到重新定义错误。

不管上述情况如何,都不能保证会导致重新定义错误,因为虽然类型uint16_tuint32_tuint64_t也必须是来自同一类别的无符号整数类型,但它们不必覆盖整个类别,事实上也不能覆盖整个类别,因为有至少 5 个无符号整数类型,但您只列出了三个uintX_t重载。因此size_t不需要匹配其中任何一个,事实上根本不需要匹配任何一个uintX_t

例如,在 64 位体系结构上,通常uint16_tunsigned shortuint32_tunsigned intuint64_tunsigned longunsigned long long,其余一个不被任何别名uintX_t

所以超载设置是不安全的。size_t可以是其中之一uintX_t,也可以不是,并且既不是整个uintX_t集合,也不是整个集合(包括size_t必须覆盖所有无符号整数类型的集合)。

如果要重载所有无符号整数类型,请按上面列出的标准无符号整数类型的实际(非别名)类型名称以及所有扩展无符号整数类型(如果您的实现有它们)进行重载。但是,请考虑可能受类型特征约束的模板是否不是更好的选择,因为您无法移植地了解扩展整数类型。

  • @Afshin“_我找不到一种方法来声明它不能是不同的类型。_”:我链接了 ISO C++ 标准草案中的段落,使其不可能。“_作为例外,char 是一种不同的类型_”:是的,链接部分中也详细说明了这一点。`char` 永远不是_无符号整数类型_,即使它是无符号的。 (2认同)

Vla*_*cow 6

C++ 头<cstddef>实际上与 C 相同<stddef.h>

来自 C++17 标准

1 头文件的内容和含义与 C 标准库头文件 <stdlib.h> 相同,只是它没有声明类型 wchar_t,以及 21.2.3、21.2.4、21.5、23.10 中所述的除外。 11、24.5.6、28.8、29.6.9 和 29.9.2。

在 C 中,名称 size_t 被定义为宏

7.19 通用定义<stddef.h>

1 头文件 <stddef.h> 定义以下宏并声明以下类型。有些还在其他标头中定义,如其各自的子条款中所述。2 类型有

ptrdiff_t 
Run Code Online (Sandbox Code Playgroud)

这是两个指针相减结果的有符号整数类型;

size_t
Run Code Online (Sandbox Code Playgroud)

这是 sizeof 运算符结果的无符号整数类型;

通常size_t被定义为类型的别名unsigned long

4 用于 size_t 和 ptrdiff_t 的类型的整数转换等级不应大于有符号长整型,除非实现支持足够大的对象以使其必要

  • `std::size_t` 不是宏 (3认同)
  • 引用是*定义以下宏**和**声明以下类型*是说类型声明与该标头中定义的 CPP 宏是分开的。“and”用于分隔两件事,而不是告诉您类型是如何声明的。正常实现使用“typedef”来定义类型,因此您不能像@RM所说的“#undef size_t”。例如,GCC 的“stddef.h”在一些“#ifdef”内容之后使用“typedef __SIZE_TYPE__ size_t;”来确定要选择的类型。 (3认同)