如何定义自定义跨平台 size_t 类型?

Posted

技术标签:

【中文标题】如何定义自定义跨平台 size_t 类型?【英文标题】:How to define a custom cross-platform size_t type? 【发布时间】:2017-11-15 03:48:44 【问题描述】:

std::size_t 通常用于数组索引和循环计数。根据定义,std::size_tsizeof 运算符以及sizeof... 运算符和alignof 运算符(C++11 起)的结果的无符号整数类型。它在以下标题中定义:

<cstddef> <cstdio> <cstdlib> <cstring> <ctime> <cwchar>

据我了解,这些运算符返回的类型是实现定义的。

我想要定义一个自定义size_t,以避免从我的.cpp 文件中的上述任何标题中提取不必要的内容,因为在我的文件中我只需要std::size_t

在 C++11 及更高版本中,我认为我可以使用以下别名:

using size_t = decltype(sizeof(1));

但是,我想以可移植/跨平台的方式为 C++11 之前的编译器定义一个 size_t 类型。

那么有没有一种可移植的方式来为 pre-C++11 定义 size_t

【问题讨论】:

你应该标记这个问题 C++03 或 C++98,而不是 C++11,对吧? 为什么您不想包含任何标准头文件?它们通常不是那么大,不会显着影响编译时间。由于定义了size_t 的那些并没有真正定义任何函数,这意味着也不会为它们生成任何代码。您能否详细说明您想通过这样定义自己的类型来解决的实际问题? cstddef 是一个非常小的标题,就符号而言。拉进去真的是太多命名空间污染了吗? 你可以重新制作boost::typeof 定义自定义类型是否可以避免包含包含标准定义的标头?无论如何,任何标准容器类型都有您可以使用的size_type 【参考方案1】:

理论上,如果列出size_t 的所有可能(未签名)候选人不打扰您,您可以使用 SFINAE:

template <class T, class N = void, bool = sizeof(T) == sizeof(sizeof(T))>
struct TL  
    typedef typename N::type type;
;

template <class T, class N>
struct TL<T, N, true> 
    typedef T type;
;

typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;

[live demo]


编辑:

编译器的解决方法将unsigned longunsigned long long 区分开来,尽管他们假设sizeof(unsigned long) == sizeof(unsigned long long)

template <class U>
U *declptrval(U);

template <class U>
char is_exact(U *);

template <class U>
short is_exact(...);

template <class T, class N = void, bool = sizeof(is_exact<T>(declptrval(sizeof(T))))==sizeof(char)>
struct TL  
    typedef typename N::type type;
;

template <class T, class N>
struct TL<T, N, true> 
    typedef T type;
;

typedef TL<unsigned short,TL<unsigned int, TL<unsigned long, TL<unsigned long long> > > >::type SizeT;

[live demo]

【讨论】:

哥们这是什么魔法?!?!?!?!?! @101010 你可以叫我胡迪尼 ;)【参考方案2】:

据我所知,您列出了获取size_t 的仅有的两种跨平台方法:包括来自标准头文件的定义,或 decltype(C++11 起)。但两者都对您明确不可用。

第三个选项是手动移植,即使用预定义的宏来检测环境,并从手动维护的 typedef 列表中选择正确的 typedef。例如,在 GCC 上,您可以使用 __SIZE_TYPE__(但是,请考虑文档中的警告,即不应直接使用宏,并且并非在所有平台上都提供该宏)。在其他编译器上,您会使用其他东西。

【讨论】:

【参考方案3】:

不幸的是,“实现定义”包括头文件,而不仅仅是编译器本身。如果你查看[expr.sizeof],他们似乎建议只使用这个:

#include <cstddef>

【讨论】:

我知道。我只是指出 C++ 标准有点奇怪,因为它们不需要内置语言特性(如 sizeof 和 typeid)必须由内置类型(不需要包含)支持.

以上是关于如何定义自定义跨平台 size_t 类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据语言重写自定义帖子类型 slug?

自定义结构类型:结构体枚举联合

C语言进阶自定义类型详解(结构体+枚举+联合)

C语言自定义数据类型:结构体,枚举,联合

C语言自定义数据类型:结构体,枚举,联合

C语言自定义数据类型:结构体,枚举,联合