标准C++库中size_t的有符号变体



标准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_t0(。


顺便说一句,没有太多理由想要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<...>::nposstd::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_tunsigned intstd::ptrdiff_tsigned longsizeof(int) == sizeof(long),所以我们必须检查类型的范围,而不是std::is_same_v<std::ptrdiff_t, std::make_signed_t<std::size_t>>(

或者像您已经拥有的一样使用std::make_signed_t<std::size_t>

相关内容

  • 没有找到相关文章

最新更新