标准C++中是否存在size_t的有符号变体?意味着与size_t完全相同的位大小,但有符号。
我当然可以:
#include <type_traits>
using signed_size_t = std::make_signed_t<std::size_t>;
但也许在标准库中已经有了类似的定义,而不是发明额外的类型名称?
我知道有ssize_t和ptrdiff_t,它们都有签名。但根据他们的描述,它们似乎都可以具有与size_t不同的比特大小。但我需要和size_t完全相同的位大小,但要签名。
有一个地方;CCD_ 1"的签名版本;(以及std::ptrdiff_t
的无符号版本(出现在标准中:printf
格式说明符%zu
用于std::size_t
对象。%zd
用于对象,正如C++标准所指的C标准所说;相应的有符号整数类型[CCD_ 7]";
std::printf("%zu %zd %td %tu",
std::size_t{0}, std::make_signed_t<std::size_t>{0},
std::ptrdiff_t{0}, std::make_unsigned_t<std::ptrdiff_t>{0}
);
由于没有专门为%zd
和%tu
命名的类型,我倾向于相信没有你想要的标准名称(除了std::size_t
0(。
顺便说一句,没有太多理由想要std::size_t
的签名变体:std::size_t
是针对对象的大小,而对象的大小没有签名。
CCD_ 13仅保证保持CCD_ 14或非负值。它的保证范围是[-1, SSIZE_MAX]
(并且是特定于POSIX的类型,而不是标准的C++类型(。这是因为它用于";无符号值或出现错误时为-1";。
C++标准库仅使用std::size_t
,而使用std::size_t(-1) == SIZE_MAX
来指示错误/特殊值(请参见:std::basic_string<...>::npos
、std::dynamic_extent
(,因此如果您想要一个错误值(或者可能是std::optional<std::size_t>
(,则可以使用std::size_t
而不是ssize_t
如果你想要";表示大小但带有符号的"某物";,std::ssize(c)
("有符号的size
"(返回std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>
。对于数组类型,std::ssize
返回std::ptrdiff_t
。因此,可能使用std::ptrdiff_t
来实现此目的。
如果你想要";用于表示两个迭代器之间的距离的类型";(包括指针(,为此制作了std::ptrdiff_t
。这与有符号大小的概念基本一致,std::iterator_traits<...>::difference_type
通常是std::ptrdiff_t
。
这些并不意味着sizeof(std::ptrdiff_t) == sizeof(std::size_t)
。该标准没有定义它们之间的任何关系。sizeof(std::ptrdiff_t) < sizeof(std::size_t)
和sizeof(std::ptrdiff_t) > sizeof(std::size_t)
在理论上似乎都是可能的,但我还没有发现任何系统存在这种情况。因此,一个简单的断言应该适用于所有平台,并允许您只使用std::ptrdiff_t
:
static_assert(
sizeof(std::size_t) == sizeof(std::ptrdiff_t) &&
static_cast<std::size_t>(std::numeric_limits<std::ptrdiff_t>::max()) == std::numeric_limits<std::size_t>::max() / 2u,
"ptrdiff_t and size_t are not compatible"
);
(有许多系统的std::size_t
是unsigned int
,std::ptrdiff_t
是signed long
但sizeof(int) == sizeof(long)
,所以我们必须检查类型的范围,而不是std::is_same_v<std::ptrdiff_t, std::make_signed_t<std::size_t>>
(
或者像您已经拥有的一样使用std::make_signed_t<std::size_t>
。